Enhance logging and error handling in configuration loading, content fetching, and AI reply generation

This commit is contained in:
2025-03-01 05:22:45 +01:00
parent f349057975
commit 459422bc60
4 changed files with 216 additions and 16 deletions

View File

@@ -6,6 +6,9 @@ import (
"fmt"
"net/http"
"paraclub-ai-mailer/config"
"paraclub-ai-mailer/internal/logger"
"github.com/sirupsen/logrus"
)
type AI struct {
@@ -41,10 +44,19 @@ func New(cfg config.AIConfig) *AI {
}
func (a *AI) GenerateReply(emailContent string, contextContent map[string]string) (string, error) {
logger.WithFields(logrus.Fields{
"emailContentLength": len(emailContent),
"contextUrls": len(contextContent),
}).Debug("Starting AI reply generation")
// Prepare context from all URLs
var context string
for url, content := range contextContent {
context += fmt.Sprintf("\nContext from %s:\n%s\n", url, content)
logger.WithFields(logrus.Fields{
"url": url,
"contentLength": len(content),
}).Debug("Added context from URL")
}
// Prepare the system message and user message
@@ -64,6 +76,8 @@ func (a *AI) GenerateReply(emailContent string, contextContent map[string]string
var lastErr error
for attempt := 0; attempt < maxRetries; attempt++ {
logger.WithField("attempt", attempt+1).Debug("Making API request attempt")
reqBody := OpenRouterRequest{
Model: a.config.Model,
Messages: messages,
@@ -71,13 +85,21 @@ func (a *AI) GenerateReply(emailContent string, contextContent map[string]string
MaxTokens: a.config.MaxTokens,
}
logger.WithFields(logrus.Fields{
"model": reqBody.Model,
"temperature": reqBody.Temperature,
"maxTokens": reqBody.MaxTokens,
}).Debug("Prepared API request")
jsonData, err := json.Marshal(reqBody)
if err != nil {
logger.WithError(err).Error("Failed to marshal request body")
return "", err
}
req, err := http.NewRequest("POST", "https://openrouter.ai/api/v1/chat/completions", bytes.NewBuffer(jsonData))
if err != nil {
logger.WithError(err).Error("Failed to create HTTP request")
return "", err
}
@@ -86,29 +108,51 @@ func (a *AI) GenerateReply(emailContent string, contextContent map[string]string
resp, err := a.client.Do(req)
if err != nil {
logger.WithFields(logrus.Fields{
"error": err,
"attempt": attempt + 1,
}).Debug("API request failed, will retry")
lastErr = err
continue
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
logger.WithFields(logrus.Fields{
"statusCode": resp.StatusCode,
"attempt": attempt + 1,
}).Debug("API returned non-200 status code")
lastErr = fmt.Errorf("OpenRouter API returned status code: %d", resp.StatusCode)
continue
}
var result OpenRouterResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
logger.WithFields(logrus.Fields{
"error": err,
"attempt": attempt + 1,
}).Debug("Failed to decode API response")
lastErr = err
continue
}
if len(result.Choices) == 0 || result.Choices[0].Message.Content == "" {
logger.WithField("attempt", attempt+1).Debug("Received empty response from API")
lastErr = fmt.Errorf("empty response received")
continue
}
responseLength := len(result.Choices[0].Message.Content)
logger.WithFields(logrus.Fields{
"attempt": attempt + 1,
"responseLength": responseLength,
}).Debug("Successfully generated AI reply")
return result.Choices[0].Message.Content, nil
}
logger.WithFields(logrus.Fields{
"maxRetries": maxRetries,
"lastError": lastErr,
}).Error("Failed to generate AI reply after all attempts")
return "", fmt.Errorf("failed after %d attempts, last error: %v", maxRetries, lastErr)
}