tender summary refactor

This commit is contained in:
Mazyar
2026-05-19 19:03:50 +03:30
parent 92d4b14b33
commit fcf2cae6bc
3 changed files with 41 additions and 25 deletions
+25 -9
View File
@@ -156,6 +156,8 @@ func languageInDone(done []string, language string) bool {
// TenderJSON represents the structure of the <notice_id>/tender.json file // TenderJSON represents the structure of the <notice_id>/tender.json file
// stored in the AI service's MinIO bucket. // stored in the AI service's MinIO bucket.
type TenderJSON struct { type TenderJSON struct {
// Summary is the current pipeline field for the tender-level summary text.
Summary string `json:"summary"`
OverallSummary *string `json:"overall_summary"` OverallSummary *string `json:"overall_summary"`
OverallSummaryCamel *string `json:"overallSummary"` OverallSummaryCamel *string `json:"overallSummary"`
SummarizeStatus SummarizeStatus `json:"summarize_status"` SummarizeStatus SummarizeStatus `json:"summarize_status"`
@@ -165,16 +167,30 @@ type TenderJSON struct {
TranslationStatusCamel TranslationStatus `json:"translationStatus"` TranslationStatusCamel TranslationStatus `json:"translationStatus"`
} }
// resolved returns whether summarization is marked done and the best-effort // summaryText returns the best-effort tender-level summary (may be empty).
// overall summary pointer (may be nil or empty when the pipeline finished func (t *TenderJSON) summaryText() string {
// without text yet). if t == nil {
func (t *TenderJSON) resolved() (done bool, overall *string) { return ""
done = t.SummarizeStatus.isDone() || t.SummarizeStatusCamel.isDone()
overall = t.OverallSummary
if overall == nil || strings.TrimSpace(*overall) == "" {
overall = t.OverallSummaryCamel
} }
return done, overall for _, candidate := range []*string{t.OverallSummary, t.OverallSummaryCamel} {
if candidate == nil {
continue
}
if text := strings.TrimSpace(*candidate); text != "" {
return text
}
}
return strings.TrimSpace(t.Summary)
}
// resolved returns whether summarization is marked done and the summary text
// (may be empty when the pipeline finished without text yet).
func (t *TenderJSON) resolved() (done bool, overall string) {
if t == nil {
return false, ""
}
done = t.SummarizeStatus.isDone() || t.SummarizeStatusCamel.isDone()
return done, t.summaryText()
} }
// SummarizeStatus represents the summarization status inside tender.json. // SummarizeStatus represents the summarization status inside tender.json.
+2 -2
View File
@@ -9,8 +9,8 @@ var (
ErrSummaryNotReady = errors.New("ai_summarizer: summary not ready yet") ErrSummaryNotReady = errors.New("ai_summarizer: summary not ready yet")
// ErrNoOverallSummary is returned when the pipeline is done but // ErrNoOverallSummary is returned when the pipeline is done but
// overall_summary is empty or null. // summary / overall_summary text is empty.
ErrNoOverallSummary = errors.New("ai_summarizer: overall_summary is empty") ErrNoOverallSummary = errors.New("ai_summarizer: tender summary is empty")
// ErrTranslationNotReady is returned when tender.json exists but the // ErrTranslationNotReady is returned when tender.json exists but the
// requested language is not listed in translation_status.done yet. // requested language is not listed in translation_status.done yet.
+8 -8
View File
@@ -278,13 +278,15 @@ func (s *StorageClient) resolveNoticeStoragePrefix(ctx context.Context, contract
// GetSummaryFromStorage fetches the // GetSummaryFromStorage fetches the
// PROC_<contractFolderID>/<noticePublicationID>/tender.json file from the AI // PROC_<contractFolderID>/<noticePublicationID>/tender.json file from the AI
// service's MinIO bucket, parses it, and returns the overall_summary string. // service's MinIO bucket, parses it, and returns the tender summary text.
//
// Summary text is read from summary (current) or overall_summary (legacy).
// //
// It returns: // It returns:
// - (summary, nil) on success // - (summary, nil) on success
// - ("", ErrObjectNotFound) if the tender.json does not exist (404) // - ("", ErrObjectNotFound) if the tender.json does not exist (404)
// - ("", ErrSummaryNotReady) if the file exists but summarize_status.done is false // - ("", ErrSummaryNotReady) if the file exists but summarize_status.done is false
// - ("", ErrNoOverallSummary) if done is true but overall_summary is empty/null // - ("", ErrNoOverallSummary) if done is true but summary text is empty
// - ("", error) for any other failure // - ("", error) for any other failure
func (s *StorageClient) GetSummaryFromStorage(ctx context.Context, contractFolderID, noticePublicationID string) (string, error) { func (s *StorageClient) GetSummaryFromStorage(ctx context.Context, contractFolderID, noticePublicationID string) (string, error) {
if strings.TrimSpace(contractFolderID) == "" { if strings.TrimSpace(contractFolderID) == "" {
@@ -352,7 +354,7 @@ func (s *StorageClient) getTranslationFromObjectKey(ctx context.Context, objectK
return entry, nil return entry, nil
} }
// getSummaryFromObjectKey reads tender.json at objectKey and returns overall_summary when ready. // getSummaryFromObjectKey reads tender.json at objectKey and returns summary text when ready.
// contractFolderID and noticePublicationID are used for logging only (may be empty when unknown). // contractFolderID and noticePublicationID are used for logging only (may be empty when unknown).
func (s *StorageClient) readTenderJSONAtKey(ctx context.Context, objectKey string) (*TenderJSON, error) { func (s *StorageClient) readTenderJSONAtKey(ctx context.Context, objectKey string) (*TenderJSON, error) {
object, err := s.client.GetObject(ctx, s.config.MinioBucket, objectKey, minio.GetObjectOptions{}) object, err := s.client.GetObject(ctx, s.config.MinioBucket, objectKey, minio.GetObjectOptions{})
@@ -403,17 +405,15 @@ func (s *StorageClient) getSummaryFromObjectKey(ctx context.Context, objectKey,
return "", err return "", err
} }
done, overall := tenderJSON.resolved() done, summaryText := tenderJSON.resolved()
if !done { if !done {
return "", ErrSummaryNotReady return "", ErrSummaryNotReady
} }
if overall == nil || strings.TrimSpace(*overall) == "" { if summaryText == "" {
return "", ErrNoOverallSummary return "", ErrNoOverallSummary
} }
summaryText := strings.TrimSpace(*overall) s.logger.Info("Retrieved tender summary from storage", map[string]interface{}{
s.logger.Info("Retrieved overall_summary from storage", map[string]interface{}{
"contract_folder_id": contractFolderID, "contract_folder_id": contractFolderID,
"notice_id": noticePublicationID, "notice_id": noticePublicationID,
"object_key": objectKey, "object_key": objectKey,