78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package analyze
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/anthropics/anthropic-sdk-go"
|
|
|
|
"gitea.konchin.com/service/stonks/internal/config"
|
|
)
|
|
|
|
func init() {
|
|
Register("api", newAPIAnalyzer)
|
|
}
|
|
|
|
const defaultAPIModel = anthropic.ModelClaudeOpus5
|
|
|
|
// apiAnalyzer calls the Claude Messages API directly, billed per token.
|
|
// Reads credentials the standard way (ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN
|
|
// / an `ant auth login` profile) via the zero-arg client constructor.
|
|
type apiAnalyzer struct {
|
|
client anthropic.Client
|
|
model anthropic.Model
|
|
effort anthropic.OutputConfigEffort
|
|
}
|
|
|
|
func newAPIAnalyzer(cfg config.AnalyzerConfig) (Analyzer, error) {
|
|
model := anthropic.Model(cfg.Model)
|
|
if cfg.Model == "" {
|
|
model = defaultAPIModel
|
|
}
|
|
|
|
effort := anthropic.OutputConfigEffortMedium
|
|
if cfg.Effort != "" {
|
|
effort = anthropic.OutputConfigEffort(cfg.Effort)
|
|
}
|
|
|
|
return &apiAnalyzer{
|
|
client: anthropic.NewClient(),
|
|
model: model,
|
|
effort: effort,
|
|
}, nil
|
|
}
|
|
|
|
func (a *apiAnalyzer) Analyze(ctx context.Context, prompt string) (string, error) {
|
|
resp, err := a.client.Messages.New(ctx, anthropic.MessageNewParams{
|
|
Model: a.model,
|
|
MaxTokens: 4096,
|
|
System: []anthropic.TextBlockParam{{Text: SystemPrompt}},
|
|
OutputConfig: anthropic.OutputConfigParam{
|
|
Effort: a.effort,
|
|
},
|
|
Messages: []anthropic.MessageParam{
|
|
anthropic.NewUserMessage(anthropic.NewTextBlock(prompt)),
|
|
},
|
|
})
|
|
if err != nil {
|
|
return "", fmt.Errorf("analyze (api mode): %w", err)
|
|
}
|
|
|
|
if resp.StopReason == anthropic.StopReasonRefusal {
|
|
return "", fmt.Errorf("analyze (api mode): request refused by safety classifiers")
|
|
}
|
|
|
|
var out strings.Builder
|
|
for _, block := range resp.Content {
|
|
if text, ok := block.AsAny().(anthropic.TextBlock); ok {
|
|
out.WriteString(text.Text)
|
|
}
|
|
}
|
|
if out.Len() == 0 {
|
|
return "", fmt.Errorf("analyze (api mode): response contained no text content (stop_reason=%s)", resp.StopReason)
|
|
}
|
|
|
|
return out.String(), nil
|
|
}
|