254 lines
6.0 KiB
Go
254 lines
6.0 KiB
Go
package openapi
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestCreateChatCompletion(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/chat/completions" {
|
|
t.Errorf("expected path /chat/completions, got %s", r.URL.Path)
|
|
}
|
|
if r.Header.Get("Authorization") != "Bearer test-key" {
|
|
t.Errorf("expected bearer token, got %s", r.Header.Get("Authorization"))
|
|
}
|
|
|
|
var req ChatCompletionRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !req.CachePrompt {
|
|
t.Error("expected cache_prompt to be true")
|
|
}
|
|
|
|
resp := ChatCompletionResponse{
|
|
ID: "test-id",
|
|
Model: "test-model",
|
|
Choices: []Choice{
|
|
{
|
|
Message: Message{
|
|
Role: RoleAssistant,
|
|
Content: "Hello!",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-key")
|
|
resp, err := client.CreateChatCompletion(context.Background(), ChatCompletionRequest{
|
|
Model: "test-model",
|
|
Messages: []Message{
|
|
{Role: RoleUser, Content: "Hi"},
|
|
},
|
|
CachePrompt: true,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if resp.Choices[0].Message.Content != "Hello!" {
|
|
t.Errorf("expected Hello!, got %s", resp.Choices[0].Message.Content)
|
|
}
|
|
}
|
|
|
|
func TestCreateChatCompletionWithReasoning(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
resp := ChatCompletionResponse{
|
|
Choices: []Choice{
|
|
{
|
|
Message: Message{
|
|
Role: RoleAssistant,
|
|
Content: "Hello!",
|
|
ReasoningContent: "Thinking...",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-key")
|
|
resp, err := client.CreateChatCompletion(context.Background(), ChatCompletionRequest{
|
|
Model: "test-model",
|
|
Messages: []Message{
|
|
{Role: RoleUser, Content: "Hi"},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if resp.Choices[0].Message.ReasoningContent != "Thinking..." {
|
|
t.Errorf("expected Thinking..., got %s", resp.Choices[0].Message.ReasoningContent)
|
|
}
|
|
}
|
|
|
|
func TestCreateChatCompletionWithToolCalls(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
resp := ChatCompletionResponse{
|
|
Choices: []Choice{
|
|
{
|
|
Message: Message{
|
|
Role: RoleAssistant,
|
|
ToolCalls: []ToolCall{
|
|
{
|
|
ID: "call_123",
|
|
Type: "function",
|
|
Function: ToolCallFunction{
|
|
Name: "get_weather",
|
|
Arguments: `{"location":"Stockholm"}`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-key")
|
|
resp, err := client.CreateChatCompletion(context.Background(), ChatCompletionRequest{
|
|
Model: "test-model",
|
|
Messages: []Message{
|
|
{Role: RoleUser, Content: "What is the weather in Stockholm?"},
|
|
},
|
|
Tools: []Tool{
|
|
{
|
|
Type: "function",
|
|
Function: FunctionDefinition{
|
|
Name: "get_weather",
|
|
Description: "Get the current weather",
|
|
Parameters: json.RawMessage(`{"type":"object","properties":{"location":{"type":"string"}}}`),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(resp.Choices[0].Message.ToolCalls) != 1 {
|
|
t.Fatalf("expected 1 tool call, got %d", len(resp.Choices[0].Message.ToolCalls))
|
|
}
|
|
|
|
tc := resp.Choices[0].Message.ToolCalls[0]
|
|
if tc.Function.Name != "get_weather" {
|
|
t.Errorf("expected get_weather, got %s", tc.Function.Name)
|
|
}
|
|
}
|
|
|
|
func TestCreateChatCompletionWithToolResponse(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var req ChatCompletionRequest
|
|
json.NewDecoder(r.Body).Decode(&req)
|
|
|
|
// Check if the tool response is present
|
|
foundToolResponse := false
|
|
for _, msg := range req.Messages {
|
|
if msg.Role == RoleTool && msg.ToolCallID == "call_123" {
|
|
foundToolResponse = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundToolResponse {
|
|
t.Error("expected tool response message in request")
|
|
}
|
|
|
|
resp := ChatCompletionResponse{
|
|
Choices: []Choice{
|
|
{
|
|
Message: Message{
|
|
Role: RoleAssistant,
|
|
Content: "The weather in Stockholm is 15°C.",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-key")
|
|
_, err := client.CreateChatCompletion(context.Background(), ChatCompletionRequest{
|
|
Model: "test-model",
|
|
Messages: []Message{
|
|
{Role: RoleUser, Content: "What is the weather in Stockholm?"},
|
|
{
|
|
Role: RoleAssistant,
|
|
ToolCalls: []ToolCall{
|
|
{
|
|
ID: "call_123",
|
|
Type: "function",
|
|
Function: ToolCallFunction{
|
|
Name: "get_weather",
|
|
Arguments: `{"location":"Stockholm"}`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Role: RoleTool,
|
|
ToolCallID: "call_123",
|
|
Content: `{"temp":15}`,
|
|
},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestCreateChatCompletionStreamWithReasoning(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
fmt.Fprintf(w, "data: %s\n\n", `{"choices":[{"delta":{"reasoning_content":"Thinking"}}]} `)
|
|
fmt.Fprintf(w, "data: %s\n\n", `{"choices":[{"delta":{"content":"Hello"}}]} `)
|
|
fmt.Fprintf(w, "data: [DONE]\n\n")
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(server.URL, "test-key")
|
|
chunks, errs := client.CreateChatCompletionStream(context.Background(), ChatCompletionRequest{
|
|
Model: "test-model",
|
|
Messages: []Message{
|
|
{Role: RoleUser, Content: "Hi"},
|
|
},
|
|
})
|
|
|
|
var reasoning, content string
|
|
for chunk := range chunks {
|
|
if len(chunk.Choices) > 0 {
|
|
reasoning += chunk.Choices[0].Delta.ReasoningContent
|
|
content += chunk.Choices[0].Delta.Content
|
|
}
|
|
}
|
|
|
|
if err := <-errs; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if reasoning != "Thinking" {
|
|
t.Errorf("expected Thinking, got %s", reasoning)
|
|
}
|
|
if content != "Hello" {
|
|
t.Errorf("expected Hello, got %s", content)
|
|
}
|
|
}
|