ofermend commited on
Commit
14aa01b
1 Parent(s): 35cdc9b

added amplitude analytics and other bug fixes

Browse files
Files changed (3) hide show
  1. agent.py +5 -3
  2. app.py +15 -65
  3. utils.py +74 -0
agent.py CHANGED
@@ -72,6 +72,7 @@ def create_assistant_tools(cfg):
72
  return (tools_factory.standard_tools() +
73
  tools_factory.guardrail_tools() +
74
  tools_factory.database_tools(
 
75
  content_description = 'Electric Vehicles in the state of Washington',
76
  sql_database = SQLDatabase(create_engine('sqlite:///ev_database.db')),
77
  ) +
@@ -85,9 +86,10 @@ def initialize_agent(_cfg, update_func=None):
85
  - For a query with multiple sub-questions, break down the query into the sub-questions,
86
  and make separate calls to the ask_vehicles or ask_policies tool to answer each sub-question,
87
  then combine the answers to provide a complete response.
88
- - Use the database tools to answer analytical questions.
89
- - IMPORTANT: When using database tools, always query SELECT * FROM (table_name) LIMIT 25; first to figure out the format of the columns and
90
- then call the tool again to try to answer the user's question.
 
91
  - When providing links, try to put the name of the website or source of information for the displayed text. Don't just say 'Source'.
92
  - Never discuss politics, and always respond politely.
93
  """
 
72
  return (tools_factory.standard_tools() +
73
  tools_factory.guardrail_tools() +
74
  tools_factory.database_tools(
75
+ tool_name_prefix = "ev",
76
  content_description = 'Electric Vehicles in the state of Washington',
77
  sql_database = SQLDatabase(create_engine('sqlite:///ev_database.db')),
78
  ) +
 
86
  - For a query with multiple sub-questions, break down the query into the sub-questions,
87
  and make separate calls to the ask_vehicles or ask_policies tool to answer each sub-question,
88
  then combine the answers to provide a complete response.
89
+ - Use the database tools (ev_load_data, ev_describe_tables and ev_list_tables) to answer analytical queries.
90
+ - IMPORTANT: When using database tools, always "query SELECT * FROM (table_name) LIMIT 25;" first to figure out the format of the columns and
91
+ then call the tool again to try to answer the user's query.
92
+ - Avoid "SELECT *" queries on tables, as they can be slow, instead craft the correct query to get the required information.
93
  - When providing links, try to put the name of the website or source of information for the displayed text. Don't just say 'Source'.
94
  - Never discuss politics, and always respond politely.
95
  """
app.py CHANGED
@@ -1,19 +1,15 @@
1
  from PIL import Image
2
  import sys
3
  import os
4
- import requests
5
- import json
6
  import uuid
7
 
8
  import streamlit as st
9
  from streamlit_pills import pills
10
  from streamlit_feedback import streamlit_feedback
11
 
12
- from langdetect import detect_langs
13
- from langcodes import Language
14
 
15
  import sqlite3
16
- import pandas as pd
17
  from datasets import load_dataset
18
 
19
  from vectara_agent.agent import AgentStatusType
@@ -26,40 +22,6 @@ initial_prompt = "How can I help you today?"
26
  if 'device_id' not in st.session_state:
27
  st.session_state.device_id = str(uuid.uuid4())
28
 
29
- headers = {
30
- 'Content-Type': 'application/json',
31
- 'Accept': '*/*'
32
- }
33
- amp_api_key = os.getenv('AMPLITUDE_TOKEN')
34
-
35
- def identifyLanguage(response):
36
- lang_code = detect_langs(response)[0].lang
37
- return Language.make(language=lang_code).display_name()
38
-
39
- def thumbs_feedback(feedback, **kwargs):
40
- """
41
- Sends feedback to Amplitude Analytics
42
- """
43
- data = {
44
- "api_key": amp_api_key,
45
- "events": [{
46
- "device_id": st.session_state.device_id,
47
- "event_type": "provided_feedback",
48
- "event_properties": {
49
- "Space Name": kwargs.get("demo_name", "Unknown"),
50
- "Demo Type": "Agent",
51
- "query": kwargs.get("prompt", "No user input"),
52
- "response": kwargs.get("response", "No chat response"),
53
- "feedback": feedback["score"],
54
- "Response Language": kwargs.get("language", "Unknown language")
55
- }
56
- }]
57
- }
58
- response = requests.post('https://api2.amplitude.com/2/httpapi', headers=headers, data=json.dumps(data))
59
- if response.status_code != 200:
60
- print(f"Request failed with status code {response.status_code}. Response Text: {response.text}")
61
-
62
- st.session_state.feedback_key += 1
63
 
64
  if "feedback_key" not in st.session_state:
65
  st.session_state.feedback_key = 0
@@ -117,7 +79,7 @@ def launch_bot():
117
  reset()
118
  st.rerun()
119
 
120
- st.markdown("---")
121
  st.markdown(
122
  "## How this works?\n"
123
  "This app was built with [Vectara](https://vectara.com).\n\n"
@@ -159,29 +121,16 @@ def launch_bot():
159
  with st.chat_message("assistant", avatar='🤖'):
160
  with st.spinner(st.session_state.thinking_message):
161
  res = st.session_state.agent.chat(st.session_state.prompt)
162
- res = res.replace('$', '\\$') # escape dollar sign for markdown
163
  message = {"role": "assistant", "content": res, "avatar": '🤖'}
164
  st.session_state.messages.append(message)
165
  st.markdown(res)
166
 
167
- # Send query and response to Amplitude Analytics
168
- data = {
169
- "api_key": amp_api_key,
170
- "events": [{
171
- "device_id": st.session_state.device_id,
172
- "event_type": "submitted_query",
173
- "event_properties": {
174
- "Space Name": cfg['demo_name'],
175
- "Demo Type": "Agent",
176
- "query": st.session_state.messages[-2]["content"],
177
- "response": st.session_state.messages[-1]["content"],
178
- "Response Language": identifyLanguage(st.session_state.messages[-1]["content"])
179
- }
180
- }]
181
- }
182
- response = requests.post('https://api2.amplitude.com/2/httpapi', headers=headers, data=json.dumps(data))
183
- if response.status_code != 200:
184
- print(f"Request failed with status code {response.status_code}. Response Text: {response.text}")
185
 
186
  st.session_state.ex_prompt = None
187
  st.session_state.prompt = None
@@ -189,12 +138,13 @@ def launch_bot():
189
  st.rerun()
190
 
191
  # Record user feedback
192
- if (st.session_state.messages[-1]["role"] == "assistant") & (st.session_state.messages[-1]["content"] != "How can I help you today?"):
193
- streamlit_feedback(feedback_type="thumbs", on_submit = thumbs_feedback, key = st.session_state.feedback_key,
194
- kwargs = {"prompt": st.session_state.messages[-2]["content"],
195
- "response": st.session_state.messages[-1]["content"],
196
- "demo_name": cfg["demo_name"],
197
- "language": identifyLanguage(st.session_state.messages[-1]["content"])})
 
198
 
199
  log_placeholder = st.empty()
200
  with log_placeholder.container():
 
1
  from PIL import Image
2
  import sys
3
  import os
 
 
4
  import uuid
5
 
6
  import streamlit as st
7
  from streamlit_pills import pills
8
  from streamlit_feedback import streamlit_feedback
9
 
10
+ from utils import thumbs_feedback, escape_dollars_outside_latex, send_amplitude_data
 
11
 
12
  import sqlite3
 
13
  from datasets import load_dataset
14
 
15
  from vectara_agent.agent import AgentStatusType
 
22
  if 'device_id' not in st.session_state:
23
  st.session_state.device_id = str(uuid.uuid4())
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  if "feedback_key" not in st.session_state:
27
  st.session_state.feedback_key = 0
 
79
  reset()
80
  st.rerun()
81
 
82
+ st.divider()
83
  st.markdown(
84
  "## How this works?\n"
85
  "This app was built with [Vectara](https://vectara.com).\n\n"
 
121
  with st.chat_message("assistant", avatar='🤖'):
122
  with st.spinner(st.session_state.thinking_message):
123
  res = st.session_state.agent.chat(st.session_state.prompt)
124
+ res = escape_dollars_outside_latex(res)
125
  message = {"role": "assistant", "content": res, "avatar": '🤖'}
126
  st.session_state.messages.append(message)
127
  st.markdown(res)
128
 
129
+ send_amplitude_data(
130
+ user_query=st.session_state.messages[-2]["content"],
131
+ bot_response=st.session_state.messages[-1]["content"],
132
+ demo_name=cfg['demo_name']
133
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  st.session_state.ex_prompt = None
136
  st.session_state.prompt = None
 
138
  st.rerun()
139
 
140
  # Record user feedback
141
+ if (st.session_state.messages[-1]["role"] == "assistant") & (st.session_state.messages[-1]["content"] != initial_prompt):
142
+ streamlit_feedback(
143
+ feedback_type="thumbs", on_submit = thumbs_feedback, key = st.session_state.feedback_key,
144
+ kwargs = {"user_query": st.session_state.messages[-2]["content"],
145
+ "bot_response": st.session_state.messages[-1]["content"],
146
+ "demo_name": cfg["demo_name"]}
147
+ )
148
 
149
  log_placeholder = st.empty()
150
  with log_placeholder.container():
utils.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import json
4
+ import re
5
+
6
+ import streamlit as st
7
+
8
+ from langdetect import detect_langs
9
+ from langcodes import Language
10
+
11
+ headers = {
12
+ 'Content-Type': 'application/json',
13
+ 'Accept': '*/*'
14
+ }
15
+
16
+ def identify_language(response):
17
+ lang_code = detect_langs(response)[0].lang
18
+ return Language.make(language=lang_code).display_name()
19
+
20
+ def thumbs_feedback(feedback, **kwargs):
21
+ """
22
+ Sends feedback to Amplitude Analytics
23
+ """
24
+ send_amplitude_data(
25
+ user_query=kwargs.get("user_query", "No user input"),
26
+ bot_response=kwargs.get("bot_response", "No bot response"),
27
+ demo_name=kwargs.get("demo_name", "Unknown"),
28
+ feedback=feedback['score'],
29
+ )
30
+ st.session_state.feedback_key += 1
31
+
32
+ def send_amplitude_data(user_query, bot_response, demo_name, feedback=None):
33
+ # Send query and response to Amplitude Analytics
34
+ data = {
35
+ "api_key": os.getenv('AMPLITUDE_TOKEN'),
36
+ "events": [{
37
+ "device_id": st.session_state.device_id,
38
+ "event_type": "submitted_query",
39
+ "event_properties": {
40
+ "Space Name": demo_name,
41
+ "Demo Type": "Agent",
42
+ "query": user_query,
43
+ "response": bot_response,
44
+ "Response Language": identify_language(bot_response)
45
+ }
46
+ }]
47
+ }
48
+ if feedback:
49
+ data["events"][0]["event_properties"]["feedback"] = feedback
50
+
51
+ response = requests.post('https://api2.amplitude.com/2/httpapi', headers=headers, data=json.dumps(data))
52
+ if response.status_code != 200:
53
+ print(f"Amplitude request failed with status code {response.status_code}. Response Text: {response.text}")
54
+
55
+ def escape_dollars_outside_latex(text):
56
+ # Define a regex pattern to find LaTeX equations (either single $ or double $$)
57
+ pattern = re.compile(r'(\$\$.*?\$\$|\$.*?\$)')
58
+ latex_matches = pattern.findall(text)
59
+
60
+ # Placeholder to temporarily store LaTeX equations
61
+ placeholders = {}
62
+ for i, match in enumerate(latex_matches):
63
+ placeholder = f'__LATEX_PLACEHOLDER_{i}__'
64
+ placeholders[placeholder] = match
65
+ text = text.replace(match, placeholder)
66
+
67
+ # Escape dollar signs in the rest of the text
68
+ text = text.replace('$', '\\$')
69
+
70
+ # Replace placeholders with the original LaTeX equations
71
+ for placeholder, original in placeholders.items():
72
+ text = text.replace(placeholder, original)
73
+ return text
74
+