utar commited on
Commit
de9bf37
·
1 Parent(s): eded2a2
Files changed (2) hide show
  1. app.py +271 -0
  2. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import datetime
4
+ import random
5
+ import os
6
+ from typing import List
7
+ from langchain.callbacks import get_openai_callback
8
+ from langchain.chat_models import ChatOpenAI
9
+ from langchain.prompts.chat import (
10
+ SystemMessagePromptTemplate,
11
+ HumanMessagePromptTemplate,
12
+ )
13
+ from langchain.schema import (
14
+ AIMessage,
15
+ HumanMessage,
16
+ SystemMessage,
17
+ BaseMessage,
18
+ )
19
+ #-----------------------------------------------------------------------
20
+ # from dotenv import find_dotenv, load_dotenv
21
+ # # Load environment variables
22
+ # load_dotenv(find_dotenv())
23
+ #----------------------------------------------------------------------
24
+ # Define agent class
25
+ class CAMELAgent:
26
+ def __init__(
27
+ self,
28
+ system_message: SystemMessage,
29
+ model: ChatOpenAI,
30
+ ) -> None:
31
+ self.system_message = system_message
32
+ self.model = model
33
+ self.init_messages()
34
+
35
+ def reset(self) -> None:
36
+ self.init_messages()
37
+ return self.stored_messages
38
+
39
+ def init_messages(self) -> None:
40
+ self.stored_messages = [self.system_message]
41
+
42
+ def update_messages(self, message: BaseMessage) -> List[BaseMessage]:
43
+ self.stored_messages.append(message)
44
+ # print(self.stored_messages)
45
+ return self.stored_messages
46
+
47
+ def step(
48
+ self,
49
+ input_message: HumanMessage,
50
+ ) -> AIMessage:
51
+ messages = self.update_messages(input_message)
52
+
53
+ output_message = self.model(messages)
54
+ self.update_messages(output_message)
55
+
56
+ return output_message
57
+
58
+ # Inception templates
59
+ assistant_inception_prompt = (
60
+ """Never forget you are a {assistant_role_name} and I am a {user_role_name}. Never flip roles!
61
+ We share a common interest in collaborating to successfully complete a task.
62
+ You must help me to complete the task.
63
+ Here is the task: {task}. Never forget our task!
64
+ I will instruct you based on your expertise and my needs to complete the task.
65
+
66
+ I must give you one question at a time.
67
+ You must write a specific answer that appropriately completes the requested question.
68
+ You must decline my question honestly if you cannot comply the question due to physical, moral, legal reasons or your capability and explain the reasons.
69
+ Do not add anything else other than your answer to my instruction.
70
+
71
+ Unless I say the task is completed, you should always start with:
72
+
73
+ My response: <YOUR_SOLUTION>
74
+
75
+ <YOUR_SOLUTION> should be specific and descriptive.
76
+ Always end <YOUR_SOLUTION> with: Next question."""
77
+ )
78
+
79
+ user_inception_prompt = (
80
+ """Never forget you are a {user_role_name} and I am a {assistant_role_name}. Never flip roles! You will always ask me.
81
+ We share a common interest in collaborating to successfully complete a task.
82
+ I must help you to answer the questions.
83
+ Here is the task: {task}. Never forget our task!
84
+ You must instruct me based on my expertise and your needs to complete the task ONLY in the following two ways:
85
+
86
+ 1. Instruct with a necessary input:
87
+ Instruction: <YOUR_INSTRUCTION>
88
+ Input: <YOUR_INPUT>
89
+
90
+ 2. Instruct without any input:
91
+ Instruction: <YOUR_INSTRUCTION>
92
+ Input: None
93
+
94
+ The "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction".
95
+
96
+ You must give me one instruction at a time.
97
+ I must write a response that appropriately completes the requested instruction.
98
+ I must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons.
99
+ You should instruct me not ask me questions.
100
+ Now you must start to instruct me using the two ways described above.
101
+ Do not add anything else other than your instruction and the optional corresponding input!
102
+ Keep giving me instructions and necessary inputs until you think the task is completed.
103
+ When the task is completed, you must only reply with a single word <TASK_DONE>.
104
+ Never say <TASK_DONE> unless my responses have solved your task."""
105
+ )
106
+
107
+ def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str):
108
+ """
109
+ A helper functioın to get system messages for AI assistant and AI user from role names and the task
110
+ - SystemMessage: the guidance
111
+ - HumanMessage: input
112
+ - AIMessage: the agent output/response
113
+ """
114
+ assistant_sys_template = SystemMessagePromptTemplate.from_template(template=assistant_inception_prompt)
115
+ assistant_sys_msg = assistant_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]
116
+
117
+ user_sys_template = SystemMessagePromptTemplate.from_template(template=user_inception_prompt)
118
+ user_sys_msg = user_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]
119
+
120
+ return assistant_sys_msg, user_sys_msg
121
+
122
+ def write_conversation_to_file(conversation, filename):
123
+ """
124
+ Write a conversation to a text file with a timestamp in its filename.
125
+
126
+ Parameters:
127
+ conversation (list): A list of tuples. Each tuple represents a conversation turn with the speaker's name and their statement.
128
+ filename (str): The name of the file to write the conversation to.
129
+
130
+ Returns:
131
+ None
132
+ """
133
+ def timestamp():
134
+ """
135
+ Convert the current date and time into a custom timestamp format.
136
+
137
+ Returns:
138
+ str: The current date and time in the format HHMMDDMMYYYY.
139
+ """
140
+
141
+ # Get the current date and time
142
+ now = datetime.datetime.now()
143
+
144
+ # Format the date and time as a string in the desired format
145
+ timestamp = now.strftime("%H%M%d%m%Y")
146
+
147
+ return timestamp
148
+
149
+ def append_timestamp_to_filename(filename):
150
+ """
151
+ Append a timestamp to a filename before the extension.
152
+
153
+ Parameters:
154
+ filename (str): The original filename.
155
+
156
+ Returns:
157
+ str: The filename with a timestamp appended.
158
+ """
159
+
160
+ # Split the filename into the base and extension
161
+ base, extension = os.path.splitext(filename)
162
+
163
+ # Append the timestamp to the base and add the extension back on
164
+ new_filename = f"{base}-{timestamp()}{extension}"
165
+
166
+ return new_filename
167
+
168
+ # Append timestamp to the filename
169
+ filename = append_timestamp_to_filename(filename)
170
+
171
+ with open(filename, 'w') as f:
172
+ for turn in conversation:
173
+ speaker, statement = turn
174
+ f.write(f"{speaker}: {statement}\n\n")
175
+
176
+ def get_specified_task(assistant_role_name: str, user_role_name: str, task: str, word_limit: int) -> str:
177
+ task_specifier_sys_msg = SystemMessage(content="You can make a task more specific.")
178
+ task_specifier_prompt = (
179
+ """Here is a task that {assistant_role_name} will discuss with {user_role_name} to : {task}.
180
+ Please make it more specific. Be creative and imaginative.
181
+ Please reply with the full task in {word_limit} words or less. Do not add anything else."""
182
+ )
183
+ # Ask agent to expand on the task
184
+ task_specifier_template = HumanMessagePromptTemplate.from_template(template=task_specifier_prompt)
185
+ task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(temperature=0.7))
186
+ task_specifier_msg = task_specifier_template.format_messages(assistant_role_name=assistant_role_name,
187
+ user_role_name=user_role_name,
188
+ task=task,
189
+ word_limit=word_limit)[0]
190
+ specified_task_msg = task_specify_agent.step(task_specifier_msg)
191
+ print(f"Specified task: {specified_task_msg.content}")
192
+ return specified_task_msg.content
193
+
194
+ specified_task = None
195
+ stop = False
196
+ st.title("Chatbot Demo")
197
+
198
+ with st.container():
199
+ assistant_role_name = st.text_input("User-AI", value="Singapore Tourism Board")
200
+ user_role_name = st.text_input("Assistant-AI", value="Tourist that has never been to Singapore")
201
+ task = st.text_input("Task", value="Discuss the best tourist attractions to see in Singapore")
202
+ word_limit = st.slider("Word limit", min_value=0, max_value=50, value=15)
203
+ chat_turn_limit = st.slider("Max. Messages", min_value=0, max_value=30, value=10)
204
+ specified_task_container = st.empty()
205
+
206
+ with st.container():
207
+ chat_container = st.empty()
208
+
209
+ with st.container():
210
+ # tab = st.tabs(1)
211
+ # with tab:
212
+ stop_button = st.button("Stop")
213
+ gen_button = st.button("Generate Task")
214
+ init_button = st.button("Initialize Agents")
215
+
216
+ if gen_button:
217
+ specified_task = get_specified_task(assistant_role_name, user_role_name, task, word_limit)
218
+ with chat_container.container():
219
+ st.write(f"Task: {specified_task}")
220
+
221
+ if stop_button:
222
+ stop = True
223
+ st.stop()
224
+
225
+ if init_button:
226
+ # Initialize agents
227
+ assistant_sys_msg, user_sys_msg = get_sys_msgs(assistant_role_name, user_role_name, specified_task)
228
+ assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(temperature=0.2))
229
+ user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(temperature=0.2))
230
+
231
+ # Reset agents
232
+ assistant_agent.reset()
233
+ user_agent.reset()
234
+
235
+ # Initialize chats
236
+ assistant_msg = HumanMessage(content=(f"{user_sys_msg.content}. "
237
+ "Now start to give me introductions one by one. "
238
+ "Only reply with Instruction and Input.")
239
+ )
240
+
241
+ user_msg = HumanMessage(content=f"{assistant_sys_msg.content}")
242
+ user_msg = assistant_agent.step(user_msg)
243
+
244
+ conversation = []
245
+ with st.expander("See explanation"):
246
+ with chat_container.container():
247
+ with get_openai_callback() as cb:
248
+ n = 0
249
+ while n < chat_turn_limit and not stop:
250
+ n += 1
251
+ user_ai_msg = user_agent.step(assistant_msg)
252
+ user_msg = HumanMessage(content=user_ai_msg.content)
253
+ st.write(f"AI User ({user_role_name}):\n\n{user_msg.content}\n\n")
254
+ conversation.append((user_role_name,user_msg.content))
255
+
256
+ assistant_ai_msg = assistant_agent.step(user_msg)
257
+ assistant_msg = HumanMessage(content=assistant_ai_msg.content)
258
+ st.write(f"AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n")
259
+ conversation.append((assistant_role_name,assistant_msg.content))
260
+
261
+ if "<TASK_DONE>" in user_msg.content:
262
+ break
263
+ time.sleep(1)
264
+
265
+ st.write(f"Total Successful Requests: {cb.successful_requests}")
266
+ st.write(f"Total Tokens Used: {cb.total_tokens}")
267
+ st.write(f"Prompt Tokens: {cb.prompt_tokens}")
268
+ st.write(f"Completion Tokens: {cb.completion_tokens}")
269
+ st.write(f"Total Cost (USD): ${cb.total_cost}")
270
+
271
+ write_conversation_to_file(conversation, 'conversation.txt')
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ langchain
2
+ openai
3
+ tiktoken
4
+ streamlit