import os import streamlit as st import pandas as pd import matplotlib.pyplot as plt import networkx as nx from langchain_community.tools.tavily_search import TavilySearchResults from langchain_openai import ChatOpenAI from langgraph.graph import MessagesState from langgraph.graph import START, StateGraph from langgraph.prebuilt import tools_condition from langgraph.prebuilt import ToolNode from langchain_core.messages import HumanMessage, SystemMessage # ------------------- Environment Variable Setup ------------------- # Fetch API keys from environment variables openai_api_key = os.getenv("OPENAI_API_KEY") tavily_api_key = os.getenv("TAVILY_API_KEY") # Verify if API keys are set if not openai_api_key: raise ValueError("Missing required environment variable: OPENAI_API_KEY") if not tavily_api_key: raise ValueError("Missing required environment variable: TAVILY_API_KEY") # ------------------- Tool Definitions ------------------- tavily_tool = TavilySearchResults(max_results=5) def multiply(a: int, b: int) -> int: """Multiply two numbers.""" return a * b def add(a: int, b: int) -> int: """Add two numbers.""" return a + b def divide(a: int, b: int) -> float: """Divide two numbers.""" if b == 0: raise ValueError("Division by zero is not allowed.") return a / b tools = [add, multiply, divide, tavily_tool] # ------------------- LLM Setup ------------------- llm = ChatOpenAI(model="gpt-4o-mini") llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False) sys_msg = SystemMessage(content="You are a helpful assistant tasked with performing arithmetic and search on a set of inputs.") # ------------------- LangGraph Workflow ------------------- def assistant(state: MessagesState): """Assistant node to invoke LLM with tools.""" return {"messages": [llm_with_tools.invoke([sys_msg] + state["messages"])]} app_graph = StateGraph(MessagesState) app_graph.add_node("assistant", assistant) app_graph.add_node("tools", ToolNode(tools)) app_graph.add_edge(START, "assistant") app_graph.add_conditional_edges("assistant", tools_condition) app_graph.add_edge("tools", "assistant") react_graph = app_graph.compile() # ------------------- Streamlit Interface ------------------- st.title("ReAct Agent") # Display the workflow graph using NetworkX st.header("LangGraph Workflow Visualization") G = nx.DiGraph() G.add_edge("START", "assistant") G.add_edge("assistant", "tools", label="tools_condition") G.add_edge("tools", "assistant", label="loop back") plt.figure(figsize=(10, 6)) pos = nx.spring_layout(G, seed=42) nx.draw(G, pos, with_labels=True, node_size=3000, node_color="lightblue", font_size=10, font_weight="bold") nx.draw_networkx_edge_labels(G, pos, edge_labels={ ("assistant", "tools"): "tools_condition", ("tools", "assistant"): "loop back" }, font_color="red") st.pyplot(plt) # User input user_question = st.text_area("Enter your question:", placeholder="Example: 'Add 3 and 4. Multiply the result by 2. Divide it by 5.'") if st.button("Submit"): if not user_question.strip(): st.error("Please enter a valid question.") st.stop() st.info("Processing your question...") messages = [HumanMessage(content=user_question)] response = react_graph.invoke({"messages": messages}) st.subheader("Responses") for m in response['messages']: st.write(m.content) st.success("Processing complete!") # Example Questions st.sidebar.subheader("Example Questions") st.sidebar.write("- Add 3 and 4. Multiply the result by 2. Divide it by 5.") st.sidebar.write("- Tell me how many centuries Virat Kohli scored.") st.sidebar.write("- Search for the tallest building in the world.")