82 lines
2.3 KiB
Go
82 lines
2.3 KiB
Go
package llm_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.vakhrushev.me/av/jellybit/internal/llm"
|
|
)
|
|
|
|
// TestIntegration_OpenAICompat бьётся в реальный эндпоинт. По умолчанию
|
|
// пропускается; включается переменными окружения:
|
|
//
|
|
// JELLYBIT_LLM_BASE_URL=https://bothub.chat/api/v2/openai/v1 \
|
|
// JELLYBIT_LLM_API_KEY=... \
|
|
// JELLYBIT_LLM_MODEL=deepseek-v4-flash \
|
|
// go test ./internal/llm/ -run Integration -v
|
|
func TestIntegration_OpenAICompat(t *testing.T) {
|
|
base := os.Getenv("JELLYBIT_LLM_BASE_URL")
|
|
key := os.Getenv("JELLYBIT_LLM_API_KEY")
|
|
model := os.Getenv("JELLYBIT_LLM_MODEL")
|
|
if base == "" || model == "" {
|
|
t.Skip("set JELLYBIT_LLM_BASE_URL and JELLYBIT_LLM_MODEL to run")
|
|
}
|
|
|
|
p, err := llm.New(llm.Config{
|
|
Type: "openai-compat",
|
|
BaseURL: base,
|
|
APIKey: key,
|
|
Model: model,
|
|
Timeout: 90 * time.Second,
|
|
}, nil)
|
|
if err != nil {
|
|
t.Fatalf("New: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
|
|
defer cancel()
|
|
|
|
zero := 0.0
|
|
resp, err := p.Complete(ctx, llm.Request{
|
|
JSONMode: true,
|
|
Temperature: &zero,
|
|
MaxTokens: 2000,
|
|
Messages: []llm.Message{
|
|
{Role: llm.RoleSystem, Content: `Распознай медиа. Ответь только JSON по схеме: ` +
|
|
`{"kind":"movie|series","title":string,"year":number,"season":number|null}`},
|
|
{Role: llm.RoleUser, Content: "Аватар: Легенда об Аанге / Avatar: The Last Airbender / " +
|
|
"Книга 2: Земля [2006, США, DVDRip-AVC]"},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Complete: %v", err)
|
|
}
|
|
t.Logf("model=%s usage=%+v content=%s", resp.Model, resp.Usage, resp.Content)
|
|
|
|
raw, err := llm.ExtractJSONObject(resp.Content)
|
|
if err != nil {
|
|
t.Fatalf("ExtractJSONObject: %v (content: %q)", err, resp.Content)
|
|
}
|
|
var plan struct {
|
|
Kind string `json:"kind"`
|
|
Title string `json:"title"`
|
|
Year int `json:"year"`
|
|
Season *int `json:"season"`
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &plan); err != nil {
|
|
t.Fatalf("unmarshal plan: %v (raw: %s)", err, raw)
|
|
}
|
|
if plan.Kind != "series" {
|
|
t.Errorf("kind = %q, want series", plan.Kind)
|
|
}
|
|
if plan.Year != 2006 {
|
|
t.Errorf("year = %d, want 2006", plan.Year)
|
|
}
|
|
if plan.Season == nil || *plan.Season != 2 {
|
|
t.Errorf("season = %v, want 2", plan.Season)
|
|
}
|
|
}
|