fix: 修复 web_search 搜索超时和噪音问题

- 移除baidu/360search引擎(安全验证拦截),保留bing+sogou
- 超时从10s增加到25s,SearXNG内部timeout=20s
- 添加User-Agent
- 跳过失败的工具结果推送,避免"百度被安全验证挡住"等噪音刷屏

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-03 12:02:46 +08:00
parent e26501b25d
commit 197c86fa72
2 changed files with 17 additions and 6 deletions
+8
View File
@@ -462,6 +462,14 @@ func main() {
if err := json.Unmarshal([]byte(result), &toolResult); err != nil { if err := json.Unmarshal([]byte(result), &toolResult); err != nil {
toolResult = map[string]interface{}{"output": result} 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) output, _ := toolResult["output"].(string)
if output == "" { if output == "" {
output = result output = result
+9 -6
View File
@@ -11,7 +11,7 @@ import (
"time" "time"
) )
// WebSearchTool 网页搜索工具 - 基于 SearXNG (或 DuckDuckGo fallback) // WebSearchTool 网页搜索工具 - 基于 SearXNG
type WebSearchTool struct { type WebSearchTool struct {
client *http.Client client *http.Client
timeout time.Duration timeout time.Duration
@@ -22,9 +22,9 @@ type WebSearchTool struct {
func NewWebSearchTool() *WebSearchTool { func NewWebSearchTool() *WebSearchTool {
return &WebSearchTool{ return &WebSearchTool{
client: &http.Client{ 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 { func NewWebSearchToolWithURL(searxngURL string) *WebSearchTool {
return &WebSearchTool{ return &WebSearchTool{
client: &http.Client{ client: &http.Client{
Timeout: 10 * time.Second, Timeout: 25 * time.Second,
}, },
timeout: 10 * time.Second, timeout: 25 * time.Second,
searxngURL: strings.TrimRight(searxngURL, "/"), 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) { 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)) t.searxngURL, url.QueryEscape(query))
req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil) req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil)
if err != nil { if err != nil {
return &ToolResult{ToolName: "web_search", Success: false, Error: fmt.Sprintf("创建请求失败: %v", 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) resp, err := t.client.Do(req)
if err != nil { if err != nil {