├── README.md ├── main.py ├── requirements.txt ├── sample.env └── tools.py /README.md: -------------------------------------------------------------------------------- 1 | # PythonAIAgentFromScratch -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from dotenv import load_dotenv 2 | from pydantic import BaseModel 3 | from langchain_openai import ChatOpenAI 4 | from langchain_anthropic import ChatAnthropic 5 | from langchain_core.prompts import ChatPromptTemplate 6 | from langchain_core.output_parsers import PydanticOutputParser 7 | from langchain.agents import create_tool_calling_agent, AgentExecutor 8 | from tools import search_tool, wiki_tool, save_tool 9 | 10 | load_dotenv() 11 | 12 | class ResearchResponse(BaseModel): 13 | topic: str 14 | summary: str 15 | sources: list[str] 16 | tools_used: list[str] 17 | 18 | 19 | llm = ChatAnthropic(model="claude-3-5-sonnet-20241022") 20 | parser = PydanticOutputParser(pydantic_object=ResearchResponse) 21 | 22 | prompt = ChatPromptTemplate.from_messages( 23 | [ 24 | ( 25 | "system", 26 | """ 27 | You are a research assistant that will help generate a research paper. 28 | Answer the user query and use neccessary tools. 29 | Wrap the output in this format and provide no other text\n{format_instructions} 30 | """, 31 | ), 32 | ("placeholder", "{chat_history}"), 33 | ("human", "{query}"), 34 | ("placeholder", "{agent_scratchpad}"), 35 | ] 36 | ).partial(format_instructions=parser.get_format_instructions()) 37 | 38 | tools = [search_tool, wiki_tool, save_tool] 39 | agent = create_tool_calling_agent( 40 | llm=llm, 41 | prompt=prompt, 42 | tools=tools 43 | ) 44 | 45 | agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) 46 | query = input("What can i help you research? ") 47 | raw_response = agent_executor.invoke({"query": query}) 48 | 49 | try: 50 | structured_response = parser.parse(raw_response.get("output")[0]["text"]) 51 | print(structured_response) 52 | except Exception as e: 53 | print("Error parsing response", e, "Raw Response - ", raw_response) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | langchain 2 | wikipedia 3 | langchain-community 4 | langchain-openai 5 | langchain-anthropic 6 | python-dotenv 7 | pydantic 8 | duckduckgo-search -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY="" 2 | ANTHROPIC_API_KEY="" -------------------------------------------------------------------------------- /tools.py: -------------------------------------------------------------------------------- 1 | from langchain_community.tools import WikipediaQueryRun, DuckDuckGoSearchRun 2 | from langchain_community.utilities import WikipediaAPIWrapper 3 | from langchain.tools import Tool 4 | from datetime import datetime 5 | 6 | def save_to_txt(data: str, filename: str = "research_output.txt"): 7 | timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") 8 | formatted_text = f"--- Research Output ---\nTimestamp: {timestamp}\n\n{data}\n\n" 9 | 10 | with open(filename, "a", encoding="utf-8") as f: 11 | f.write(formatted_text) 12 | 13 | return f"Data successfully saved to {filename}" 14 | 15 | save_tool = Tool( 16 | name="save_text_to_file", 17 | func=save_to_txt, 18 | description="Saves structured research data to a text file.", 19 | ) 20 | 21 | search = DuckDuckGoSearchRun() 22 | search_tool = Tool( 23 | name="search", 24 | func=search.run, 25 | description="Search the web for information", 26 | ) 27 | 28 | api_wrapper = WikipediaAPIWrapper(top_k_results=1, doc_content_chars_max=100) 29 | wiki_tool = WikipediaQueryRun(api_wrapper=api_wrapper) 30 | 31 | --------------------------------------------------------------------------------