forked from aipotheosis-labs/aci-agents
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagent_with_dynamic_tool_discovery_pattern_2.py
More file actions
105 lines (91 loc) · 3.77 KB
/
Copy pathagent_with_dynamic_tool_discovery_pattern_2.py
File metadata and controls
105 lines (91 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import json
import os
from aci import ACI
from aci.meta_functions import ACISearchFunctions, ACIExecuteFunction
from aci.types.functions import FunctionDefinitionFormat
from dotenv import load_dotenv
from openai import OpenAI
from rich import print as rprint
from rich.panel import Panel
load_dotenv()
LINKED_ACCOUNT_OWNER_ID = os.getenv("LINKED_ACCOUNT_OWNER_ID", "")
if not LINKED_ACCOUNT_OWNER_ID:
raise ValueError("LINKED_ACCOUNT_OWNER_ID is not set")
# gets OPENAI_API_KEY from your environment variables
openai = OpenAI()
# gets ACI_API_KEY from your environment variables
aci = ACI()
prompt = (
"You are a helpful assistant with access to a unlimited number of tools via some meta functions: "
"ACI_SEARCH_FUNCTIONS, and ACI_EXECUTE_FUNCTION."
"You can use ACI_SEARCH_FUNCTIONS to find relevant functions across all apps. Try to limit the number of results per request to 1."
"Once you have identified the function you need to use, you can use ACI_EXECUTE_FUNCTION to execute the function provided you have the correct input arguments."
)
# aipolabs meta functions for the LLM to discover the available executale functions dynamically
tools_meta = [
ACISearchFunctions.to_json_schema(FunctionDefinitionFormat.OPENAI),
ACIExecuteFunction.to_json_schema(FunctionDefinitionFormat.OPENAI),
]
def main() -> None:
# Start the LLM processing loop
chat_history: list[dict] = []
while True:
rprint(Panel("Waiting for LLM Output", style="bold blue"))
response = openai.chat.completions.create(
model="gpt-4.1",
messages=[
{
"role": "system",
"content": prompt,
},
{
"role": "user",
"content": "Can you use brave search to find top 5 results about aipolabs ACI?",
},
]
+ chat_history,
tools=tools_meta,
# tool_choice="required", # force the model to generate a tool call
parallel_tool_calls=False,
)
# Process LLM response and potential function call (there can only be at most one function call)
content = response.choices[0].message.content
tool_call = (
response.choices[0].message.tool_calls[0]
if response.choices[0].message.tool_calls
else None
)
if content:
rprint(Panel("LLM Message", style="bold green"))
rprint(content)
chat_history.append({"role": "assistant", "content": content})
# Handle function call if any
if tool_call:
rprint(
Panel(f"Function Call: {tool_call.function.name}", style="bold yellow")
)
rprint(f"arguments: {tool_call.function.arguments}")
chat_history.append({"role": "assistant", "tool_calls": [tool_call]})
result = aci.handle_function_call(
tool_call.function.name,
json.loads(tool_call.function.arguments),
linked_account_owner_id=LINKED_ACCOUNT_OWNER_ID,
allowed_apps_only=True,
format=FunctionDefinitionFormat.OPENAI,
)
rprint(Panel("Function Call Result", style="bold magenta"))
rprint(result)
# Continue loop, feeding the result back to the LLM for further instructions
chat_history.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
}
)
else:
# If there's no further function call, exit the loop
rprint(Panel("Task Completed", style="bold green"))
break
if __name__ == "__main__":
main()