wt002 commited on
Commit
8f90b3d
·
verified ·
1 Parent(s): 1623ee4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -1
app.py CHANGED
@@ -4,7 +4,17 @@ import requests
4
  import inspect
5
  import pandas as pd
6
  from langchain_core.messages import HumanMessage
7
- from agent import BasicAgent
 
 
 
 
 
 
 
 
 
 
8
 
9
  # (Keep Constants as is)
10
  # --- Constants ---
@@ -12,6 +22,29 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
12
 
13
  # --- Basic Agent Definition ---
14
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  class BasicAgent:
16
  """A langgraph agent."""
17
  def __init__(self):
@@ -26,6 +59,67 @@ class BasicAgent:
26
  answer = messages['messages'][-1].content
27
  return answer[14:]
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  def run_and_submit_all( profile: gr.OAuthProfile | None):
30
  """
31
  Fetches all questions, runs the BasicAgent on them, submits all answers,
 
4
  import inspect
5
  import pandas as pd
6
  from langchain_core.messages import HumanMessage
7
+ from typing import TypedDict, Annotated, Sequence, Dict, Any, List
8
+ from langchain_core.messages import BaseMessage, HumanMessage
9
+ from langchain_core.tools import tool
10
+ from langchain_openai import ChatOpenAI
11
+ from langgraph.graph import END, StateGraph
12
+ from langgraph.prebuilt import ToolNode
13
+ from langchain_community.tools import DuckDuckGoSearchResults
14
+ from langchain_community.utilities import WikipediaAPIWrapper
15
+ from langchain.agents import create_tool_calling_agent, AgentExecutor
16
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
17
+ import operator
18
 
19
  # (Keep Constants as is)
20
  # --- Constants ---
 
22
 
23
  # --- Basic Agent Definition ---
24
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
25
+
26
+
27
+ class AgentState(TypedDict):
28
+ messages: Annotated[Sequence[BaseMessage], operator.add]
29
+ sender: str
30
+
31
+ @tool
32
+ def wikipedia_search(query: str) -> str:
33
+ """Search Wikipedia for information."""
34
+ return WikipediaAPIWrapper().run(query)
35
+
36
+ @tool
37
+ def web_search(query: str, num_results: int = 3) -> list:
38
+ """Search the web for current information."""
39
+ return DuckDuckGoSearchResults(num_results=num_results).run(query)
40
+
41
+ @tool
42
+ def calculate(expression: str) -> str:
43
+ """Evaluate mathematical expressions."""
44
+ from langchain_experimental.utilities import PythonREPL
45
+ python_repl = PythonREPL()
46
+ return python_repl.run(expression)
47
+
48
  class BasicAgent:
49
  """A langgraph agent."""
50
  def __init__(self):
 
59
  answer = messages['messages'][-1].content
60
  return answer[14:]
61
 
62
+
63
+ def _build_workflow(self) -> StateGraph:
64
+ """Build and return the compiled workflow"""
65
+ workflow = StateGraph(AgentState)
66
+
67
+ workflow.add_node("agent", self._run_agent)
68
+ workflow.add_node("tools", ToolNode(self.tools))
69
+
70
+ workflow.set_entry_point("agent")
71
+ workflow.add_conditional_edges(
72
+ "agent",
73
+ self._should_continue,
74
+ {"continue": "tools", "end": END}
75
+ )
76
+ workflow.add_edge("tools", "agent")
77
+
78
+ return workflow.compile()
79
+
80
+ def _run_agent(self, state: AgentState) -> Dict[str, Any]:
81
+ """Execute the agent"""
82
+ response = self.agent_executor.invoke({"messages": state["messages"]})
83
+ return {"messages": [response["output"]]}
84
+
85
+ def _should_continue(self, state: AgentState) -> str:
86
+ """Determine if the workflow should continue"""
87
+ last_message = state["messages"][-1]
88
+ return "continue" if last_message.additional_kwargs.get("tool_calls") else "end"
89
+
90
+ def __call__(self, query: str) -> Dict[str, Any]:
91
+ """Process a user query"""
92
+ state = AgentState(messages=[HumanMessage(content=query)], sender="user")
93
+
94
+ for output in self.workflow.stream(state):
95
+ for key, value in output.items():
96
+ if key == "messages":
97
+ for message in value:
98
+ if isinstance(message, BaseMessage):
99
+ return {
100
+ "response": message.content,
101
+ "sources": self._extract_sources(state["messages"]),
102
+ "steps": self._extract_steps(state["messages"])
103
+ }
104
+ return {"response": "No response generated", "sources": [], "steps": []}
105
+
106
+ def _extract_sources(self, messages: Sequence[BaseMessage]) -> List[str]:
107
+ """Extract sources from tool messages"""
108
+ return [
109
+ f"{msg.additional_kwargs.get('name', 'unknown')}: {msg.content}"
110
+ for msg in messages
111
+ if hasattr(msg, 'additional_kwargs') and 'name' in msg.additional_kwargs
112
+ ]
113
+
114
+ def _extract_steps(self, messages: Sequence[BaseMessage]) -> List[str]:
115
+ """Extract reasoning steps"""
116
+ steps = []
117
+ for msg in messages:
118
+ if hasattr(msg, 'additional_kwargs') and 'tool_calls' in msg.additional_kwargs:
119
+ for call in msg.additional_kwargs['tool_calls']:
120
+ steps.append(f"Used {call['function']['name']}: {call['function']['arguments']}")
121
+ return steps
122
+
123
  def run_and_submit_all( profile: gr.OAuthProfile | None):
124
  """
125
  Fetches all questions, runs the BasicAgent on them, submits all answers,