-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathmain.py
257 lines (214 loc) · 10 KB
/
main.py
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
import os
import autogen
# IMPORTS
import copy
from typing import Any, Dict
from autogen import (
AFTER_WORK,
ON_CONDITION,
AfterWorkOption,
SwarmAgent,
SwarmResult,
UserProxyAgent,
initiate_swarm_chat,
)
from autogen.agentchat.contrib.graph_rag.document import Document, DocumentType
from graphrag_sdk.models.openai import OpenAiGenerativeModel
from autogen.agentchat.contrib.graph_rag.falkor_graph_query_engine import (
FalkorGraphQueryEngine,
)
from autogen.agentchat.contrib.graph_rag.falkor_graph_rag_capability import (
FalkorGraphRagCapability,
)
# local file imports
from ontology import get_trip_ontology
from google_map_platforms import Itinerary, update_itinerary_with_travel_times
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
# 1. Initialize the LLM Configuration
# Option 1: Load the configuration file
config_path = "OAI_CONFIG_LIST"
config_list = autogen.config_list_from_json(
config_path, filter_dict={"model": ["gpt-4o"]}
)
# Option 2: Load the keys directly
# config_list = [
# {
# "model": "gpt-4o",
# "api_key": open("...", "r").read(),
# }
# ]
llm_config = {"config_list": config_list, "timeout": 120}
os.environ["OPENAI_API_KEY"] = config_list[0][
"api_key"
] # Put the OpenAI API key into the environment
# TODO: configure the Google API key
# os.environ["GOOGLE_MAP_API_KEY"] = open("<google_api_key_path>", "r").read()
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
# 2. Initialize the FalkorDB GraphRAG
input_paths = [
"./trip_planner_data/attractions.json",
"./trip_planner_data/cities.json",
"./trip_planner_data/restaurants.json",
]
input_documents = [
Document(doctype=DocumentType.TEXT, path_or_url=input_path)
for input_path in input_paths
]
# Get the ontology
trip_data_ontology = get_trip_ontology()
# Create FalkorGraphQueryEngine
query_engine = FalkorGraphQueryEngine(
name="trip_data",
host="0.0.0.0", # Change
port=6379, # if needed
ontology=trip_data_ontology,
model=OpenAiGenerativeModel("gpt-4o"),
)
# Ingest data and initialize the database
query_engine.init_db(input_doc=input_documents)
# If you have already ingested and created the database, you can use this connect_db instead of init_db
# query_engine.connect_db()
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
# Create Swarm Agents and start the conversation
trip_context = {
"itinerary_confirmed": False,
"itinerary": "",
"structured_itinerary": None,
}
def mark_itinerary_as_complete(
final_itinerary: str, context_variables: Dict[str, Any]
) -> SwarmResult:
"""Store and mark our itinerary as accepted by the customer."""
context_variables["itinerary_confirmed"] = True
context_variables["itinerary"] = final_itinerary
# This will update the context variables and then transfer to the Structured Output agent
return SwarmResult(
agent="structured_output_agent",
context_variables=context_variables,
values="Itinerary recorded and confirmed.",
)
def create_structured_itinerary(
context_variables: Dict[str, Any], structured_itinerary: str
) -> SwarmResult:
"""Once a structured itinerary is created, store it and pass on to the Route Timing agent."""
# Ensure the itinerary is confirmed, if not, back to the Planner agent to confirm it with the customer
if not context_variables["itinerary_confirmed"]:
return SwarmResult(
agent="planner_agent",
values="Itinerary not confirmed, please confirm the itinerary with the customer first.",
)
context_variables["structured_itinerary"] = structured_itinerary
# This will update the context variables and then transfer to the Route Timing agent
return SwarmResult(
agent="route_timing_agent",
context_variables=context_variables,
values="Structured itinerary stored.",
)
# Planner agent, interacting with the customer and GraphRag agent, to create an itinerary
planner_agent = SwarmAgent(
name="planner_agent",
system_message="You are a trip planner agent. It is important to know where the customer is going, how many days, what they want to do."
+ "You will work with another agent, graphrag_agent, to get information about restaurant and attractions. "
+ "You are also working with the customer, so you must ask the customer what they want to do if you don’t have LOCATION, NUMBER OF DAYS, MEALS, and ATTRACTIONS. "
+ "When you have the customer's requirements, work with graphrag_agent to get information for an itinerary."
+ "You are responsible for creating the itinerary and for each day in the itinerary you MUST HAVE events and EACH EVENT MUST HAVE a 'type' ('Restaurant' or 'Attraction'), 'location' (name of restaurant or attraction), 'city', and 'description'. "
+ "Finally, YOU MUST ask the customer if they are happy with the itinerary before marking the itinerary as complete.",
functions=[mark_itinerary_as_complete],
llm_config=llm_config,
)
# FalkorDB GraphRAG agent, utilising the FalkorDB to gather data for the Planner agent
graphrag_agent = SwarmAgent(
name="graphrag_agent",
system_message="Return a list of restaurants and/or attractions. List them separately and provide ALL the options in the location. Do not provide travel advice.",
)
# Adding the FalkorDB capability to the agent
graph_rag_capability = FalkorGraphRagCapability(query_engine)
graph_rag_capability.add_to_agent(graphrag_agent)
# Structured Output agent, formatting the itinerary into a structured format through the response_format on the LLM Configuration
structured_config_list = copy.deepcopy(config_list)
for config in structured_config_list:
config["response_format"] = Itinerary
structured_output_agent = SwarmAgent(
name="structured_output_agent",
system_message="You are a data formatting agent, format the provided itinerary in the context below into the provided format.",
llm_config={"config_list": structured_config_list, "timeout": 120},
functions=[create_structured_itinerary],
)
# Route Timing agent, adding estimated travel times to the itinerary by utilising the Google Maps Platform
route_timing_agent = SwarmAgent(
name="route_timing_agent",
system_message="You are a route timing agent. YOU MUST call the update_itinerary_with_travel_times tool if you do not see the exact phrase 'Timed itinerary added to context with travel times' is seen in this conversation. Only after this please tell the customer 'Your itinerary is ready!'.",
llm_config=llm_config,
functions=[update_itinerary_with_travel_times],
)
# Our customer will be a human in the loop
customer = UserProxyAgent(name="customer", code_execution_config=False)
planner_agent.register_hand_off(
hand_to=[
ON_CONDITION(
graphrag_agent,
"Need information on the restaurants and attractions for a location. DO NOT call more than once at a time.",
), # Get info from FalkorDB GraphRAG
ON_CONDITION(structured_output_agent, "Itinerary is confirmed by the customer"),
AFTER_WORK(
AfterWorkOption.REVERT_TO_USER
), # Revert to the customer for more information on their plans
]
)
# Back to the Planner when information has been retrieved
graphrag_agent.register_hand_off(hand_to=[AFTER_WORK(planner_agent)])
# Once we have formatted our itinerary, we can hand off to the route timing agent to add in the travel timings
structured_output_agent.register_hand_off(hand_to=[AFTER_WORK(route_timing_agent)])
# Finally, once the route timing agent has finished, we can terminate the swarm
route_timing_agent.register_hand_off(
hand_to=[
AFTER_WORK(AfterWorkOption.TERMINATE)
] # Once this agent has finished, the swarm can terminate
)
# Start the conversation
chat_result, context_variables, last_agent = initiate_swarm_chat(
initial_agent=planner_agent,
agents=[planner_agent, graphrag_agent, structured_output_agent, route_timing_agent],
user_agent=customer,
context_variables=trip_context,
messages="I want to go to Rome for a couple of days. Can you help me plan my trip?",
after_work=AfterWorkOption.TERMINATE,
max_rounds=100,
)
def print_itinerary(itinerary_data):
header = "█ █\n █ █ \n █ █████ █ \n ██ ██ \n █ █ \n █ ███████ █ \n █ ██ ███ ██ █ \n █████████ \n\n ██ ███ ███ \n█ █ █ █ \n████ █ ██ ██ \n█ █ █ █ █ \n█ █ ██ ████ \n"
width = 80
icons = {"Travel": "🚶", "Restaurant": "🍽️", "Attraction": "🏛️"}
for line in header.split("\n"):
print(line.center(width))
print(
f"Itinerary for {itinerary_data['days'][0]['events'][0]['city']}".center(width)
)
print("=" * width)
for day_num, day in enumerate(itinerary_data["days"], 1):
print(f"\nDay {day_num}".center(width))
print("-" * width)
for event in day["events"]:
event_type = event["type"]
print(f"\n {icons[event_type]} {event['location']}")
if event_type != "Travel":
words = event["description"].split()
line = " "
for word in words:
if len(line) + len(word) + 1 <= 76:
line += word + " "
else:
print(line)
line = " " + word + " "
if line.strip():
print(line)
else:
print(f" {event['description']}")
print("\n" + "-" * width)
if "timed_itinerary" in context_variables:
print_itinerary(context_variables["timed_itinerary"])
else:
print("No itinerary available to print.")