Spaces:
Running
Running
Upload 2 files
Browse files- app.py +117 -1
- requirements.txt +1 -0
app.py
CHANGED
|
@@ -4,6 +4,9 @@ import gradio as gr
|
|
| 4 |
import uuid
|
| 5 |
from pprint import pprint
|
| 6 |
import chromadb
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
#-----------------------
|
| 9 |
# Setup
|
|
@@ -226,6 +229,99 @@ collection.add(
|
|
| 226 |
|
| 227 |
pprint(collection.get())
|
| 228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
#-----------------------
|
| 230 |
# System Message
|
| 231 |
#-----------------------
|
|
@@ -274,10 +370,30 @@ def respond_ai(message, history):
|
|
| 274 |
#Call LLM
|
| 275 |
response = client.chat.completions.create(
|
| 276 |
model="gpt-4.1-mini",
|
| 277 |
-
messages=messages
|
|
|
|
| 278 |
)
|
| 279 |
|
| 280 |
message = response.choices[0].message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
return(message.content)
|
| 282 |
|
| 283 |
#-----------------------
|
|
|
|
| 4 |
import uuid
|
| 5 |
from pprint import pprint
|
| 6 |
import chromadb
|
| 7 |
+
import json
|
| 8 |
+
import requests
|
| 9 |
+
import random
|
| 10 |
|
| 11 |
#-----------------------
|
| 12 |
# Setup
|
|
|
|
| 229 |
|
| 230 |
pprint(collection.get())
|
| 231 |
|
| 232 |
+
#-----------------------
|
| 233 |
+
# Tools
|
| 234 |
+
#-----------------------
|
| 235 |
+
tools = []
|
| 236 |
+
|
| 237 |
+
#### 1. Import pushover keys
|
| 238 |
+
pushover_user = os.getenv("PUSHOVER_USER")
|
| 239 |
+
pushover_token = os.getenv("PUSHOVER_TOKEN")
|
| 240 |
+
pushover_url = "https://api.pushover.net/1/messages.json" # Pushover API endpoint for sending messages
|
| 241 |
+
# Create send_notification function to send a notification using Pushover API
|
| 242 |
+
#create a function to send a notification using Pushover API
|
| 243 |
+
def send_notification(message:str):
|
| 244 |
+
payload = {"user": pushover_user, "token": pushover_token, "message": message}
|
| 245 |
+
requests.post(pushover_url, data=payload)
|
| 246 |
+
|
| 247 |
+
### 3. Describe Pushover as an LLM tool
|
| 248 |
+
#creating a function to explain LLM when to use the tool and how to call it, including the expected input and output formats. This will help the LLM understand how to use the tool effectively and provide the necessary information for successful execution.
|
| 249 |
+
send_notification_function = {
|
| 250 |
+
#creating dictionary
|
| 251 |
+
"name": "send_notification",
|
| 252 |
+
"description": "Sends a push notification to the real-world version of you using Pushover on mobile. Use this if the user needs to alert the real-world version of you.",
|
| 253 |
+
"parameters": {
|
| 254 |
+
# way LLM should format the input when calling the function / JSON theobject with key-value pairs corresponding to the function's parameters
|
| 255 |
+
"type": "object",
|
| 256 |
+
"properties": {
|
| 257 |
+
"message": {
|
| 258 |
+
"type": "string",
|
| 259 |
+
"description": "The content of the notification message to be sent to the user's device."
|
| 260 |
+
}
|
| 261 |
+
},
|
| 262 |
+
"required": ["message"]
|
| 263 |
+
}
|
| 264 |
+
}
|
| 265 |
+
### 3. Add Pushover to the list of tools for the LLM
|
| 266 |
+
# This is the list of tools that the LLM can use to interact with the environment. Each tool is defined by a dictionary that includes its name, description, and parameters. The LLM will use this information to determine when and how to call the tool during the conversation.
|
| 267 |
+
# we have just one tool in our list, but we could add more tools in the future by appending additional dictionaries to this list.
|
| 268 |
+
tools.append({"type": "function", "function": send_notification_function})
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
#simulates rolling a single six-sided die
|
| 272 |
+
def dice_roll():
|
| 273 |
+
result = random.randint(1,6)
|
| 274 |
+
return result
|
| 275 |
+
|
| 276 |
+
#describe function for LLM
|
| 277 |
+
#dice role functionality
|
| 278 |
+
roll_dice_function = {
|
| 279 |
+
"name": "dice_roll",
|
| 280 |
+
"description": "Simulates rolling a single six-sided die and returns the result. Use this when the user wants to roll a die for games, decisions or random number generation",
|
| 281 |
+
"parameters": {
|
| 282 |
+
# way LLM should format the input when calling the function / JSON theobject with key-value pairs corresponding to the function's parameters
|
| 283 |
+
"type": "object",
|
| 284 |
+
"properties": {},
|
| 285 |
+
"required": []
|
| 286 |
+
}
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
#Add function to list of tools of LLM
|
| 290 |
+
tools.append({"type": "function", "function": roll_dice_function})
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
#-----------------------
|
| 294 |
+
# Tool Call Handler
|
| 295 |
+
#-----------------------
|
| 296 |
+
def handle_tool_call(tool_calls):
|
| 297 |
+
tool_results = []
|
| 298 |
+
|
| 299 |
+
for tool_call in tool_calls:
|
| 300 |
+
function_name = tool_call.function.name
|
| 301 |
+
args = json.loads(tool_call.function.arguments)
|
| 302 |
+
#print(f"Calling funvtion {function_name}") #for future debugging
|
| 303 |
+
#Route to the appropriate function based on function name
|
| 304 |
+
if function_name == "send_notification":
|
| 305 |
+
#acctually send the notification, i.e. call the tool
|
| 306 |
+
send_notification(args["message"])
|
| 307 |
+
content = f"Notification sent: {args['message']}"
|
| 308 |
+
elif function_name == "dice_roll":
|
| 309 |
+
content = f"Rolled: {dice_roll()}"
|
| 310 |
+
#elif function_name == "insert_function_name_3":
|
| 311 |
+
# content = insert_function_name_3(args["message"])
|
| 312 |
+
else:
|
| 313 |
+
content = f"Uknown function: {function_name}"
|
| 314 |
+
#print(f"Sent notification with message: {args['message']}")
|
| 315 |
+
tool_call_result = {
|
| 316 |
+
"role": "tool",
|
| 317 |
+
"content": content,
|
| 318 |
+
"tool_call_id" : tool_call.id
|
| 319 |
+
}
|
| 320 |
+
tool_results.append(tool_call_result)
|
| 321 |
+
#return what to add to our "context (about tool call results), a dictionary "
|
| 322 |
+
return tool_results
|
| 323 |
+
|
| 324 |
+
|
| 325 |
#-----------------------
|
| 326 |
# System Message
|
| 327 |
#-----------------------
|
|
|
|
| 370 |
#Call LLM
|
| 371 |
response = client.chat.completions.create(
|
| 372 |
model="gpt-4.1-mini",
|
| 373 |
+
messages=messages,
|
| 374 |
+
tools=tools
|
| 375 |
)
|
| 376 |
|
| 377 |
message = response.choices[0].message
|
| 378 |
+
|
| 379 |
+
#check if model wants to call a tool
|
| 380 |
+
while message.tool_calls:
|
| 381 |
+
pprint(message.tool_calls)
|
| 382 |
+
#..handle tool call
|
| 383 |
+
tool_result = handle_tool_call(message.tool_calls) #whole list of tool calls on purpose
|
| 384 |
+
#..add message to "context", i.e. messages
|
| 385 |
+
messages.append(message)
|
| 386 |
+
#..add information about the tool call to the context for the LLM to learn from i.e. messages
|
| 387 |
+
messages.extend(tool_result) #cheanged from append() to extend() when we switched to multiple tool call handling
|
| 388 |
+
|
| 389 |
+
# ..invoke the LLM one more time to get it's updated response and provide context with tool calling
|
| 390 |
+
response = client.chat.completions.create(
|
| 391 |
+
model="gpt-4.1-mini",
|
| 392 |
+
messages=messages,
|
| 393 |
+
tools=tools # consecutive tool call will be considered by LLM
|
| 394 |
+
)
|
| 395 |
+
message = response.choices[0].message
|
| 396 |
+
|
| 397 |
return(message.content)
|
| 398 |
|
| 399 |
#-----------------------
|
requirements.txt
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
openai
|
| 2 |
gradio
|
| 3 |
chromadb
|
|
|
|
|
|
| 1 |
openai
|
| 2 |
gradio
|
| 3 |
chromadb
|
| 4 |
+
requests
|