forked from alexeygrigorev/rag-agents-workshop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat_assistant.py
More file actions
128 lines (94 loc) · 3.4 KB
/
chat_assistant.py
File metadata and controls
128 lines (94 loc) · 3.4 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import json
from IPython.display import display, HTML
import markdown
class Tools:
def __init__(self):
self.tools = {}
self.functions = {}
def add_tool(self, function, description):
self.tools[function.__name__] = description
self.functions[function.__name__] = function
def get_tools(self):
return list(self.tools.values())
def function_call(self, tool_call_response):
function_name = tool_call_response.name
arguments = json.loads(tool_call_response.arguments)
f = self.functions[function_name]
result = f(**arguments)
return {
"type": "function_call_output",
"call_id": tool_call_response.call_id,
"output": json.dumps(result, indent=2),
}
def shorten(text, max_length=50):
if len(text) <= max_length:
return text
return text[:max_length - 3] + "..."
class ChatInterface:
def input(self):
question = input("You:")
return question
def display(self, message):
print(message)
def display_function_call(self, entry, result):
call_html = f"""
<details>
<summary>Function call: <tt>{entry.name}({shorten(entry.arguments)})</tt></summary>
<div>
<b>Call</b>
<pre>{entry}</pre>
</div>
<div>
<b>Output</b>
<pre>{result['output']}</pre>
</div>
</details>
"""
display(HTML(call_html))
def display_response(self, entry):
response_html = markdown.markdown(entry.content[0].text)
html = f"""
<div>
<div><b>Assistant:</b></div>
<div>{response_html}</div>
</div>
"""
display(HTML(html))
class ChatAssistant:
def __init__(self, tools, developer_prompt, chat_interface, client):
self.tools = tools
self.developer_prompt = developer_prompt
self.chat_interface = chat_interface
self.client = client
def gpt(self, chat_messages):
return self.client.responses.create(
model='gpt-4o-mini',
input=chat_messages,
tools=self.tools.get_tools(),
)
def run(self):
chat_messages = [
{"role": "developer", "content": self.developer_prompt},
]
# Chat loop
while True:
question = self.chat_interface.input()
if question.strip().lower() == 'stop':
self.chat_interface.display("Chat ended.")
break
message = {"role": "user", "content": question}
chat_messages.append(message)
while True: # inner request loop
response = self.gpt(chat_messages)
has_messages = False
for entry in response.output:
chat_messages.append(entry)
if entry.type == "function_call":
result = self.tools.function_call(entry)
chat_messages.append(result)
self.chat_interface.display_function_call(entry, result)
elif entry.type == "message":
self.chat_interface.display_response(entry)
has_messages = True
if has_messages:
break