Avery64 commited on
Commit
baabc30
·
verified ·
1 Parent(s): 81917a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -3
app.py CHANGED
@@ -1,8 +1,25 @@
1
  import os
 
2
  import gradio as gr
 
3
  import requests
4
  import inspect
5
  import pandas as pd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  # (Keep Constants as is)
8
  # --- Constants ---
@@ -10,14 +27,118 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
11
  # --- Basic Agent Definition ---
12
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
 
 
 
 
 
 
 
 
 
 
13
  class BasicAgent:
14
  def __init__(self):
 
15
  print("BasicAgent initialized.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def __call__(self, question: str) -> str:
17
  print(f"Agent received question (first 50 chars): {question[:50]}...")
18
- fixed_answer = "This is a default answer."
19
- print(f"Agent returning fixed answer: {fixed_answer}")
20
- return fixed_answer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def run_and_submit_all( profile: gr.OAuthProfile | None):
23
  """
 
1
  import os
2
+ from dotenv import load_dotenv
3
  import gradio as gr
4
+ import re
5
  import requests
6
  import inspect
7
  import pandas as pd
8
+ from typing import TypedDict, Annotated
9
+ from langgraph.graph import StateGraph, START, END
10
+ from langgraph.graph.message import add_messages
11
+ from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage
12
+ from langgraph.prebuilt import tools_condition
13
+ from langchain_community.tools import DuckDuckGoSearchRun
14
+ from langchain_openai import ChatOpenAI
15
+ from langchain_community.tools import WikipediaQueryRun
16
+ from langchain_community.utilities import WikipediaAPIWrapper
17
+ from langchain.tools import tool
18
+ from langchain_core.tools import Tool
19
+ from langgraph.prebuilt import ToolNode, tools_condition
20
+
21
+ load_dotenv()
22
+ os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
23
 
24
  # (Keep Constants as is)
25
  # --- Constants ---
 
27
 
28
  # --- Basic Agent Definition ---
29
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
30
+ @tool
31
+ def python_calc(expr: str) -> str:
32
+ """Safely evaluate a numeric Python expression."""
33
+ allowed = {"__builtins__": {}}
34
+ return str(eval(expr, allowed, {}))
35
+
36
+ class AgentState(TypedDict):
37
+ messages: Annotated[list[AnyMessage], add_messages]
38
+ evidence: list[str]
39
+
40
  class BasicAgent:
41
  def __init__(self):
42
+
43
  print("BasicAgent initialized.")
44
+ # Generate the chat interface, including the tools
45
+ llm = ChatOpenAI(model="gpt-4.1")
46
+ search_tool = DuckDuckGoSearchRun()
47
+ wiki = WikipediaQueryRun(
48
+ api_wrapper=WikipediaAPIWrapper(top_k_results=3, doc_content_chars_max=4000)
49
+ )
50
+ search_tools = [search_tool, wiki]
51
+
52
+ calc_tools = [python_calc]
53
+
54
+ self.retrieve_tools = llm.bind_tools(search_tools)
55
+ self.calc_tools = llm.bind_tools(calc_tools)
56
+
57
+ ## The graph
58
+ builder = StateGraph(AgentState)
59
+
60
+ # Define nodes: these do the work
61
+ builder.add_node("retriever", self.retriever)
62
+ builder.add_node("retrieve_tools", ToolNode(search_tools))
63
+ builder.add_node("solver", self.solver)
64
+ builder.add_node("calc_tools", ToolNode(calc_tools))
65
+
66
+ # Define edges: these determine how the control flow moves
67
+ # START → retriever
68
+ builder.add_edge(START, "retriever")
69
+
70
+ # retriever tool loop
71
+ builder.add_conditional_edges(
72
+ "retriever",
73
+ tools_condition,
74
+ {
75
+ "tools": "retrieve_tools", # if LLM emitted a tool call
76
+ END: "solver", # if no tool call
77
+ },
78
+ )
79
+ builder.add_edge("retrieve_tools", "retriever")
80
+
81
+ builder.add_conditional_edges(
82
+ "solver",
83
+ tools_condition,
84
+ {
85
+ "tools": "calc_tools",
86
+ END: END,
87
+ },
88
+ )
89
+ builder.add_edge("calc_tools", "solver")
90
+
91
+ self.agent = builder.compile()
92
+
93
  def __call__(self, question: str) -> str:
94
  print(f"Agent received question (first 50 chars): {question[:50]}...")
95
+ messages = [HumanMessage(content=question)]
96
+ response = self.agent.invoke({"messages": messages})
97
+ print(response["messages"][-1].content)
98
+ return response["messages"][-1].content
99
+
100
+ def retriever(self, state: AgentState):
101
+ system = SystemMessage(
102
+ content=(
103
+ "You are a retrieval agent for the GAIA benchmark.\n"
104
+ "Your task is to gather factual evidence needed to answer the question.\n"
105
+ "Use search or Wikipedia tools if helpful.\n"
106
+ "Return relevant factual text only.\n"
107
+ "Do NOT compute, infer, or answer the question.\n"
108
+ "Once you have sufficient evidence, STOP and do not call more tools."
109
+ )
110
+ )
111
+
112
+ msg = self.retrieve_tools.invoke([system] + state["messages"])
113
+ return {
114
+ "messages": [msg],
115
+ "evidence": state.get("evidence", []) + [msg.content],
116
+ }
117
+
118
+ def solver(self, state: AgentState):
119
+ system = SystemMessage(
120
+ content=(
121
+ "You are solving a GAIA benchmark question.\n"
122
+ "Determine the final answer based ONLY on the evidence.\n"
123
+ "The final answer must be either:\n"
124
+ "• a single number, OR\n"
125
+ "• a single word (no spaces), OR\n"
126
+ "• a comma-separated list of numbers (no spaces).\n\n"
127
+ "Output ONLY the final answer.\n"
128
+ "Do NOT include explanations or extra text.\n"
129
+ "If the answer cannot be determined with certainty, output 0.\n"
130
+ "You MUST NOT call the calculator more than once."
131
+ )
132
+ )
133
+
134
+ human = HumanMessage(
135
+ content="\n\n".join(state["evidence"])
136
+ )
137
+
138
+ msg = self.calc_tools.invoke([system, human])
139
+ return {
140
+ "messages": [msg],
141
+ }
142
 
143
  def run_and_submit_all( profile: gr.OAuthProfile | None):
144
  """