diff --git a/backend/ai-core/cmd/main.go b/backend/ai-core/cmd/main.go index 7e03e21..876c878 100644 --- a/backend/ai-core/cmd/main.go +++ b/backend/ai-core/cmd/main.go @@ -462,6 +462,14 @@ func main() { if err := json.Unmarshal([]byte(result), &toolResult); err != nil { toolResult = map[string]interface{}{"output": result} } + + // 跳过失败的工具调用 — 错误结果不需要 LLM 跟进,避免噪音刷屏 + if success, ok := toolResult["success"].(bool); ok && !success { + errMsg, _ := toolResult["error"].(string) + log.Printf("[tool-followup] 跳过失败工具 %s: %s", toolName, errMsg) + return + } + output, _ := toolResult["output"].(string) if output == "" { output = result diff --git a/backend/ai-core/internal/tools/web_search.go b/backend/ai-core/internal/tools/web_search.go index a0e2c90..ab0c104 100644 --- a/backend/ai-core/internal/tools/web_search.go +++ b/backend/ai-core/internal/tools/web_search.go @@ -11,7 +11,7 @@ import ( "time" ) -// WebSearchTool 网页搜索工具 - 基于 SearXNG (或 DuckDuckGo fallback) +// WebSearchTool 网页搜索工具 - 基于 SearXNG type WebSearchTool struct { client *http.Client timeout time.Duration @@ -22,9 +22,9 @@ type WebSearchTool struct { func NewWebSearchTool() *WebSearchTool { return &WebSearchTool{ client: &http.Client{ - Timeout: 10 * time.Second, + Timeout: 25 * time.Second, }, - timeout: 10 * time.Second, + timeout: 25 * time.Second, } } @@ -32,9 +32,9 @@ func NewWebSearchTool() *WebSearchTool { func NewWebSearchToolWithURL(searxngURL string) *WebSearchTool { return &WebSearchTool{ client: &http.Client{ - Timeout: 10 * time.Second, + Timeout: 25 * time.Second, }, - timeout: 10 * time.Second, + timeout: 25 * time.Second, searxngURL: strings.TrimRight(searxngURL, "/"), } } @@ -97,13 +97,16 @@ func (t *WebSearchTool) Execute(ctx context.Context, arguments map[string]interf } func (t *WebSearchTool) searchViaSearXNG(ctx context.Context, query string) (*ToolResult, error) { - apiURL := fmt.Sprintf("%s/search?format=json&engines=bing,sogou,360search,baidu&q=%s", + // 只用 bing+sogou,去掉 baidu(安全验证拦截)和360search(不稳定) + // timeout=20 让 SearXNG 内部限速,避免慢引擎拖垮整次搜索 + apiURL := fmt.Sprintf("%s/search?format=json&engines=bing,sogou&timeout=20&q=%s", t.searxngURL, url.QueryEscape(query)) req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil) if err != nil { return &ToolResult{ToolName: "web_search", Success: false, Error: fmt.Sprintf("创建请求失败: %v", err)}, nil } + req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; CyreneBot/1.0)") resp, err := t.client.Do(req) if err != nil {