Spaces:
Runtime error
Runtime error
Ashhar
commited on
Commit
·
83a5cfb
1
Parent(s):
061239f
improvemnts
Browse files- app.py +83 -133
- icons/check.png +0 -0
- icons/magic-wand(1) - Copy.png +0 -0
- icons/{magic-wand(1).png → magic-wand-1.png} +0 -0
- icons/magic-wand.gif +0 -0
- icons/settings.png +0 -0
- tools.py +15 -24
app.py
CHANGED
@@ -5,7 +5,6 @@ import pytz
|
|
5 |
import time
|
6 |
import json
|
7 |
import re
|
8 |
-
from typing import List
|
9 |
from transformers import AutoTokenizer
|
10 |
from gradio_client import Client
|
11 |
from tools import toolsInfo
|
@@ -45,14 +44,14 @@ You are a personalized email generator for cold outreach. You take the user thro
|
|
45 |
- His/her role
|
46 |
- More details about the recipient
|
47 |
|
48 |
-
Highlight the exact entity you're requesting for.
|
49 |
Once collected, you store these info in a Google Sheet
|
50 |
|
51 |
"""
|
52 |
|
53 |
USER_ICON = "icons/man.png"
|
54 |
-
ASSISTANT_ICON = "icons/magic-wand
|
55 |
-
TOOL_ICON = "icons/
|
56 |
|
57 |
IMAGE_LOADER = "icons/ripple.svg"
|
58 |
TEXT_LOADER = "icons/balls.svg"
|
@@ -129,21 +128,6 @@ def __isInvalidResponse(response: str):
|
|
129 |
return True
|
130 |
|
131 |
|
132 |
-
def __matchingKeywordsCount(keywords: List[str], text: str):
|
133 |
-
return sum([
|
134 |
-
1 if keyword in text else 0
|
135 |
-
for keyword in keywords
|
136 |
-
])
|
137 |
-
|
138 |
-
|
139 |
-
def __isStringNumber(s: str) -> bool:
|
140 |
-
try:
|
141 |
-
float(s)
|
142 |
-
return True
|
143 |
-
except ValueError:
|
144 |
-
return False
|
145 |
-
|
146 |
-
|
147 |
def __resetButtonState():
|
148 |
st.session_state["buttonValue"] = ""
|
149 |
|
@@ -164,6 +148,8 @@ if "buttonValue" not in st.session_state:
|
|
164 |
if "startMsg" not in st.session_state:
|
165 |
st.session_state.startMsg = ""
|
166 |
|
|
|
|
|
167 |
|
168 |
def __getMessages():
|
169 |
def getContextSize():
|
@@ -183,47 +169,26 @@ tools = [
|
|
183 |
]
|
184 |
|
185 |
|
186 |
-
def
|
187 |
-
|
188 |
-
|
189 |
-
taskContainer.markdown(
|
190 |
-
f"""
|
191 |
-
<div class='code'>
|
192 |
-
{msg}
|
193 |
-
</div>
|
194 |
-
""",
|
195 |
-
unsafe_allow_html=True
|
196 |
-
)
|
197 |
-
|
198 |
-
|
199 |
-
def __processToolCalls(tool_calls):
|
200 |
-
for toolCall in tool_calls:
|
201 |
-
functionName = toolCall.function.name
|
202 |
-
functionToCall = toolsInfo[functionName]["func"]
|
203 |
-
functionArgs = json.loads(toolCall.function.arguments)
|
204 |
-
functionResult = functionToCall(**functionArgs)
|
205 |
-
functionResponse = functionResult["response"]
|
206 |
-
shouldShow = functionResult["shouldShow"]
|
207 |
-
pprint(f"{functionResponse=}")
|
208 |
-
|
209 |
-
if shouldShow:
|
210 |
-
st.session_state.chatHistory.append(
|
211 |
-
{
|
212 |
-
"role": "tool",
|
213 |
-
"content": functionResponse,
|
214 |
-
}
|
215 |
-
)
|
216 |
-
|
217 |
-
__showTaskStatus(functionResponse)
|
218 |
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
"content": functionResponse,
|
225 |
-
}
|
226 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
def __process_stream_chunk(chunk):
|
229 |
delta = chunk.choices[0].delta
|
@@ -252,59 +217,48 @@ def __addToolCallsToMsgs(toolCalls):
|
|
252 |
}
|
253 |
)
|
254 |
|
255 |
-
def __add_tool_call(tool_call):
|
256 |
-
st.session_state.messages.append({
|
257 |
-
"role": "assistant",
|
258 |
-
"tool_calls": [{
|
259 |
-
"id": tool_call.id,
|
260 |
-
"function": {
|
261 |
-
"name": tool_call.function.name,
|
262 |
-
"arguments": tool_call.function.arguments,
|
263 |
-
},
|
264 |
-
"type": tool_call.type,
|
265 |
-
}]
|
266 |
-
})
|
267 |
-
|
268 |
-
def predict1():
|
269 |
-
shouldStream = True
|
270 |
-
|
271 |
-
messagesFormatted = [{"role": "system", "content": SYSTEM_MSG}]
|
272 |
-
messagesFormatted.extend(__getMessages())
|
273 |
-
contextSize = countTokens(messagesFormatted)
|
274 |
-
pprint(f"{contextSize=} | {MODEL}")
|
275 |
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
)
|
284 |
|
285 |
-
content = ""
|
286 |
-
tool_call = None
|
287 |
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
tool_call.function.arguments += chunk_content.function.arguments
|
298 |
|
299 |
-
|
300 |
-
|
|
|
301 |
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
|
|
|
|
|
|
308 |
|
309 |
|
310 |
def __dedupeToolCalls(toolCalls: list):
|
@@ -343,23 +297,23 @@ def predict():
|
|
343 |
content = ""
|
344 |
toolCall = None
|
345 |
|
346 |
-
for chunk in response:
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
toolCalls = [toolCall] if toolCall else []
|
358 |
else:
|
359 |
responseMessage = response.choices[0].message
|
360 |
# pprint(f"{responseMessage=}")
|
361 |
responseContent = responseMessage.content
|
362 |
-
pprint(f"{responseContent=}")
|
363 |
if responseContent:
|
364 |
yield responseContent
|
365 |
toolCalls = responseMessage.tool_calls
|
@@ -368,7 +322,6 @@ def predict():
|
|
368 |
if toolCalls:
|
369 |
pprint(f"{toolCalls=}")
|
370 |
toolCalls = __dedupeToolCalls(toolCalls)
|
371 |
-
__addToolCallsToMsgs(toolCalls)
|
372 |
try:
|
373 |
__processToolCalls(toolCalls)
|
374 |
return predict()
|
@@ -384,19 +337,12 @@ for chat in st.session_state.chatHistory:
|
|
384 |
role = chat["role"]
|
385 |
content = chat["content"]
|
386 |
imagePath = chat.get("image")
|
|
|
387 |
avatar = ROLE_TO_AVATAR[role]
|
388 |
with st.chat_message(role, avatar=avatar):
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
<div class='code'>
|
393 |
-
{content}
|
394 |
-
</div>
|
395 |
-
""",
|
396 |
-
unsafe_allow_html=True
|
397 |
-
)
|
398 |
-
else:
|
399 |
-
st.markdown(content)
|
400 |
|
401 |
if imagePath:
|
402 |
st.image(imagePath)
|
@@ -408,8 +354,8 @@ if prompt := (st.chat_input() or st.session_state["buttonValue"] or st.session_s
|
|
408 |
with st.chat_message("user", avatar=USER_ICON):
|
409 |
st.markdown(prompt)
|
410 |
pprint(f"{prompt=}")
|
411 |
-
st.session_state.messages.append({"role": "user", "content": prompt })
|
412 |
st.session_state.chatHistory.append({"role": "user", "content": prompt })
|
|
|
413 |
|
414 |
with st.chat_message("assistant", avatar=ASSISTANT_ICON):
|
415 |
responseContainer = st.empty()
|
@@ -463,11 +409,15 @@ if prompt := (st.chat_input() or st.session_state["buttonValue"] or st.session_s
|
|
463 |
# except Exception as e:
|
464 |
# pprint(e)
|
465 |
|
466 |
-
st.session_state.
|
|
|
467 |
"role": "assistant",
|
468 |
"content": response,
|
|
|
469 |
})
|
470 |
-
|
|
|
471 |
"role": "assistant",
|
472 |
"content": response,
|
473 |
})
|
|
|
|
5 |
import time
|
6 |
import json
|
7 |
import re
|
|
|
8 |
from transformers import AutoTokenizer
|
9 |
from gradio_client import Client
|
10 |
from tools import toolsInfo
|
|
|
44 |
- His/her role
|
45 |
- More details about the recipient
|
46 |
|
47 |
+
Highlight the exact entity you're requesting for by making it CAPITAL CASE.
|
48 |
Once collected, you store these info in a Google Sheet
|
49 |
|
50 |
"""
|
51 |
|
52 |
USER_ICON = "icons/man.png"
|
53 |
+
ASSISTANT_ICON = "icons/magic-wand-1.png"
|
54 |
+
TOOL_ICON = "icons/check.png"
|
55 |
|
56 |
IMAGE_LOADER = "icons/ripple.svg"
|
57 |
TEXT_LOADER = "icons/balls.svg"
|
|
|
128 |
return True
|
129 |
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
def __resetButtonState():
|
132 |
st.session_state["buttonValue"] = ""
|
133 |
|
|
|
148 |
if "startMsg" not in st.session_state:
|
149 |
st.session_state.startMsg = ""
|
150 |
|
151 |
+
st.session_state.toolResponseDisplay = {}
|
152 |
+
|
153 |
|
154 |
def __getMessages():
|
155 |
def getContextSize():
|
|
|
169 |
]
|
170 |
|
171 |
|
172 |
+
def __showToolResponse(toolResponseDisplay: dict):
|
173 |
+
msg = toolResponseDisplay.get("text")
|
174 |
+
icon = toolResponseDisplay.get("icon")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
|
176 |
+
col1, col2 = st.columns([1, 20])
|
177 |
+
with col1:
|
178 |
+
st.image(
|
179 |
+
icon or TOOL_ICON,
|
180 |
+
width=30
|
|
|
|
|
181 |
)
|
182 |
+
with col2:
|
183 |
+
st.markdown(
|
184 |
+
f"""
|
185 |
+
<div class='code'>
|
186 |
+
{msg}
|
187 |
+
</div>
|
188 |
+
""",
|
189 |
+
unsafe_allow_html=True
|
190 |
+
)
|
191 |
+
|
192 |
|
193 |
def __process_stream_chunk(chunk):
|
194 |
delta = chunk.choices[0].delta
|
|
|
217 |
}
|
218 |
)
|
219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
+
def __addToolCallToMsgs(toolCall: dict):
|
222 |
+
st.session_state.messages.append(
|
223 |
+
{
|
224 |
+
"role": "assistant",
|
225 |
+
"tool_calls": [
|
226 |
+
{
|
227 |
+
"id": toolCall.id,
|
228 |
+
"function": {
|
229 |
+
"name": toolCall.function.name,
|
230 |
+
"arguments": toolCall.function.arguments,
|
231 |
+
},
|
232 |
+
"type": toolCall.type,
|
233 |
+
}
|
234 |
+
],
|
235 |
+
}
|
236 |
)
|
237 |
|
|
|
|
|
238 |
|
239 |
+
def __processToolCalls(toolCalls):
|
240 |
+
for toolCall in toolCalls:
|
241 |
+
functionName = toolCall.function.name
|
242 |
+
functionToCall = toolsInfo[functionName]["func"]
|
243 |
+
functionArgs = json.loads(toolCall.function.arguments)
|
244 |
+
functionResult = functionToCall(**functionArgs)
|
245 |
+
functionResponse = functionResult["response"]
|
246 |
+
responseDisplay = functionResult.get("display")
|
247 |
+
pprint(f"{functionResponse=}")
|
|
|
248 |
|
249 |
+
if responseDisplay:
|
250 |
+
__showToolResponse(responseDisplay)
|
251 |
+
st.session_state.toolResponseDisplay = responseDisplay
|
252 |
|
253 |
+
__addToolCallToMsgs(toolCall)
|
254 |
+
st.session_state.messages.append(
|
255 |
+
{
|
256 |
+
"role": "tool",
|
257 |
+
"tool_call_id": toolCall.id,
|
258 |
+
"name": functionName,
|
259 |
+
"content": functionResponse,
|
260 |
+
}
|
261 |
+
)
|
262 |
|
263 |
|
264 |
def __dedupeToolCalls(toolCalls: list):
|
|
|
297 |
content = ""
|
298 |
toolCall = None
|
299 |
|
300 |
+
# for chunk in response:
|
301 |
+
# chunkContent = __process_stream_chunk(chunk)
|
302 |
+
# if isinstance(chunkContent, str):
|
303 |
+
# content += chunkContent
|
304 |
+
# yield chunkContent
|
305 |
+
# elif chunkContent:
|
306 |
+
# if not toolCall:
|
307 |
+
# toolCall = chunkContent
|
308 |
+
# else:
|
309 |
+
# toolCall.function.arguments += chunkContent.function.arguments
|
310 |
+
|
311 |
+
# toolCalls = [toolCall] if toolCall else []
|
312 |
else:
|
313 |
responseMessage = response.choices[0].message
|
314 |
# pprint(f"{responseMessage=}")
|
315 |
responseContent = responseMessage.content
|
316 |
+
# pprint(f"{responseContent=}")
|
317 |
if responseContent:
|
318 |
yield responseContent
|
319 |
toolCalls = responseMessage.tool_calls
|
|
|
322 |
if toolCalls:
|
323 |
pprint(f"{toolCalls=}")
|
324 |
toolCalls = __dedupeToolCalls(toolCalls)
|
|
|
325 |
try:
|
326 |
__processToolCalls(toolCalls)
|
327 |
return predict()
|
|
|
337 |
role = chat["role"]
|
338 |
content = chat["content"]
|
339 |
imagePath = chat.get("image")
|
340 |
+
toolResponseDisplay = chat.get("toolResponseDisplay")
|
341 |
avatar = ROLE_TO_AVATAR[role]
|
342 |
with st.chat_message(role, avatar=avatar):
|
343 |
+
st.markdown(content)
|
344 |
+
if toolResponseDisplay:
|
345 |
+
__showToolResponse(toolResponseDisplay)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
346 |
|
347 |
if imagePath:
|
348 |
st.image(imagePath)
|
|
|
354 |
with st.chat_message("user", avatar=USER_ICON):
|
355 |
st.markdown(prompt)
|
356 |
pprint(f"{prompt=}")
|
|
|
357 |
st.session_state.chatHistory.append({"role": "user", "content": prompt })
|
358 |
+
st.session_state.messages.append({"role": "user", "content": prompt })
|
359 |
|
360 |
with st.chat_message("assistant", avatar=ASSISTANT_ICON):
|
361 |
responseContainer = st.empty()
|
|
|
409 |
# except Exception as e:
|
410 |
# pprint(e)
|
411 |
|
412 |
+
toolResponseDisplay = st.session_state.toolResponseDisplay
|
413 |
+
st.session_state.chatHistory.append({
|
414 |
"role": "assistant",
|
415 |
"content": response,
|
416 |
+
"toolResponseDisplay": toolResponseDisplay
|
417 |
})
|
418 |
+
|
419 |
+
st.session_state.messages.append({
|
420 |
"role": "assistant",
|
421 |
"content": response,
|
422 |
})
|
423 |
+
|
icons/check.png
ADDED
icons/magic-wand(1) - Copy.png
DELETED
Binary file (27.6 kB)
|
|
icons/{magic-wand(1).png → magic-wand-1.png}
RENAMED
File without changes
|
icons/magic-wand.gif
DELETED
Binary file (598 kB)
|
|
icons/settings.png
ADDED
tools.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
|
2 |
import gspread
|
3 |
-
from oauth2client.service_account import ServiceAccountCredentials
|
4 |
import os
|
5 |
import json
|
6 |
|
@@ -8,6 +7,7 @@ import json
|
|
8 |
# load_dotenv()
|
9 |
|
10 |
GCP_JSON_KEY = os.environ.get("GCP_JSON_KEY")
|
|
|
11 |
|
12 |
|
13 |
def saveInGSheet(
|
@@ -17,13 +17,18 @@ def saveInGSheet(
|
|
17 |
):
|
18 |
client = gspread.service_account_from_dict(json.loads(GCP_JSON_KEY))
|
19 |
|
20 |
-
workBook = "
|
21 |
try:
|
22 |
spreadsheet = client.open(workBook)
|
23 |
except gspread.SpreadsheetNotFound:
|
|
|
24 |
spreadsheet = client.create(workBook)
|
25 |
-
spreadsheet.share('[email protected]', perm_type='user', role='writer')
|
26 |
print(f"Created new sheet: {spreadsheet.url}")
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
sheet = spreadsheet.sheet1
|
29 |
sheet.append_row([
|
@@ -32,20 +37,14 @@ def saveInGSheet(
|
|
32 |
profileDetails
|
33 |
])
|
34 |
return {
|
35 |
-
"response": "Saved in
|
36 |
-
"
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
|
40 |
-
# saveInGSheet({
|
41 |
-
# "name": "Ashhar",
|
42 |
-
# "email": "XXXXXXXXXXXXXXXXXXXXX",
|
43 |
-
# "subject": "Test Subject",
|
44 |
-
# "message": "Test Message",
|
45 |
-
# "sent": True
|
46 |
-
# })
|
47 |
-
|
48 |
-
|
49 |
toolsInfo = {
|
50 |
"saveInGSheet": {
|
51 |
"func": saveInGSheet,
|
@@ -53,7 +52,7 @@ toolsInfo = {
|
|
53 |
"type": "function",
|
54 |
"function": {
|
55 |
"name": "saveInGSheet",
|
56 |
-
"description": "Saves the profile details in
|
57 |
"parameters": {
|
58 |
"type": "object",
|
59 |
"properties": {
|
@@ -63,7 +62,7 @@ toolsInfo = {
|
|
63 |
},
|
64 |
"role": {
|
65 |
"type": "string",
|
66 |
-
"description": "Role of the person"
|
67 |
},
|
68 |
"profileDetails": {
|
69 |
"type": "string",
|
@@ -77,11 +76,3 @@ toolsInfo = {
|
|
77 |
}
|
78 |
}
|
79 |
|
80 |
-
|
81 |
-
# def load_json_and_print():
|
82 |
-
# with open('emailgenie-434420-b9c81c93bb39.json', 'r') as json_file:
|
83 |
-
# data = json.load(json_file)
|
84 |
-
# json_string = json.dumps(data)
|
85 |
-
# print(json_string)
|
86 |
-
|
87 |
-
# load_json_and_print()
|
|
|
1 |
|
2 |
import gspread
|
|
|
3 |
import os
|
4 |
import json
|
5 |
|
|
|
7 |
# load_dotenv()
|
8 |
|
9 |
GCP_JSON_KEY = os.environ.get("GCP_JSON_KEY")
|
10 |
+
MY_EMAIL = "[email protected]"
|
11 |
|
12 |
|
13 |
def saveInGSheet(
|
|
|
17 |
):
|
18 |
client = gspread.service_account_from_dict(json.loads(GCP_JSON_KEY))
|
19 |
|
20 |
+
workBook = "Cold Outreach - User Prof"
|
21 |
try:
|
22 |
spreadsheet = client.open(workBook)
|
23 |
except gspread.SpreadsheetNotFound:
|
24 |
+
print(f"Creating new sheet: {workBook}")
|
25 |
spreadsheet = client.create(workBook)
|
|
|
26 |
print(f"Created new sheet: {spreadsheet.url}")
|
27 |
+
spreadsheet.share(
|
28 |
+
MY_EMAIL,
|
29 |
+
perm_type='user',
|
30 |
+
role='writer',
|
31 |
+
)
|
32 |
|
33 |
sheet = spreadsheet.sheet1
|
34 |
sheet.append_row([
|
|
|
37 |
profileDetails
|
38 |
])
|
39 |
return {
|
40 |
+
"response": f"Saved in Google Sheet. [Link]({spreadsheet.url})",
|
41 |
+
"display": {
|
42 |
+
"text": "Saved in Google Sheet",
|
43 |
+
"icon": "icons/completed-task.png",
|
44 |
+
}
|
45 |
}
|
46 |
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
toolsInfo = {
|
49 |
"saveInGSheet": {
|
50 |
"func": saveInGSheet,
|
|
|
52 |
"type": "function",
|
53 |
"function": {
|
54 |
"name": "saveInGSheet",
|
55 |
+
"description": "Saves the profile details in Google Sheet",
|
56 |
"parameters": {
|
57 |
"type": "object",
|
58 |
"properties": {
|
|
|
62 |
},
|
63 |
"role": {
|
64 |
"type": "string",
|
65 |
+
"description": "Role of the person in the Company"
|
66 |
},
|
67 |
"profileDetails": {
|
68 |
"type": "string",
|
|
|
76 |
}
|
77 |
}
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|