import json from actions.duck_search import duckduckgo_search from processing.text import read_txt_files from agent.llm_utils import llm_response, llm_stream_response from config import Config from agent import prompts import os import string CFG = Config() class ResearchAgent: def __init__(self, question, agent): """ Initializes the research assistant with the given question. Args: question (str): The question to research Returns: None """ self.question = question self.agent = agent self.visited_urls = set() self.search_summary = "" self.directory_name = ''.join(c for c in question if c.isascii() and c not in string.punctuation)[:100] self.dir_path = os.path.dirname(f"./outputs/{self.directory_name}/") def call_agent(self, action): messages = [{ "role": "system", "content": prompts.generate_agent_role_prompt(self.agent), }, { "role": "user", "content": action, }] return llm_response( model=CFG.fast_llm_model, messages=messages, ) def call_agent_stream(self, action): messages = [{ "role": "system", "content": prompts.generate_agent_role_prompt(self.agent), }, { "role": "user", "content": action, }] yield from llm_stream_response( model=CFG.fast_llm_model, messages=messages ) def create_search_queries(self): """ Creates the search queries for the given question. Args: None Returns: list[str]: The search queries for the given question """ result = self.call_agent(prompts.generate_search_queries_prompt(self.question)) return json.loads(result) def search_single_query(self, query): """ Runs the async search for the given query. Args: query (str): The query to run the async search for Returns: list[str]: The async search for the given query """ return duckduckgo_search(query, max_search_result=3) def run_search_summary(self, query): """ Runs the search summary for the given query. Args: query (str): The query to run the search summary for Returns: str: The search summary for the given query """ responses = self.search_single_query(query) print(f"Searching for {query}") query = hash(query) file_path = f"./outputs/{self.directory_name}/research-{query}.txt" os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, "w") as f: json.dump(responses, f) print(f"Saved {query} to {file_path}") return responses def search_online(self): """ Conducts the search for the given question. Args: None Returns: str: The search results for the given question """ self.search_summary = read_txt_files(self.dir_path) if os.path.isdir(self.dir_path) else "" if not self.search_summary: search_queries = self.create_search_queries() for _, query in search_queries.items(): search_result = self.run_search_summary(query) self.search_summary += f"=Query=:\n{query}\n=Search Result=:\n{search_result}\n================\n" return self.search_summary def write_report(self, report_type): """ Writes the report for the given question. Args: None Returns: str: The report for the given question """ # yield "Searching online..." report_type_func = prompts.get_report_by_type(report_type) yield from self.call_agent_stream(report_type_func(self.question, self.search_online()))