feat: add web search config
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
from typing import Optional, Dict, Any
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.api.llm import get_current_user, get_admin_user, CurrentUser
|
||||
from app.services.web_search_config_store import get_web_search_config, save_web_search_config
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class WebSearchConfigModel(BaseModel):
|
||||
provider: str = Field(default="duckduckgo", description="Web search provider (brave, tavily, duckduckgo, searxng, jina)")
|
||||
api_key: Optional[str] = Field(default="", description="API Key for the provider")
|
||||
base_url: Optional[str] = Field(default="", description="Base URL for SearXNG")
|
||||
max_results: int = Field(default=5, description="Maximum number of search results")
|
||||
|
||||
def _sanitize_config(config: Dict[str, Any], is_admin: bool) -> Dict[str, Any]:
|
||||
sanitized = config.copy()
|
||||
if not is_admin:
|
||||
sanitized["api_key"] = None
|
||||
return sanitized
|
||||
|
||||
@router.get("/web-search/config", response_model=WebSearchConfigModel)
|
||||
def get_config(current_user: CurrentUser = Depends(get_current_user)):
|
||||
config = get_web_search_config()
|
||||
return WebSearchConfigModel(**_sanitize_config(config, current_user.is_admin))
|
||||
|
||||
@router.put("/web-search/config", response_model=WebSearchConfigModel)
|
||||
def update_config(config: WebSearchConfigModel, _: CurrentUser = Depends(get_admin_user)):
|
||||
config_dict = config.dict()
|
||||
save_web_search_config(config_dict)
|
||||
return WebSearchConfigModel(**config_dict)
|
||||
@@ -33,6 +33,7 @@ from nanobot.config.schema import Config
|
||||
from app.api.skills import load_skills
|
||||
from app.core.patched_openai_compat_provider import PatchedOpenAICompatProvider
|
||||
from app.services.llm_cache import get_llm_configs, get_active_llm_config
|
||||
from app.services.web_search_config_store import get_web_search_config
|
||||
|
||||
from app.core.data_root import get_workspace_root
|
||||
|
||||
@@ -103,6 +104,16 @@ class NanobotIntegration:
|
||||
usage = self._last_usage_by_session.get(session_id)
|
||||
return dict(usage) if usage else None
|
||||
|
||||
def _get_web_search_config(self) -> Any:
|
||||
from nanobot.config.schema import WebSearchConfig
|
||||
ws_dict = get_web_search_config()
|
||||
return WebSearchConfig(
|
||||
provider=ws_dict.get("provider", "duckduckgo"),
|
||||
api_key=ws_dict.get("api_key", ""),
|
||||
base_url=ws_dict.get("base_url", ""),
|
||||
max_results=ws_dict.get("max_results", 5)
|
||||
)
|
||||
|
||||
def _need_custom_agent_for_target(self, target_config: Dict[str, Any]) -> bool:
|
||||
if not self.agent:
|
||||
return False
|
||||
@@ -173,7 +184,7 @@ class NanobotIntegration:
|
||||
model=initial_model,
|
||||
max_iterations=self.config.agents.defaults.max_tool_iterations,
|
||||
context_window_tokens=self.config.agents.defaults.context_window_tokens,
|
||||
web_search_config=self.config.tools.web.search,
|
||||
web_search_config=self._get_web_search_config(),
|
||||
web_proxy=self.config.tools.web.proxy or None,
|
||||
exec_config=self.config.tools.exec,
|
||||
cron_service=self.cron,
|
||||
@@ -319,7 +330,7 @@ class NanobotIntegration:
|
||||
model=provider.default_model,
|
||||
max_iterations=self.config.agents.defaults.max_tool_iterations,
|
||||
context_window_tokens=self.config.agents.defaults.context_window_tokens,
|
||||
web_search_config=self.config.tools.web.search,
|
||||
web_search_config=self._get_web_search_config(),
|
||||
web_proxy=self.config.tools.web.proxy or None,
|
||||
exec_config=self.config.tools.exec,
|
||||
cron_service=self.cron,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import os
|
||||
import json
|
||||
import threading
|
||||
from typing import Any, Dict
|
||||
|
||||
from app.core.data_root import get_data_root
|
||||
|
||||
_cache_lock = threading.RLock()
|
||||
_cache_mtime: float = -1.0
|
||||
_cache_data: Dict[str, Any] = {}
|
||||
|
||||
def get_config_file_path() -> str:
|
||||
return str(get_data_root() / "web_search_config.json")
|
||||
|
||||
def get_web_search_config() -> Dict[str, Any]:
|
||||
global _cache_mtime, _cache_data
|
||||
config_file = get_config_file_path()
|
||||
current_mtime = os.path.getmtime(config_file) if os.path.exists(config_file) else -1.0
|
||||
|
||||
with _cache_lock:
|
||||
if current_mtime != _cache_mtime:
|
||||
if not os.path.exists(config_file):
|
||||
_cache_data = {
|
||||
"provider": "duckduckgo",
|
||||
"api_key": "",
|
||||
"base_url": "",
|
||||
"max_results": 5
|
||||
}
|
||||
else:
|
||||
try:
|
||||
with open(config_file, "r") as f:
|
||||
_cache_data = json.load(f)
|
||||
except json.JSONDecodeError:
|
||||
_cache_data = {
|
||||
"provider": "duckduckgo",
|
||||
"api_key": "",
|
||||
"base_url": "",
|
||||
"max_results": 5
|
||||
}
|
||||
_cache_mtime = current_mtime
|
||||
return dict(_cache_data)
|
||||
|
||||
def save_web_search_config(config: Dict[str, Any]) -> None:
|
||||
global _cache_mtime, _cache_data
|
||||
config_file = get_config_file_path()
|
||||
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
||||
with _cache_lock:
|
||||
with open(config_file, "w") as f:
|
||||
json.dump(config, f, indent=2)
|
||||
_cache_data = dict(config)
|
||||
_cache_mtime = os.path.getmtime(config_file)
|
||||
+2
-1
@@ -21,7 +21,7 @@ import re
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from app.api import upload, llm, skills, users, datasources, projects, semantic, mcp, subagents, knowledge, embedding_models
|
||||
from app.api import upload, llm, skills, users, datasources, projects, semantic, mcp, subagents, knowledge, embedding_models, web_search
|
||||
from app.connectors.postgres import postgres_connector
|
||||
from app.connectors.clickhouse import clickhouse_connector
|
||||
from app.core.artifacts import extract_artifacts
|
||||
@@ -77,6 +77,7 @@ app.include_router(mcp.router, prefix="/api/v1")
|
||||
app.include_router(subagents.router, prefix="/api/v1")
|
||||
app.include_router(knowledge.router, prefix="/api/v1")
|
||||
app.include_router(embedding_models.router, prefix="/api/v1")
|
||||
app.include_router(web_search.router, prefix="/api/v1")
|
||||
|
||||
STREAM_DELTA_CHUNK_SIZE = 48
|
||||
PREVIEWABLE_TEXT_EXTENSIONS = {
|
||||
|
||||
Reference in New Issue
Block a user