mirror of
https://github.com/R0m1k3/FlowReader.git
synced 2026-10-11 17:28:05 +02:00
108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
)
|
|
|
|
// AIService handles interactions with AI providers (OpenRouter).
|
|
type AIService struct {
|
|
apiKey string
|
|
client *http.Client
|
|
}
|
|
|
|
// NewAIService creates a new AI service.
|
|
func NewAIService() *AIService {
|
|
return &AIService{
|
|
apiKey: os.Getenv("OPENROUTER_API_KEY"),
|
|
client: &http.Client{},
|
|
}
|
|
}
|
|
|
|
// OpenRouterRequest represents the request body for OpenRouter.
|
|
type OpenRouterRequest struct {
|
|
Model string `json:"model"`
|
|
Messages []Message `json:"messages"`
|
|
}
|
|
|
|
// Message represents a message in the conversation.
|
|
type Message struct {
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
}
|
|
|
|
// OpenRouterResponse represents the response body from OpenRouter.
|
|
type OpenRouterResponse struct {
|
|
Choices []struct {
|
|
Message Message `json:"message"`
|
|
} `json:"choices"`
|
|
Error *struct {
|
|
Message string `json:"message"`
|
|
} `json:"error,omitempty"`
|
|
}
|
|
|
|
// Summarize generates a concise summary of the given content.
|
|
func (s *AIService) Summarize(ctx context.Context, content string) (string, error) {
|
|
if s.apiKey == "" {
|
|
return "", fmt.Errorf("OPENROUTER_API_KEY not set")
|
|
}
|
|
|
|
prompt := fmt.Sprintf("Résume l'article suivant en 3 à 5 phrases percutantes. Sois direct et informatif :\n\n%s", content)
|
|
|
|
reqBody := OpenRouterRequest{
|
|
Model: "google/gemini-2.0-flash-001", // Économique et performant
|
|
Messages: []Message{
|
|
{Role: "user", Content: prompt},
|
|
},
|
|
}
|
|
|
|
jsonData, err := json.Marshal(reqBody)
|
|
if err != nil {
|
|
return "", fmt.Errorf("marshaling request: %w", err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "POST", "https://openrouter.ai/api/v1/chat/completions", bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return "", fmt.Errorf("creating request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+s.apiKey)
|
|
req.Header.Set("HTTP-Referer", "https://github.com/michael/flowreader") // Optionnel pour OpenRouter
|
|
|
|
resp, err := s.client.Do(req)
|
|
if err != nil {
|
|
return "", fmt.Errorf("sending request: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", fmt.Errorf("reading response: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
var orResp OpenRouterResponse
|
|
if err := json.Unmarshal(body, &orResp); err != nil {
|
|
return "", fmt.Errorf("unmarshaling response: %w", err)
|
|
}
|
|
|
|
if orResp.Error != nil {
|
|
return "", fmt.Errorf("OpenRouter error: %s", orResp.Error.Message)
|
|
}
|
|
|
|
if len(orResp.Choices) == 0 {
|
|
return "", fmt.Errorf("no summary generated")
|
|
}
|
|
|
|
return orResp.Choices[0].Message.Content, nil
|
|
}
|