dealspace/lib/llm.go

71 lines
1.8 KiB
Go

package lib
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
// CallOpenRouter sends a request to OpenRouter (OpenAI-compatible API).
func CallOpenRouter(apiKey, model string, messages []map[string]interface{}, maxTokens int) (string, error) {
if apiKey == "" {
return "", fmt.Errorf("OpenRouter API key not configured")
}
reqBody := map[string]interface{}{
"model": model,
"messages": messages,
"max_tokens": maxTokens,
"temperature": 0.1,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return "", fmt.Errorf("marshal request: %w", err)
}
req, err := http.NewRequest("POST", "https://openrouter.ai/api/v1/chat/completions", bytes.NewReader(jsonBody))
if err != nil {
return "", fmt.Errorf("create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("API request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("read response: %w", err)
}
if resp.StatusCode != 200 {
return "", fmt.Errorf("OpenRouter API error %d: %s", resp.StatusCode, string(body))
}
var oaiResp struct {
Choices []struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
}
if err := json.Unmarshal(body, &oaiResp); err != nil {
return "", fmt.Errorf("parse response: %w", err)
}
if len(oaiResp.Choices) == 0 {
return "", fmt.Errorf("empty response from OpenRouter")
}
text := strings.TrimSpace(oaiResp.Choices[0].Message.Content)
text = strings.TrimPrefix(text, "```json")
text = strings.TrimPrefix(text, "```")
text = strings.TrimSuffix(text, "```")
return strings.TrimSpace(text), nil
}