mirror of
https://github.com/ollama/ollama.git
synced 2026-03-27 02:58:43 +07:00
middleware: enable local tool model for web search (#14787)
This commit is contained in:
@@ -240,15 +240,6 @@ func (w *WebSearchAnthropicWriter) runWebSearchLoop(ctx context.Context, initial
|
|||||||
|
|
||||||
var serverContent []anthropic.ContentBlock
|
var serverContent []anthropic.ContentBlock
|
||||||
|
|
||||||
if !isCloudModelName(w.req.Model) {
|
|
||||||
logutil.TraceContext(ctx, "anthropic middleware: web_search execution blocked", "reason", "non_cloud_model")
|
|
||||||
return anthropic.MessagesResponse{}, &webSearchLoopError{
|
|
||||||
code: "web_search_not_supported_for_local_models",
|
|
||||||
query: extractQueryFromToolCall(&initialToolCall),
|
|
||||||
usage: usage,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for loop := 1; loop <= maxWebSearchLoops; loop++ {
|
for loop := 1; loop <= maxWebSearchLoops; loop++ {
|
||||||
query := extractQueryFromToolCall(¤tToolCall)
|
query := extractQueryFromToolCall(¤tToolCall)
|
||||||
logutil.TraceContext(ctx, "anthropic middleware: web_search loop iteration",
|
logutil.TraceContext(ctx, "anthropic middleware: web_search loop iteration",
|
||||||
|
|||||||
@@ -1644,7 +1644,35 @@ func TestWebSearchCloudModelGating(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("local model emits web_search and gets structured error", func(t *testing.T) {
|
t.Run("local model emits web_search and gets results", func(t *testing.T) {
|
||||||
|
// Mock followup server for the model's response after receiving search results
|
||||||
|
followupServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
resp := api.ChatResponse{
|
||||||
|
Model: "llama3.2",
|
||||||
|
Message: api.Message{Role: "assistant", Content: "Based on search results, here is the answer."},
|
||||||
|
Done: true,
|
||||||
|
DoneReason: "stop",
|
||||||
|
Metrics: api.Metrics{PromptEvalCount: 20, EvalCount: 10},
|
||||||
|
}
|
||||||
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
|
}))
|
||||||
|
defer followupServer.Close()
|
||||||
|
t.Setenv("OLLAMA_HOST", followupServer.URL)
|
||||||
|
|
||||||
|
// Mock search server
|
||||||
|
searchServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
resp := anthropic.OllamaWebSearchResponse{
|
||||||
|
Results: []anthropic.OllamaWebSearchResult{
|
||||||
|
{Title: "Result", URL: "https://example.com", Content: "content"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
|
}))
|
||||||
|
defer searchServer.Close()
|
||||||
|
originalEndpoint := anthropic.WebSearchEndpoint
|
||||||
|
anthropic.WebSearchEndpoint = searchServer.URL
|
||||||
|
defer func() { anthropic.WebSearchEndpoint = originalEndpoint }()
|
||||||
|
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
router.Use(AnthropicMessagesMiddleware())
|
router.Use(AnthropicMessagesMiddleware())
|
||||||
router.POST("/v1/messages", func(c *gin.Context) {
|
router.POST("/v1/messages", func(c *gin.Context) {
|
||||||
@@ -1685,16 +1713,23 @@ func TestWebSearchCloudModelGating(t *testing.T) {
|
|||||||
if err := json.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
if err := json.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
||||||
t.Fatalf("unmarshal error: %v", err)
|
t.Fatalf("unmarshal error: %v", err)
|
||||||
}
|
}
|
||||||
if len(result.Content) != 2 {
|
|
||||||
t.Fatalf("expected 2 content blocks for local model web_search error, got %d", len(result.Content))
|
// Should have search result content blocks and the final text response
|
||||||
|
hasText := false
|
||||||
|
hasSearchResult := false
|
||||||
|
for _, block := range result.Content {
|
||||||
|
if block.Type == "text" {
|
||||||
|
hasText = true
|
||||||
|
}
|
||||||
|
if block.Type == "web_search_tool_result" {
|
||||||
|
hasSearchResult = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
contentJSON, _ := json.Marshal(result.Content[1].Content)
|
if !hasText {
|
||||||
var errContent anthropic.WebSearchToolResultError
|
t.Fatal("expected text content block in response")
|
||||||
if err := json.Unmarshal(contentJSON, &errContent); err != nil {
|
|
||||||
t.Fatalf("failed to parse web_search error content: %v", err)
|
|
||||||
}
|
}
|
||||||
if errContent.ErrorCode != "web_search_not_supported_for_local_models" {
|
if !hasSearchResult {
|
||||||
t.Fatalf("expected web_search_not_supported_for_local_models, got %q", errContent.ErrorCode)
|
t.Fatal("expected web_search_tool_result content block in response")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user