mrhenu commited on
Commit
10d3577
·
verified ·
1 Parent(s): b314ecf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -19
app.py CHANGED
@@ -4,8 +4,8 @@ import requests
4
  import pandas as pd
5
  from typing import TypedDict, Annotated, Sequence
6
  import operator
7
- from langchain_core.messages import BaseMessage, HumanMessage
8
- from langchain_community.tools import DuckDuckGoSearchRun
9
  from langchain_openai import ChatOpenAI
10
  from langgraph.graph import StateGraph, END
11
  from langgraph.prebuilt import ToolNode, tools_condition
@@ -16,22 +16,68 @@ from langgraph.prebuilt import ToolNode, tools_condition
16
  class AgentState(TypedDict):
17
  messages: Annotated[Sequence[BaseMessage], operator.add]
18
 
19
- # This function builds our final, robust agent using LangGraph and OpenAI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def create_langgraph_agent():
21
  print("Initializing LangGraph Agent with OpenAI...")
22
 
23
- # 1. Set up the LLM (The "Brain") using OpenAI's GPT-3.5 Turbo
24
- llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
25
 
26
- # 2. Define the Tools, now using DuckDuckGo
27
- tools = [DuckDuckGoSearchRun()]
28
  llm_with_tools = llm.bind_tools(tools)
29
  print("LLM and tools initialized.")
30
 
31
- # 3. Define the Graph Nodes
 
 
 
 
 
 
 
32
  def agent_node(state):
33
  print("Calling agent node...")
34
- response = llm_with_tools.invoke(state["messages"])
 
 
35
  return {"messages": [response]}
36
 
37
  tool_node = ToolNode(tools)
@@ -41,7 +87,6 @@ def create_langgraph_agent():
41
  graph = StateGraph(AgentState)
42
  graph.add_node("agent", agent_node)
43
  graph.add_node("tools", tool_node)
44
-
45
  graph.set_entry_point("agent")
46
  graph.add_conditional_edges("agent", tools_condition)
47
  graph.add_edge("tools", "agent")
@@ -51,12 +96,20 @@ def create_langgraph_agent():
51
  print("LangGraph agent compiled and ready.")
52
  return app
53
 
54
- # This function runs the agent for a single question.
55
- def run_agent(agent_executor, question: str) -> str:
56
  print(f"Agent received question: {question}")
57
  try:
58
- response = agent_executor.invoke({"messages": [HumanMessage(content=question)]})
59
- final_answer = response['messages'][-1].content
 
 
 
 
 
 
 
 
60
  except Exception as e:
61
  print(f"Error during agent execution: {e}")
62
  final_answer = f"Error: Agent failed to execute. {e}"
@@ -71,8 +124,9 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
71
  return "Please Login to Hugging Face with the button.", None
72
  username = f"{profile.username}"
73
 
74
- if not os.getenv("OPENAI_API_KEY"):
75
- return "OpenAI API key not found. Please set the OPENAI_API_KEY secret in your Space settings.", None
 
76
 
77
  try:
78
  agent_executor = create_langgraph_agent()
@@ -93,13 +147,13 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
93
  for item in questions_data:
94
  task_id, question_text = item.get("task_id"), item.get("question")
95
  if task_id and question_text:
96
- submitted_answer = run_agent(agent_executor, question_text)
97
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
98
 
99
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
100
  submit_url = f"https://agents-course-unit4-scoring.hf.space/submit"
101
  try:
102
- response = requests.post(submit_url, json=submission_data, timeout=120)
103
  response.raise_for_status()
104
  result_data = response.json()
105
  final_status = (
@@ -115,7 +169,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
115
 
116
  # Gradio Interface
117
  with gr.Blocks() as demo:
118
- gr.Markdown("# Agent Evaluation Runner (OpenAI + DuckDuckGo)")
119
  gr.LoginButton()
120
  run_button = gr.Button("Run Evaluation & Submit All Answers")
121
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
4
  import pandas as pd
5
  from typing import TypedDict, Annotated, Sequence
6
  import operator
7
+ from langchain_core.messages import BaseMessage, HumanMessage, ToolMessage
8
+ from langchain.tools import tool
9
  from langchain_openai import ChatOpenAI
10
  from langgraph.graph import StateGraph, END
11
  from langgraph.prebuilt import ToolNode, tools_condition
 
16
  class AgentState(TypedDict):
17
  messages: Annotated[Sequence[BaseMessage], operator.add]
18
 
19
+ # NEW: Custom tool for downloading files from the course API
20
+ @tool
21
+ def download_file(task_id: str) -> str:
22
+ """
23
+ Downloads a file associated with a specific task_id from the course API.
24
+ The file will be saved in the /tmp/ directory.
25
+ Use this tool when a question mentions an attached file (e.g., image, excel, audio).
26
+ """
27
+ try:
28
+ # NOTE: This assumes the Space is running on the Hugging Face platform
29
+ # and can access the scoring API directly.
30
+ file_url = f"https://agents-course-unit4-scoring.hf.space/files/{task_id}"
31
+ response = requests.get(file_url)
32
+ response.raise_for_status()
33
+
34
+ # Extract filename from headers, or default to task_id
35
+ content_disposition = response.headers.get('content-disposition')
36
+ if content_disposition:
37
+ parts = content_disposition.split(';')
38
+ for part in parts:
39
+ if 'filename=' in part:
40
+ filename = part.split('=')[1].strip('"')
41
+ break
42
+ else:
43
+ # Fallback filename if header is not present
44
+ # This is a simplification; a real app might need better content-type handling
45
+ filename = task_id
46
+
47
+ # Save the file to a temporary directory within the Space
48
+ save_path = f"/tmp/{filename}"
49
+ with open(save_path, "wb") as f:
50
+ f.write(response.content)
51
+
52
+ return f"Successfully downloaded file for task {task_id}. It is available at path: {save_path}"
53
+ except Exception as e:
54
+ return f"An error occurred while downloading the file: {str(e)}"
55
+
56
+ # This function builds our final, robust agent.
57
  def create_langgraph_agent():
58
  print("Initializing LangGraph Agent with OpenAI...")
59
 
60
+ # 1. Set up the LLM (The "Brain")
61
+ llm = ChatOpenAI(model="gpt-4o", temperature=0) # Switched to gpt-4o for better performance
62
 
63
+ # 2. Define the Tools, including our new file downloader
64
+ tools = [TavilySearchResults(max_results=3), download_file]
65
  llm_with_tools = llm.bind_tools(tools)
66
  print("LLM and tools initialized.")
67
 
68
+ # 3. Define the agent's logic (the "agent" node)
69
+ # NEW: We are using a much more specific system prompt based on the GAIA paper
70
+ system_prompt = """You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
71
+ YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings.
72
+ If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise.
73
+ If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise.
74
+ If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string."""
75
+
76
  def agent_node(state):
77
  print("Calling agent node...")
78
+ # Add the system prompt to the beginning of the conversation
79
+ messages_with_system_prompt = [("system", system_prompt)] + state["messages"]
80
+ response = llm_with_tools.invoke(messages_with_system_prompt)
81
  return {"messages": [response]}
82
 
83
  tool_node = ToolNode(tools)
 
87
  graph = StateGraph(AgentState)
88
  graph.add_node("agent", agent_node)
89
  graph.add_node("tools", tool_node)
 
90
  graph.set_entry_point("agent")
91
  graph.add_conditional_edges("agent", tools_condition)
92
  graph.add_edge("tools", "agent")
 
96
  print("LangGraph agent compiled and ready.")
97
  return app
98
 
99
+ # This function runs the agent and extracts the final answer.
100
+ def run_agent(agent_executor, question: str, task_id: str) -> str:
101
  print(f"Agent received question: {question}")
102
  try:
103
+ # Pass the task_id to the agent's input so the file downloader can use it
104
+ response = agent_executor.invoke({"messages": [HumanMessage(content=f"Task ID: {task_id}\n\nQuestion: {question}")]})
105
+
106
+ # NEW: Extract only the part after "FINAL ANSWER:"
107
+ raw_answer = response['messages'][-1].content
108
+ if "FINAL ANSWER:" in raw_answer:
109
+ final_answer = raw_answer.split("FINAL ANSWER:")[-1].strip()
110
+ else:
111
+ final_answer = raw_answer # Fallback if the model doesn't follow the format
112
+
113
  except Exception as e:
114
  print(f"Error during agent execution: {e}")
115
  final_answer = f"Error: Agent failed to execute. {e}"
 
124
  return "Please Login to Hugging Face with the button.", None
125
  username = f"{profile.username}"
126
 
127
+ # API key checks
128
+ if not os.getenv("TAVILY_API_KEY") or not os.getenv("OPENAI_API_KEY"):
129
+ return "One or more API keys (TAVILY_API_KEY, OPENAI_API_KEY) are not set. Please set them in your Space secrets.", None
130
 
131
  try:
132
  agent_executor = create_langgraph_agent()
 
147
  for item in questions_data:
148
  task_id, question_text = item.get("task_id"), item.get("question")
149
  if task_id and question_text:
150
+ submitted_answer = run_agent(agent_executor, question_text, task_id)
151
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
152
 
153
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
154
  submit_url = f"https://agents-course-unit4-scoring.hf.space/submit"
155
  try:
156
+ response = requests.post(submit_url, json=submission_data, timeout=180) # Increased timeout for gpt-4
157
  response.raise_for_status()
158
  result_data = response.json()
159
  final_status = (
 
169
 
170
  # Gradio Interface
171
  with gr.Blocks() as demo:
172
+ gr.Markdown("# Agent Evaluation Runner (GPT-4o + LangGraph)")
173
  gr.LoginButton()
174
  run_button = gr.Button("Run Evaluation & Submit All Answers")
175
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)