mirror of
https://github.com/ollama/ollama.git
synced 2025-11-10 20:57:27 +01:00
reverse changes
This commit is contained in:
@@ -381,3 +381,30 @@ func TestAPIShowModel(t *testing.T) {
|
|||||||
t.Errorf("%s missing modified_at: %#v", modelName, resp)
|
t.Errorf("%s missing modified_at: %#v", modelName, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPIEmbeddings(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
client, _, cleanup := InitServerConnection(ctx, t)
|
||||||
|
defer cleanup()
|
||||||
|
req := api.EmbeddingRequest{
|
||||||
|
Model: libraryEmbedModels[0],
|
||||||
|
Prompt: "why is the sky blue?",
|
||||||
|
Options: map[string]interface{}{
|
||||||
|
"temperature": 0,
|
||||||
|
"seed": 123,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := PullIfMissing(ctx, client, req.Model); err != nil {
|
||||||
|
t.Fatalf("pull failed %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Embeddings(ctx, &req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("embeddings call failed %s", err)
|
||||||
|
}
|
||||||
|
if len(resp.Embedding) == 0 {
|
||||||
|
t.Errorf("zero length embedding response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,18 +12,22 @@ import (
|
|||||||
"github.com/ollama/ollama/api"
|
"github.com/ollama/ollama/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestQwen3VLStreaming tests Qwen3-VL with streaming enabled
|
// getTestConfig returns model and streaming mode based on environment variables or defaults
|
||||||
func TestQwen3VLStreaming(t *testing.T) {
|
func getTestConfig() (model string, stream bool) {
|
||||||
runQwen3VLTests(t, true)
|
model = os.Getenv("QWEN3VL_MODEL")
|
||||||
|
if model == "" {
|
||||||
|
model = "qwen3-vl:235b-cloud" // default
|
||||||
|
}
|
||||||
|
|
||||||
|
streamStr := os.Getenv("QWEN3VL_STREAM")
|
||||||
|
stream = streamStr != "false" // default to true
|
||||||
|
|
||||||
|
return model, stream
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestQwen3VLNonStreaming tests Qwen3-VL with streaming disabled
|
func TestQwen3VL(t *testing.T) {
|
||||||
func TestQwen3VLNonStreaming(t *testing.T) {
|
model, stream := getTestConfig()
|
||||||
runQwen3VLTests(t, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func runQwen3VLTests(t *testing.T, stream bool) {
|
|
||||||
models := []string{"qwen3-vl:235b-cloud", "qwen3-vl:235b-instruct-cloud"}
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
messages []api.Message
|
messages []api.Message
|
||||||
@@ -46,10 +50,10 @@ func runQwen3VLTests(t *testing.T, stream bool) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
Content: "What is the answer to this question?",
|
Content: "What is in this image?",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
images: []string{"testdata/question.png"},
|
images: []string{"testdata/menu.png"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple Images Scenario",
|
name: "Multiple Images Scenario",
|
||||||
@@ -63,7 +67,7 @@ func runQwen3VLTests(t *testing.T, stream bool) {
|
|||||||
Content: "Use both images to answer the question.",
|
Content: "Use both images to answer the question.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
images: []string{"testdata/question.png", "testdata/menu.png"},
|
images: []string{"testdata/satmath1.png", "testdata/satmath2.png"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Tools Scenario",
|
name: "Tools Scenario",
|
||||||
@@ -158,102 +162,90 @@ func runQwen3VLTests(t *testing.T, stream bool) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, model := range models {
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
// Load and attach images if specified
|
// Load and attach images to last user message
|
||||||
|
messages := tt.messages
|
||||||
if len(tt.images) > 0 {
|
if len(tt.images) > 0 {
|
||||||
var imgs []api.ImageData
|
var imgs []api.ImageData
|
||||||
for _, path := range tt.images {
|
for _, path := range tt.images {
|
||||||
imgs = append(imgs, loadImageData(t, path))
|
imgs = append(imgs, loadImageData(t, path))
|
||||||
}
|
}
|
||||||
if len(tt.messages) > 0 {
|
// Find last user message and attach images
|
||||||
lastMessage := &tt.messages[len(tt.messages)-1]
|
for i := len(messages) - 1; i >= 0; i-- {
|
||||||
if lastMessage.Role == "user" {
|
if messages[i].Role == "user" {
|
||||||
lastMessage.Images = imgs
|
messages[i].Images = imgs
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build chat request
|
|
||||||
req := api.ChatRequest{
|
|
||||||
Model: model,
|
|
||||||
Messages: tt.messages,
|
|
||||||
Tools: tt.tools,
|
|
||||||
Stream: &stream,
|
|
||||||
Options: map[string]any{
|
|
||||||
"seed": 42,
|
|
||||||
"temperature": 0.0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
isRemote := os.Getenv("OLLAMA_TEST_EXISTING") != ""
|
|
||||||
|
|
||||||
// Use integration helpers
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
client, _, cleanup := InitServerConnection(ctx, t)
|
client, _, cleanup := InitServerConnection(ctx, t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// Skip pulling/preloading when using an existing (cloud) server
|
// Pull/preload model if not using remote server
|
||||||
if !isRemote {
|
if os.Getenv("OLLAMA_TEST_EXISTING") == "" {
|
||||||
if err := PullIfMissing(ctx, client, req.Model); err != nil {
|
if err := PullIfMissing(ctx, client, model); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
// Preload model once to reduce startup latency
|
// Preload to reduce startup latency
|
||||||
_ = client.Generate(ctx, &api.GenerateRequest{Model: req.Model}, func(r api.GenerateResponse) error { return nil })
|
_ = client.Generate(ctx, &api.GenerateRequest{Model: model}, func(api.GenerateResponse) error { return nil })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build and execute chat request
|
||||||
|
req := &api.ChatRequest{
|
||||||
|
Model: model,
|
||||||
|
Messages: messages,
|
||||||
|
Tools: tt.tools,
|
||||||
|
Stream: &stream,
|
||||||
|
Options: map[string]any{"seed": 42, "temperature": 0.0},
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentBuf, thinkingBuf strings.Builder
|
var contentBuf, thinkingBuf strings.Builder
|
||||||
var gotCalls []api.ToolCall
|
var toolCalls []api.ToolCall
|
||||||
|
|
||||||
err := client.Chat(ctx, &req, func(r api.ChatResponse) error {
|
err := client.Chat(ctx, req, func(r api.ChatResponse) error {
|
||||||
contentBuf.WriteString(r.Message.Content)
|
contentBuf.WriteString(r.Message.Content)
|
||||||
thinkingBuf.WriteString(r.Message.Thinking)
|
thinkingBuf.WriteString(r.Message.Thinking)
|
||||||
if len(r.Message.ToolCalls) > 0 {
|
toolCalls = append(toolCalls, r.Message.ToolCalls...)
|
||||||
gotCalls = append(gotCalls, r.Message.ToolCalls...)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("chat error: %v", err)
|
t.Fatalf("chat error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log responses (truncated)
|
// Log truncated responses
|
||||||
content := contentBuf.String()
|
logTruncated := func(label, text string) {
|
||||||
thinking := thinkingBuf.String()
|
if text != "" {
|
||||||
const maxLog = 800
|
if len(text) > 800 {
|
||||||
if len(thinking) > 0 {
|
text = text[:800] + "... [truncated]"
|
||||||
if len(thinking) > maxLog {
|
|
||||||
thinking = thinking[:maxLog] + "... [truncated]"
|
|
||||||
}
|
}
|
||||||
t.Logf("Thinking: %s", thinking)
|
t.Logf("%s: %s", label, text)
|
||||||
}
|
}
|
||||||
if len(content) > 0 {
|
|
||||||
if len(content) > maxLog {
|
|
||||||
content = content[:maxLog] + "... [truncated]"
|
|
||||||
}
|
}
|
||||||
t.Logf("Content: %s", content)
|
logTruncated("Thinking", thinkingBuf.String())
|
||||||
}
|
logTruncated("Content", contentBuf.String())
|
||||||
if len(gotCalls) > 0 {
|
|
||||||
t.Logf("Tool calls: %d", len(gotCalls))
|
if len(toolCalls) > 0 {
|
||||||
for i, call := range gotCalls {
|
t.Logf("Tool calls: %d", len(toolCalls))
|
||||||
|
for i, call := range toolCalls {
|
||||||
t.Logf(" [%d] %s(%+v)", i, call.Function.Name, call.Function.Arguments)
|
t.Logf(" [%d] %s(%+v)", i, call.Function.Name, call.Function.Arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a tools scenario, validate tool_calls
|
// Validate tool calls if tools were provided
|
||||||
if len(tt.tools) > 0 {
|
if len(tt.tools) > 0 {
|
||||||
if len(gotCalls) == 0 {
|
if len(toolCalls) == 0 {
|
||||||
t.Fatalf("expected at least one tool call, got none")
|
t.Fatal("expected at least one tool call, got none")
|
||||||
}
|
}
|
||||||
if gotCalls[0].Function.Name == "" {
|
if toolCalls[0].Function.Name == "" {
|
||||||
t.Fatalf("tool call missing function name: %#v", gotCalls[0])
|
t.Fatalf("tool call missing function name: %#v", toolCalls[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadImageData loads image data from a file path
|
// loadImageData loads image data from a file path
|
||||||
|
|||||||
BIN
integration/testdata/question.png
vendored
BIN
integration/testdata/question.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 569 KiB |
BIN
integration/testdata/sketch2code_input.jpeg
vendored
BIN
integration/testdata/sketch2code_input.jpeg
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 MiB |
Reference in New Issue
Block a user