feat: replace search_web with unified lookup tool (Wikipedia + SearXNG fallback)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 21:56:31 -04:00
parent 6a8f0e9143
commit 06cd3493fd
2 changed files with 118 additions and 16 deletions
+57 -16
View File
@@ -1,4 +1,4 @@
"""Web search, research, and image tools (require SearXNG)."""
"""Web search, research, and image tools."""
from __future__ import annotations
@@ -10,29 +10,70 @@ logger = logging.getLogger(__name__)
@tool(
name="search_web",
name="lookup",
description=(
"Quick web lookup — returns search result snippets for factual questions, current events, "
"definitions, or version numbers. No note is saved. Use research_topic when the user wants "
"a comprehensive written report saved as a note."
"Look up a topic, concept, or factual question. Returns a concise answer from "
"Wikipedia or web sources. Use for definitions, explanations, 'what is X', "
"'how does Y work', current events, or version numbers. No note is saved. "
"For comprehensive written reports saved as notes, use research_topic instead."
),
parameters={
"query": {"type": "string", "description": "The search query"},
"query": {"type": "string", "description": "The topic or question to look up"},
},
required=["query"],
requires="searxng",
)
async def search_web_tool(*, user_id, arguments, **_ctx):
from fabledassistant.services.research import _search_searxng
async def lookup_tool(*, user_id, arguments, **_ctx):
from fabledassistant.config import Config
from fabledassistant.services.wikipedia import wiki_summary
query = arguments.get("query", "")
results = await _search_searxng(query)
if not results:
return {"success": False, "error": f"No results found for '{query}'"}
# 1. Try Wikipedia first
wiki = await wiki_summary(query)
if wiki:
return {
"success": True,
"type": "lookup",
"source": "wikipedia",
"data": wiki,
}
# 2. Fall back to SearXNG + article fetch
if Config.searxng_enabled():
from fabledassistant.services.research import _search_searxng
from fabledassistant.services.rss import _fetch_full_article
results = await _search_searxng(query)
if results:
articles: list[dict] = []
for r in results[:2]:
url = r.get("url", "")
if not url:
continue
content = await _fetch_full_article(url)
articles.append({
"url": url,
"title": r.get("title", url),
"snippet": r.get("snippet", ""),
"content": (content or "")[:4000],
})
if articles:
return {
"success": True,
"type": "lookup",
"source": "web",
"data": {"query": query, "results": articles},
}
# 3. No sources available
return {
"success": True,
"type": "web_search",
"data": {"query": query, "results": results, "count": len(results)},
"type": "lookup",
"source": "none",
"data": {
"query": query,
"message": "No results found. You can answer from your own knowledge.",
},
}
@@ -42,7 +83,7 @@ async def search_web_tool(*, user_id, arguments, **_ctx):
"Deep web research — searches multiple sources, synthesizes findings, and saves the result "
"as a structured note with sections and citations. Use when the user says 'research', "
"'look into', or wants a comprehensive write-up. Takes 30120 seconds. "
"For a quick factual answer without saving a note, use search_web."
"For a quick factual answer without saving a note, use lookup."
),
parameters={
"topic": {"type": "string", "description": "The topic or question to research"},
@@ -64,7 +105,7 @@ async def research_topic_tool(*, user_id, arguments, **_ctx):
@tool(
name="search_images",
description="Search and display images inline. Use ONLY when the user explicitly asks to see, show, or find an image or photo. Not for factual questions — use search_web for those.",
description="Search and display images inline. Use ONLY when the user explicitly asks to see, show, or find an image or photo. Not for factual questions — use lookup for those.",
parameters={
"query": {"type": "string", "description": "The image search query"},
},