Files
Dialectic.Backend/services/search_service.py
2026-02-12 15:45:48 +00:00

105 lines
3.7 KiB
Python

from typing import List, Optional
from models.debate import SearchResult, SearchEvidence
class SearchService:
"""
Tavily web search wrapper for debate research.
"""
def __init__(self, api_key: str):
from tavily import TavilyClient
self.client = TavilyClient(api_key=api_key)
def search(self, query: str, max_results: int = 5) -> List[SearchResult]:
"""
Perform a web search using Tavily and return structured results.
"""
try:
response = self.client.search(
query=query,
max_results=max_results,
search_depth="basic"
)
results = []
for item in response.get("results", []):
results.append(SearchResult(
title=item.get("title", ""),
url=item.get("url", ""),
snippet=item.get("content", "")[:500], # Truncate to avoid token bloat
score=item.get("score")
))
return results
except Exception as e:
print(f"Tavily search error: {e}")
return []
@staticmethod
def format_results_for_context(evidence: SearchEvidence) -> str:
"""
Format search results into a string suitable for injecting into the LLM context.
"""
if not evidence or not evidence.results:
return ""
lines = [f"\n[网络搜索结果] 搜索词: \"{evidence.query}\""]
for i, r in enumerate(evidence.results, 1):
lines.append(f" {i}. {r.title}")
lines.append(f" {r.snippet}")
lines.append(f" 来源: {r.url}")
lines.append("[搜索结果结束]\n")
return "\n".join(lines)
@staticmethod
def generate_search_query(topic: str, last_opponent_argument: Optional[str] = None) -> str:
"""
Generate a search query from the debate topic and the opponent's last argument.
"""
if last_opponent_argument:
# Extract key phrases from the opponent's argument (first ~100 chars)
snippet = last_opponent_argument[:100].strip()
return f"{topic} {snippet}"
return topic
@staticmethod
def get_tool_definition() -> dict:
"""
Return the web_search tool definition for function calling.
"""
return {
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for current information relevant to the debate topic. Use this to find facts, statistics, or recent news that support your argument.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query to look up"
}
},
"required": ["query"]
}
}
}
@staticmethod
def get_tool_definition_anthropic() -> dict:
"""
Return the web_search tool definition in Anthropic format.
"""
return {
"name": "web_search",
"description": "Search the web for current information relevant to the debate topic. Use this to find facts, statistics, or recent news that support your argument.",
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query to look up"
}
},
"required": ["query"]
}
}