AI translate refactor

This commit is contained in:
Mazyar
2026-05-16 12:56:10 +03:30
parent ca490f3acf
commit 6701428b09
10 changed files with 510 additions and 166 deletions
+80 -11
View File
@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"net/http"
"strings"
"time"
"tm/pkg/logger"
@@ -93,8 +94,9 @@ func (c *Client) FetchTranslationOnDemand(ctx context.Context, reqBody Translate
for attempt := 0; attempt <= c.config.APIRetryCount; attempt++ {
if attempt > 0 {
c.logger.Warn("Retrying AI translate request", map[string]interface{}{
"notice_id": reqBody.NoticeID,
"attempt": attempt,
"notice_publication_id": reqBody.NoticePublicationID,
"language": reqBody.Language,
"attempt": attempt,
})
select {
case <-ctx.Done():
@@ -107,9 +109,10 @@ func (c *Client) FetchTranslationOnDemand(ctx context.Context, reqBody Translate
if err != nil {
lastErr = err
c.logger.Error("AI translate request failed", map[string]interface{}{
"notice_id": reqBody.NoticeID,
"attempt": attempt,
"error": err.Error(),
"notice_publication_id": reqBody.NoticePublicationID,
"language": reqBody.Language,
"attempt": attempt,
"error": err.Error(),
})
continue
}
@@ -120,6 +123,50 @@ func (c *Client) FetchTranslationOnDemand(ctx context.Context, reqBody Translate
return nil, fmt.Errorf("ai_summarizer: all %d translation attempts failed, last error: %w", c.config.APIRetryCount+1, lastErr)
}
// TriggerPipelineTranslate calls POST /pipeline/translate to enqueue batch translation
// for the given target languages.
func (c *Client) TriggerPipelineTranslate(ctx context.Context, languages []string) (*PipelineTranslateResponse, error) {
reqBody := PipelineTranslateRequest{Languages: languages}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to marshal pipeline translate request: %w", err)
}
url := c.config.APIBaseURL + "/pipeline/translate"
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(jsonBody))
if err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to create pipeline translate request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
httpResp, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("ai_summarizer: pipeline translate request error: %w", err)
}
defer httpResp.Body.Close()
bodyBytes, err := io.ReadAll(httpResp.Body)
if err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to read pipeline translate response: %w", err)
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
}
var result PipelineTranslateResponse
if err := json.Unmarshal(bodyBytes, &result); err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to decode pipeline translate response: %w", err)
}
c.logger.Info("Pipeline translate triggered", map[string]interface{}{
"status": result.Status,
"languages": result.Languages,
})
return &result, nil
}
// doPost performs a single POST request and parses the response.
func (c *Client) doPost(ctx context.Context, url string, jsonBody []byte) (*SummarizeResponse, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(jsonBody))
@@ -193,15 +240,37 @@ func (c *Client) doTranslatePost(ctx context.Context, url string, jsonBody []byt
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
}
var result TranslateResponse
if err := json.Unmarshal(bodyBytes, &result); err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to decode translation response JSON: %w", err)
result, err := decodeTranslateResponse(bodyBytes)
if err != nil {
return nil, err
}
c.logger.Info("AI translate request succeeded", map[string]interface{}{
"notice_id": result.NoticeID,
"language": result.Language,
"notice_publication_id": result.NoticePublicationID,
"language": result.Language,
})
return &result, nil
return result, nil
}
type translateAPIEnvelope struct {
Success bool `json:"success"`
Message string `json:"message"`
Data TranslateResponse `json:"data"`
}
func decodeTranslateResponse(bodyBytes []byte) (*TranslateResponse, error) {
var envelope translateAPIEnvelope
if err := json.Unmarshal(bodyBytes, &envelope); err == nil && envelope.Success && envelope.Data.Language != "" {
return &envelope.Data, nil
}
var direct TranslateResponse
if err := json.Unmarshal(bodyBytes, &direct); err != nil {
return nil, fmt.Errorf("ai_summarizer: failed to decode translation response JSON: %w", err)
}
if strings.TrimSpace(direct.Language) == "" {
return nil, fmt.Errorf("ai_summarizer: translation response missing language")
}
return &direct, nil
}