Spaces:
Starting
Starting
from langchain_openai import ChatOpenAI | |
from langchain_core.tools import tool | |
from duckduckgo_search import DDGS | |
import os | |
from dotenv import load_dotenv | |
# Load environment variables | |
load_dotenv() | |
api_key = os.getenv("OPENAI_API_KEY") | |
if not api_key: | |
raise ValueError("OPENAI_API_KEY environment variable not set") | |
async def web_search(query: str) -> str: | |
""" | |
Performs a web search using DuckDuckGo and returns a string of results. | |
Args: | |
query (str): The search query string. | |
Returns: | |
str: A string containing the search results. | |
""" | |
try: | |
with DDGS() as ddgs: | |
results = await ddgs.atext(keywords=query, max_results=5) | |
return "\n".join([f"{r['title']}: {r['body']}" for r in results]) | |
except Exception as e: | |
return f"Error performing web search: {str(e)}" | |
search_tool = web_search | |
class MultiHopSearchTool: | |
def __init__(self): | |
self.name = "multi_hop_search" | |
self.description = "Performs iterative web searches to refine results for complex queries." | |
self.inputs = { | |
"query": {"type": "string", "description": "Initial search query"}, | |
"steps": {"type": "integer", "description": "Number of search iterations (default: 3)"} | |
} | |
self.output_type = str | |
self.llm = ChatOpenAI( | |
model="gpt-4o", | |
api_key=api_key, | |
temperature=0, | |
http_client=None # Explicitly disable custom HTTP client to avoid proxies | |
) | |
async def aparse(self, query: str, steps: int = 3) -> str: | |
try: | |
current_query = query | |
results = [] | |
for _ in range(steps): | |
search_result = await web_search.invoke({"query": current_query}) | |
results.append(search_result) | |
# Refine query using LLM | |
prompt = f"""Based on the query: {current_query} | |
And the search results: {search_result} | |
Generate a refined search query to get more precise results.""" | |
response = await self.llm.ainvoke(prompt) | |
current_query = response.content | |
return "\n\n".join(results) | |
except Exception as e: | |
return f"Error in multi-hop search: {str(e)}" | |
multi_hop_search_tool = MultiHopSearchTool() |