Enhance code as comment from best friends
This commit is contained in:
parent
c3967a560d
commit
487edfa64e
4 changed files with 71 additions and 27 deletions
|
|
@ -3,7 +3,7 @@
|
|||
"defaults": {
|
||||
"workspace": "~/.picoclaw/workspace",
|
||||
"restrict_to_workspace": true,
|
||||
"model": "ollama/qwen2.5:14b-instruct ",
|
||||
"model": "",
|
||||
"max_tokens": 8192,
|
||||
"temperature": 0.7,
|
||||
"max_tool_iterations": 20
|
||||
|
|
@ -119,11 +119,11 @@
|
|||
"tools": {
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "ollama",
|
||||
"api_key": "Your Ollama API Key",
|
||||
"provider": "ollama/brave/duckduckgo",
|
||||
"api_key": "Your API Key",
|
||||
"endpoint": "https://ollama.com/api/web_search",
|
||||
"rest_type": "POST",
|
||||
"query_param": "query",
|
||||
"rest_type": "POST for ollama, GET for others",
|
||||
"query_param": "query for ollama, q for others",
|
||||
"max_results": 5
|
||||
},
|
||||
"perplexity": {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers
|
|||
Param: cfg.Tools.Web.Search.QueryParam,
|
||||
},
|
||||
{
|
||||
Provider: "duckduckgo",
|
||||
Provider: "duckduckgo", //fallback to duckduckgo if not configured
|
||||
MaxResults: 5,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,23 +283,6 @@ type GatewayConfig struct {
|
|||
Port int `json:"port" env:"PICOCLAW_GATEWAY_PORT"`
|
||||
}
|
||||
|
||||
type BraveConfig struct {
|
||||
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_BRAVE_ENABLED"`
|
||||
APIKey string `json:"api_key" env:"PICOCLAW_TOOLS_WEB_BRAVE_API_KEY"`
|
||||
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_BRAVE_MAX_RESULTS"`
|
||||
}
|
||||
|
||||
type DuckDuckGoConfig struct {
|
||||
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED"`
|
||||
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_DUCKDUCKGO_MAX_RESULTS"`
|
||||
}
|
||||
|
||||
type OllamaConfig struct {
|
||||
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_OLLAMA_ENABLED"`
|
||||
BaseURL string `json:"base_url" env:"PICOCLAW_TOOLS_WEB_OLLAMA_BASE_URL"`
|
||||
MaxResults int `json:"max_results" env:"PICOCLAW_TOOLS_WEB_OLLAMA_MAX_RESULTS"`
|
||||
}
|
||||
|
||||
// WebSearchConfig defines a single active web search provider
|
||||
// Falls back to DuckDuckGo if the primary provider fails
|
||||
type WebSearchConfig struct {
|
||||
|
|
@ -429,7 +412,7 @@ func DefaultConfig() *Config {
|
|||
Web: WebToolsConfig{
|
||||
Search: WebSearchConfig{
|
||||
Provider: "ollama",
|
||||
APIKey: "77b893700a1d4c8dad9a7326be9a76d6.7pl0DA9ojPa_6UCMMZ_Sk-Cn",
|
||||
APIKey: "",
|
||||
Endpoint: "https://ollama.com/api/web_search",
|
||||
RestType: "POST",
|
||||
QueryParam: "query",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -208,10 +210,22 @@ func (p *OllamaSearchProvider) Search(ctx context.Context, query string, count i
|
|||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logger.ErrorCF("tool", "Ollama web search request failed",
|
||||
map[string]interface{}{
|
||||
"provider": "ollama",
|
||||
"status_code": resp.StatusCode,
|
||||
"endpoint": p.baseURL,
|
||||
"response": strings.TrimSpace(string(body)),
|
||||
})
|
||||
return "", fmt.Errorf("Ollama API error: %s", string(body))
|
||||
}
|
||||
|
||||
// Return the raw JSON string for the agent/tool to process
|
||||
return string(body), nil
|
||||
}
|
||||
|
|
@ -283,6 +297,7 @@ func (p *PerplexitySearchProvider) Search(ctx context.Context, query string, cou
|
|||
|
||||
type WebSearchTool struct {
|
||||
provider SearchProvider
|
||||
fallback SearchProvider
|
||||
maxResults int
|
||||
}
|
||||
|
||||
|
|
@ -298,11 +313,12 @@ type WebSearchTool struct {
|
|||
// opts := []WebSearchToolOptions{
|
||||
// {Provider: "brave", APIKey: "key", MaxResults: 5},
|
||||
// {Provider: "ollama", BaseURL: "http://localhost:11434", MaxResults: 5},
|
||||
// {Provider: "perplexity", APIKey: "key", MaxResults: 5},
|
||||
// {Provider: "duckduckgo", MaxResults: 5},
|
||||
// }
|
||||
// tool := NewWebSearchTool(opts...)
|
||||
type WebSearchToolOptions struct {
|
||||
Provider string // "brave", "ollama", "duckduckgo"
|
||||
Provider string // "brave", "ollama", "perplexity", "duckduckgo"
|
||||
APIKey string // For Brave API
|
||||
BaseURL string // For custom providers (e.g., Ollama)
|
||||
MaxResults int // Default: 5
|
||||
|
|
@ -311,8 +327,8 @@ type WebSearchToolOptions struct {
|
|||
}
|
||||
|
||||
func NewWebSearchTool(opts ...WebSearchToolOptions) *WebSearchTool {
|
||||
// Priority order: Brave > Ollama > DuckDuckGo
|
||||
priorityOrder := []string{"brave", "ollama", "duckduckgo"}
|
||||
// Priority order: Brave > Ollama > Perplexity > DuckDuckGo
|
||||
priorityOrder := []string{"brave", "ollama", "perplexity", "duckduckgo"}
|
||||
optMap := make(map[string]WebSearchToolOptions)
|
||||
|
||||
// Build map of enabled providers
|
||||
|
|
@ -344,6 +360,15 @@ func NewWebSearchTool(opts ...WebSearchToolOptions) *WebSearchTool {
|
|||
return nil
|
||||
}
|
||||
|
||||
var fallbackProvider SearchProvider
|
||||
if selectedOpt != nil && selectedOpt.Provider != "duckduckgo" {
|
||||
if ddgOpt, exists := optMap["duckduckgo"]; exists {
|
||||
if p, err := createProvider(&ddgOpt); err == nil && p != nil {
|
||||
fallbackProvider = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxResults := 5
|
||||
if selectedOpt != nil && selectedOpt.MaxResults > 0 {
|
||||
maxResults = selectedOpt.MaxResults
|
||||
|
|
@ -351,6 +376,7 @@ func NewWebSearchTool(opts ...WebSearchToolOptions) *WebSearchTool {
|
|||
|
||||
return &WebSearchTool{
|
||||
provider: provider,
|
||||
fallback: fallbackProvider,
|
||||
maxResults: maxResults,
|
||||
}
|
||||
}
|
||||
|
|
@ -386,6 +412,12 @@ func createProvider(opt *WebSearchToolOptions) (SearchProvider, error) {
|
|||
case "duckduckgo":
|
||||
return &DuckDuckGoSearchProvider{}, nil
|
||||
|
||||
case "perplexity":
|
||||
if opt.APIKey == "" {
|
||||
return nil, fmt.Errorf("Perplexity API key required")
|
||||
}
|
||||
return &PerplexitySearchProvider{apiKey: opt.APIKey}, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown provider: %s", opt.Provider)
|
||||
}
|
||||
|
|
@ -433,6 +465,35 @@ func (t *WebSearchTool) Execute(ctx context.Context, args map[string]interface{}
|
|||
|
||||
result, err := t.provider.Search(ctx, query, count)
|
||||
if err != nil {
|
||||
if t.fallback != nil {
|
||||
logger.WarnCF("tool", "Primary web search failed, attempting fallback",
|
||||
map[string]interface{}{
|
||||
"primary_error": err.Error(),
|
||||
"fallback": "duckduckgo",
|
||||
"query": query,
|
||||
})
|
||||
|
||||
fallbackResult, fallbackErr := t.fallback.Search(ctx, query, count)
|
||||
if fallbackErr == nil {
|
||||
logger.InfoCF("tool", "Fallback web search succeeded",
|
||||
map[string]interface{}{
|
||||
"provider": "duckduckgo",
|
||||
"query": query,
|
||||
})
|
||||
|
||||
return &ToolResult{
|
||||
ForLLM: fmt.Sprintf("Primary search provider failed: %v\nFallback provider (duckduckgo) result:\n%s", err, fallbackResult),
|
||||
ForUser: fallbackResult,
|
||||
}
|
||||
}
|
||||
|
||||
logger.ErrorCF("tool", "Fallback web search failed",
|
||||
map[string]interface{}{
|
||||
"provider": "duckduckgo",
|
||||
"error": fallbackErr.Error(),
|
||||
"query": query,
|
||||
})
|
||||
}
|
||||
return ErrorResult(fmt.Sprintf("search failed: %v", err))
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue