EtienneB commited on
Commit
7da4369
·
1 Parent(s): 81917a3

starting final assignment, added some tools

Browse files
Files changed (5) hide show
  1. agent.py +63 -0
  2. app.py +10 -4
  3. requirements.txt +8 -1
  4. retriever.py +1 -0
  5. tools.py +195 -0
agent.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Annotated, TypedDict
2
+
3
+ from langchain_core.messages import AIMessage, AnyMessage, HumanMessage
4
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
5
+ from langgraph.graph import START, StateGraph
6
+ from langgraph.graph.message import add_messages
7
+ from langgraph.prebuilt import ToolNode, tools_condition
8
+
9
+ from retriever import guest_info_tool
10
+ from tools import (absolute, add, divide, exponential, floor_divide, logarithm,
11
+ modulus, multiply, power, square_root, subtract, web_search)
12
+
13
+ # Generate the chat interface, including the tools
14
+ llm = HuggingFaceEndpoint(
15
+ repo_id="Qwen/Qwen2.5-Coder-32B-Instruct",
16
+ huggingfacehub_api_token=HUGGINGFACEHUB_API_TOKEN,
17
+ )
18
+
19
+ chat = ChatHuggingFace(llm=llm, verbose=True)
20
+ tools = [, weather_info_tool, hub_stats_tool]
21
+ tools = [
22
+ multiply,
23
+ add,
24
+ subtract,
25
+ power,
26
+ divide,
27
+ modulus,
28
+ square_root,
29
+ floor_divide,
30
+ absolute,
31
+ logarithm,
32
+ exponential,
33
+ web_search,
34
+ ]
35
+
36
+ chat_with_tools = chat.bind_tools(tools)
37
+
38
+ # Generate the AgentState and Agent graph
39
+ class AgentState(TypedDict):
40
+ messages: Annotated[list[AnyMessage], add_messages]
41
+
42
+ def assistant(state: AgentState):
43
+ return {
44
+ "messages": [chat_with_tools.invoke(state["messages"])],
45
+ }
46
+
47
+ ## The graph
48
+ builder = StateGraph(AgentState)
49
+
50
+ # Define nodes: these do the work
51
+ builder.add_node("assistant", assistant)
52
+ builder.add_node("tools", ToolNode(tools))
53
+
54
+ # Define edges: these determine how the control flow moves
55
+ builder.add_edge(START, "assistant")
56
+ builder.add_conditional_edges(
57
+ "assistant",
58
+ # If the latest message requires a tool, route to tools
59
+ # Otherwise, provide a direct response
60
+ tools_condition,
61
+ )
62
+ builder.add_edge("tools", "assistant")
63
+ alfred = builder.compile()
app.py CHANGED
@@ -1,8 +1,11 @@
 
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 ---
@@ -13,11 +16,14 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
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 inspect
2
  import os
3
+
4
  import gradio as gr
 
 
5
  import pandas as pd
6
+ import requests
7
+ from agent import build_graph
8
+ from langchain_core.messages import HumanMessage
9
 
10
  # (Keep Constants as is)
11
  # --- Constants ---
 
16
  class BasicAgent:
17
  def __init__(self):
18
  print("BasicAgent initialized.")
19
+ self.graph = build_graph()
20
  def __call__(self, question: str) -> str:
21
  print(f"Agent received question (first 50 chars): {question[:50]}...")
22
  fixed_answer = "This is a default answer."
23
+ messages = [HumanMessage(content=question)]
24
+ messages = self.graph.invoke({"messages": messages})
25
+ answer = messages['messages'][-1].content
26
+ return answer[14:]
27
 
28
  def run_and_submit_all( profile: gr.OAuthProfile | None):
29
  """
requirements.txt CHANGED
@@ -1,2 +1,9 @@
1
  gradio
2
- requests
 
 
 
 
 
 
 
 
1
  gradio
2
+ requests
3
+
4
+ # LangChain dependencies
5
+ langchain-core
6
+
7
+
8
+ #other
9
+ # inspect
retriever.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Nothing
tools.py ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+
3
+ from langchain_community.tools import DuckDuckGoSearchRun
4
+ from langchain_core.tools import tool
5
+
6
+
7
+ @tool
8
+ def multiply(a: int, b:int) -> int:
9
+ """Multiplies two integers and returns the product.
10
+
11
+ Args:
12
+ a (int): The first integer.
13
+ b (int): The second integer.
14
+
15
+ Returns:
16
+ int: The product of the two input integers.
17
+ """
18
+ return a * b
19
+
20
+
21
+ @tool
22
+ def add(a: int, b:int) -> int:
23
+ """Adds two integers and returns the sum.
24
+
25
+ Args:
26
+ a (int): The first integer.
27
+ b (int): The second integer.
28
+
29
+ Returns:
30
+ int: The sum of the two input integers.
31
+ """
32
+ return a + b
33
+
34
+
35
+ @tool
36
+ def power(a: float, b: float) -> float:
37
+ """Raises a number to the power of another.
38
+
39
+ Args:
40
+ a (float): The base number.
41
+ b (float): The exponent.
42
+
43
+ Returns:
44
+ float: The result of raising `a` to the power of `b`.
45
+ """
46
+ return a ** b
47
+
48
+
49
+ @tool
50
+ def subtract(a: float, b: float) -> float:
51
+ """Subtracts the second number from the first.
52
+
53
+ Args:
54
+ a (float): The number from which to subtract.
55
+ b (float): The number to subtract.
56
+
57
+ Returns:
58
+ float: The result of `a` minus `b`.
59
+ """
60
+ return a - b
61
+
62
+
63
+ @tool
64
+ def divide(a: float, b: float) -> float:
65
+ """Divides one number by another.
66
+
67
+ Args:
68
+ a (float): The numerator.
69
+ b (float): The denominator.
70
+
71
+ Returns:
72
+ float: The result of `a` divided by `b`.
73
+
74
+ Raises:
75
+ ValueError: If `b` is zero.
76
+ """
77
+ if b == 0:
78
+ raise ValueError("Divide by zero is not allowed")
79
+ return a / b
80
+
81
+
82
+ @tool
83
+ def modulus(a: int, b: int) -> int:
84
+ """Returns the remainder of the division of two integers.
85
+
86
+ Args:
87
+ a (int): The dividend.
88
+ b (int): The divisor.
89
+
90
+ Returns:
91
+ int: The remainder when `a` is divided by `b`.
92
+
93
+ Raises:
94
+ ValueError: If `b` is zero.
95
+ """
96
+ if b == 0:
97
+ raise ValueError("Modulus by zero is not allowed")
98
+ return a % b
99
+
100
+
101
+ @tool
102
+ def square_root(x: float) -> float:
103
+ """Returns the square root of a number.
104
+
105
+ Args:
106
+ x (float): The input number. Must be non-negative.
107
+
108
+ Returns:
109
+ float: The square root of `x`.
110
+
111
+ Raises:
112
+ ValueError: If `x` is negative.
113
+ """
114
+ if x < 0:
115
+ raise ValueError("Square root of negative number is not allowed")
116
+ return math.sqrt(x)
117
+
118
+
119
+ @tool
120
+ def floor_divide(a: int, b: int) -> int:
121
+ """Performs integer division (floor division) of two numbers.
122
+
123
+ Args:
124
+ a (int): The dividend.
125
+ b (int): The divisor.
126
+
127
+ Returns:
128
+ int: The floor of the quotient.
129
+ Returns the quotient rounded down to the nearest integer.
130
+
131
+ Raises:
132
+ ValueError: If `b` is zero.
133
+ """
134
+ if b == 0:
135
+ raise ValueError("Division by zero is not allowed")
136
+ return a // b
137
+
138
+
139
+ @tool
140
+ def absolute(x: float) -> float:
141
+ """Returns the absolute value of a number.
142
+
143
+ Args:
144
+ x (float): The input number.
145
+
146
+ Returns:
147
+ float: The absolute value of `x`.
148
+ """
149
+ return abs(x)
150
+
151
+
152
+ @tool
153
+ def logarithm(x: float, base: float = math.e) -> float:
154
+ """Returns the logarithm of a number with a given base.
155
+
156
+ Args:
157
+ x (float): The number to take the logarithm of. Must be positive.
158
+ base (float): The logarithmic base. Must be positive and not equal to 1.
159
+
160
+ Returns:
161
+ float: The logarithm of `x` to the given base.
162
+
163
+ Raises:
164
+ ValueError: If `x <= 0` or `base <= 0` or `base == 1`.
165
+ """
166
+ if x <= 0 or base <= 0 or base == 1:
167
+ raise ValueError("Invalid input for logarithm")
168
+ return math.log(x, base)
169
+
170
+
171
+ @tool
172
+ def exponential(x: float) -> float:
173
+ """Returns e raised to the power of `x`.
174
+
175
+ Args:
176
+ x (float): The exponent.
177
+
178
+ Returns:
179
+ float: The value of e^x.
180
+ """
181
+ return math.exp(x)
182
+
183
+ @tool
184
+ def web_search(query: str) -> str:
185
+ """Performs a DuckDuckGo search for the given query and returns the results.
186
+
187
+ Args:
188
+ query (str): The search query.
189
+
190
+ Returns:
191
+ str: The top search results as a string.
192
+ """
193
+ search_tool = DuckDuckGoSearchRun()
194
+ return search_tool.invoke(query)
195
+