Implement AI onboarding and recommendation features in company service
- Added new AI onboarding and recommendation endpoints in the company handler for starting onboarding and retrieving ranked tender recommendations. - Introduced `StartAIOnboarding` and `GetAIRecommendations` methods in the company service to handle AI interactions. - Updated the company service constructor to include the AI recommendation client. - Enhanced the AI summarizer client with methods for onboarding and fetching recommendations. - Added response structures for onboarding and recommended tenders in the company form. This update enhances the tender management system by integrating AI capabilities for onboarding and tender recommendations, improving user experience and operational efficiency.
This commit is contained in:
@@ -209,6 +209,72 @@ func (c *Client) TriggerPipelineSummarize(ctx context.Context) (*PipelineActionR
|
||||
return c.triggerPipelineAction(ctx, "/pipeline/summarize", "pipeline summarize")
|
||||
}
|
||||
|
||||
// StartOnboarding calls POST /onboarding to start company profile indexing for recommendations.
|
||||
func (c *Client) StartOnboarding(ctx context.Context, reqBody OnboardingRequest) (*OnboardingResponse, error) {
|
||||
jsonBody, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to marshal onboarding request body: %w", err)
|
||||
}
|
||||
|
||||
url := c.config.APIBaseURL + "/onboarding"
|
||||
httpResp, bodyBytes, err := c.doRawPost(ctx, url, jsonBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer httpResp.Body.Close()
|
||||
|
||||
if httpResp.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
var result OnboardingResponse
|
||||
if len(bodyBytes) > 0 {
|
||||
if err := json.Unmarshal(bodyBytes, &result); err != nil {
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to decode onboarding response: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
c.logger.Info("AI onboarding request succeeded", map[string]interface{}{
|
||||
"company_id": reqBody.CompanyID,
|
||||
"status": result.Status,
|
||||
})
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// FetchRecommendations calls POST /recommend to retrieve ranked tenders for a company.
|
||||
func (c *Client) FetchRecommendations(ctx context.Context, reqBody RecommendRequest) ([]RecommendedTender, error) {
|
||||
jsonBody, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to marshal recommend request body: %w", err)
|
||||
}
|
||||
|
||||
url := c.config.APIBaseURL + "/recommend"
|
||||
httpResp, bodyBytes, err := c.doRawPost(ctx, url, jsonBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer httpResp.Body.Close()
|
||||
|
||||
if httpResp.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
var result []RecommendedTender
|
||||
if len(bodyBytes) > 0 {
|
||||
if err := json.Unmarshal(bodyBytes, &result); err != nil {
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to decode recommend response: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
c.logger.Info("AI recommend request succeeded", map[string]interface{}{
|
||||
"company_id": reqBody.CompanyID,
|
||||
"count": len(result),
|
||||
})
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Client) triggerPipelineAction(ctx context.Context, path, label string) (*PipelineActionResponse, error) {
|
||||
url := c.config.APIBaseURL + path
|
||||
httpResp, bodyBytes, err := c.doRawPost(ctx, url, nil)
|
||||
|
||||
@@ -138,6 +138,30 @@ type PipelineActionResponse struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// OnboardingRequest is the payload for POST /onboarding.
|
||||
type OnboardingRequest struct {
|
||||
CompanyID string `json:"company_id"`
|
||||
Documents string `json:"documents"`
|
||||
WebsiteURL string `json:"website_url"`
|
||||
}
|
||||
|
||||
// OnboardingResponse is returned by POST /onboarding.
|
||||
type OnboardingResponse struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// RecommendRequest is the payload for POST /recommend.
|
||||
type RecommendRequest struct {
|
||||
CompanyID string `json:"company_id"`
|
||||
}
|
||||
|
||||
// RecommendedTender is one ranked tender from POST /recommend.
|
||||
type RecommendedTender struct {
|
||||
Rank string `json:"rank"`
|
||||
TenderID string `json:"tender_id"`
|
||||
Analysis string `json:"analysis"`
|
||||
}
|
||||
|
||||
// StoredTranslation is one language entry inside tender.json translations map.
|
||||
type StoredTranslation struct {
|
||||
Title string `json:"title"`
|
||||
|
||||
Reference in New Issue
Block a user