ofermend commited on
Commit
3108590
·
1 Parent(s): bd226e3

update to v0.1.16

Browse files
Files changed (5) hide show
  1. .gitignore +2 -1
  2. agent.py +6 -12
  3. app.py +1 -153
  4. requirements.txt +1 -1
  5. st_app.py +169 -0
.gitignore CHANGED
@@ -11,6 +11,7 @@ core/__pycache__/
11
  *.so
12
 
13
  # Distribution / packaging
 
14
  .Python
15
  build/
16
  develop-eggs/
@@ -140,4 +141,4 @@ dmypy.json
140
  project.yaml
141
 
142
  .idea/
143
- ev_database.db
 
11
  *.so
12
 
13
  # Distribution / packaging
14
+ *.db
15
  .Python
16
  build/
17
  develop-eggs/
 
141
  project.yaml
142
 
143
  .idea/
144
+ ev_database.db
agent.py CHANGED
@@ -4,7 +4,7 @@ from pydantic import Field, BaseModel
4
  from omegaconf import OmegaConf
5
 
6
  from llama_index.core.utilities.sql_wrapper import SQLDatabase
7
- from sqlalchemy import create_engine, text
8
 
9
  from dotenv import load_dotenv
10
  load_dotenv(override=True)
@@ -22,7 +22,6 @@ def create_assistant_tools(cfg):
22
  vectara_corpus_id=cfg.corpus_ids)
23
 
24
  summarizer = 'vectara-experimental-summary-ext-2023-12-11-med-omni'
25
-
26
  ask_complaints = vec_factory.create_rag_tool(
27
  tool_name = "ask_complaints",
28
  tool_description = """
@@ -32,9 +31,9 @@ def create_assistant_tools(cfg):
32
  tool_args_schema = QueryCFPBComplaints,
33
  reranker = "multilingual_reranker_v1", rerank_k = 100,
34
  n_sentences_before = 2, n_sentences_after = 2, lambda_val = 0.005,
35
- summary_num_results = 5,
36
  vectara_summarizer = summarizer,
37
- include_citations = False,
38
  )
39
 
40
  tools_factory = ToolsFactory()
@@ -53,17 +52,12 @@ def create_assistant_tools(cfg):
53
 
54
  def initialize_agent(_cfg, update_func=None):
55
  cfpb_complaints_bot_instructions = """
56
- - You are a helpful research assistant, with expertise in complaints from the Consumer Financial Protection Bureau, in conversation with a user.
 
 
57
  - For a query with multiple sub-questions, break down the query into the sub-questions,
58
  and make separate calls to the ask_complaints tool to answer each sub-question,
59
  then combine the answers to provide a complete response.
60
- - If you do not find an answer from one of the tools, try to use the other tools to answer the query.
61
- - Before answering any user query, use cfpb_describe_tables to understand schema of each table, and use get_sample_data
62
- to get sample data from each table in the database, so that you can understand NULL and unique values for each column.
63
- - Use the database tools (cfpb_load_data, cfpb_describe_tables and cfpb_list_tables) to answer analytical queries.
64
- - IMPORTANT: When using database_tools, always call the ev_load_sample_data tool with the table you want to query
65
- to understand the table structure, column naming, and values in the table. Never call the cfpb_load_data tool for a query until you have called cfpb_load_sample_data.
66
- - When providing links, try to put the name of the website or source of information for the displayed text. Don't just say 'Source'.
67
  - Never discuss politics, and always respond politely.
68
  """
69
 
 
4
  from omegaconf import OmegaConf
5
 
6
  from llama_index.core.utilities.sql_wrapper import SQLDatabase
7
+ from sqlalchemy import create_engine
8
 
9
  from dotenv import load_dotenv
10
  load_dotenv(override=True)
 
22
  vectara_corpus_id=cfg.corpus_ids)
23
 
24
  summarizer = 'vectara-experimental-summary-ext-2023-12-11-med-omni'
 
25
  ask_complaints = vec_factory.create_rag_tool(
26
  tool_name = "ask_complaints",
27
  tool_description = """
 
31
  tool_args_schema = QueryCFPBComplaints,
32
  reranker = "multilingual_reranker_v1", rerank_k = 100,
33
  n_sentences_before = 2, n_sentences_after = 2, lambda_val = 0.005,
34
+ summary_num_results = 15,
35
  vectara_summarizer = summarizer,
36
+ include_citations = True,
37
  )
38
 
39
  tools_factory = ToolsFactory()
 
52
 
53
  def initialize_agent(_cfg, update_func=None):
54
  cfpb_complaints_bot_instructions = """
55
+ - You are a helpful research assistant,
56
+ with expertise in finance and complaints from the CFPB (Consumer Financial Protection Bureau),
57
+ in conversation with a user.
58
  - For a query with multiple sub-questions, break down the query into the sub-questions,
59
  and make separate calls to the ask_complaints tool to answer each sub-question,
60
  then combine the answers to provide a complete response.
 
 
 
 
 
 
 
61
  - Never discuss politics, and always respond politely.
62
  """
63
 
app.py CHANGED
@@ -1,166 +1,14 @@
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
  import nest_asyncio
11
  import asyncio
12
 
13
- from utils import thumbs_feedback, escape_dollars_outside_latex, send_amplitude_data
14
-
15
  import sqlite3
16
  from datasets import load_dataset
17
 
18
- from vectara_agentic.agent import AgentStatusType
19
- from agent import initialize_agent, get_agent_config
20
-
21
-
22
- initial_prompt = "How can I help you today?"
23
-
24
- # Setup for HTTP API Calls to Amplitude Analytics
25
- if 'device_id' not in st.session_state:
26
- st.session_state.device_id = str(uuid.uuid4())
27
-
28
-
29
- if "feedback_key" not in st.session_state:
30
- st.session_state.feedback_key = 0
31
-
32
- def toggle_logs():
33
- st.session_state.show_logs = not st.session_state.show_logs
34
-
35
- def show_example_questions():
36
- if len(st.session_state.example_messages) > 0 and st.session_state.first_turn:
37
- selected_example = pills("Queries to Try:", st.session_state.example_messages, index=None)
38
- if selected_example:
39
- st.session_state.ex_prompt = selected_example
40
- st.session_state.first_turn = False
41
- return True
42
- return False
43
-
44
- def update_func(status_type: AgentStatusType, msg: str):
45
- if status_type != AgentStatusType.AGENT_UPDATE:
46
- output = f"{status_type.value} - {msg}"
47
- st.session_state.log_messages.append(output)
48
-
49
- async def launch_bot():
50
- def reset():
51
- st.session_state.messages = [{"role": "assistant", "content": initial_prompt, "avatar": "🦖"}]
52
- st.session_state.thinking_message = "Agent at work..."
53
- st.session_state.log_messages = []
54
- st.session_state.prompt = None
55
- st.session_state.ex_prompt = None
56
- st.session_state.first_turn = True
57
- st.session_state.show_logs = False
58
- if 'agent' not in st.session_state:
59
- st.session_state.agent = initialize_agent(cfg, update_func=update_func)
60
-
61
- if 'cfg' not in st.session_state:
62
- cfg = get_agent_config()
63
- st.session_state.cfg = cfg
64
- st.session_state.ex_prompt = None
65
- example_messages = [example.strip() for example in cfg.examples.split(";")] if cfg.examples else []
66
- st.session_state.example_messages = [em for em in example_messages if len(em)>0]
67
- reset()
68
-
69
- cfg = st.session_state.cfg
70
-
71
- # left side content
72
- with st.sidebar:
73
- image = Image.open('Vectara-logo.png')
74
- st.image(image, width=175)
75
- st.markdown(f"## {cfg['demo_welcome']}")
76
- st.markdown(f"{cfg['demo_description']}")
77
-
78
- st.markdown("\n\n")
79
- bc1, _ = st.columns([1, 1])
80
- with bc1:
81
- if st.button('Start Over'):
82
- reset()
83
- st.rerun()
84
-
85
- st.divider()
86
- st.markdown(
87
- "## How this works?\n"
88
- "This app was built with [Vectara](https://vectara.com).\n\n"
89
- "It demonstrates the use of Agentic RAG functionality with Vectara"
90
- )
91
-
92
- if "messages" not in st.session_state.keys():
93
- reset()
94
-
95
- # Display chat messages
96
- for message in st.session_state.messages:
97
- with st.chat_message(message["role"], avatar=message["avatar"]):
98
- st.write(message["content"])
99
-
100
- example_container = st.empty()
101
- with example_container:
102
- if show_example_questions():
103
- example_container.empty()
104
- st.session_state.first_turn = False
105
- st.rerun()
106
-
107
- # User-provided prompt
108
- if st.session_state.ex_prompt:
109
- prompt = st.session_state.ex_prompt
110
- else:
111
- prompt = st.chat_input()
112
- if prompt:
113
- st.session_state.messages.append({"role": "user", "content": prompt, "avatar": '🧑‍💻'})
114
- st.session_state.prompt = prompt # Save the prompt in session state
115
- st.session_state.log_messages = []
116
- st.session_state.show_logs = False
117
- with st.chat_message("user", avatar='🧑‍💻'):
118
- print(f"Starting new question: {prompt}\n")
119
- st.write(prompt)
120
- st.session_state.ex_prompt = None
121
-
122
- # Generate a new response if last message is not from assistant
123
- if st.session_state.prompt:
124
- with st.chat_message("assistant", avatar='🤖'):
125
- with st.spinner(st.session_state.thinking_message):
126
- res = st.session_state.agent.chat(st.session_state.prompt)
127
- res = escape_dollars_outside_latex(res)
128
- message = {"role": "assistant", "content": res, "avatar": '🤖'}
129
- st.session_state.messages.append(message)
130
- st.markdown(res)
131
-
132
- send_amplitude_data(
133
- user_query=st.session_state.messages[-2]["content"],
134
- bot_response=st.session_state.messages[-1]["content"],
135
- demo_name=cfg['demo_name']
136
- )
137
-
138
- st.session_state.ex_prompt = None
139
- st.session_state.prompt = None
140
- st.session_state.first_turn = False
141
- st.rerun()
142
-
143
- # Record user feedback
144
- if (st.session_state.messages[-1]["role"] == "assistant") & (st.session_state.messages[-1]["content"] != initial_prompt):
145
- streamlit_feedback(
146
- feedback_type="thumbs", on_submit = thumbs_feedback, key = st.session_state.feedback_key,
147
- kwargs = {"user_query": st.session_state.messages[-2]["content"],
148
- "bot_response": st.session_state.messages[-1]["content"],
149
- "demo_name": cfg["demo_name"]}
150
- )
151
-
152
- log_placeholder = st.empty()
153
- with log_placeholder.container():
154
- if st.session_state.show_logs:
155
- st.button("Hide Logs", on_click=toggle_logs)
156
- for msg in st.session_state.log_messages:
157
- st.text(msg)
158
- else:
159
- if len(st.session_state.log_messages) > 0:
160
- st.button("Show Logs", on_click=toggle_logs)
161
-
162
- sys.stdout.flush()
163
-
164
  def setup_db():
165
  db_path = 'cfpb_database.db'
166
  conn = sqlite3.connect(db_path)
 
 
 
1
  import os
 
2
 
3
  import streamlit as st
4
+ from st_app import launch_bot
 
5
 
6
  import nest_asyncio
7
  import asyncio
8
 
 
 
9
  import sqlite3
10
  from datasets import load_dataset
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def setup_db():
13
  db_path = 'cfpb_database.db'
14
  conn = sqlite3.connect(db_path)
requirements.txt CHANGED
@@ -7,4 +7,4 @@ langdetect==1.0.9
7
  langcodes==3.4.0
8
  datasets==2.19.2
9
  uuid==1.30
10
- vectara-agentic==0.1.15
 
7
  langcodes==3.4.0
8
  datasets==2.19.2
9
  uuid==1.30
10
+ vectara-agentic==0.1.16
st_app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ import sys
3
+ import uuid
4
+
5
+ import streamlit as st
6
+ from streamlit_pills import pills
7
+ from streamlit_feedback import streamlit_feedback
8
+
9
+ from utils import thumbs_feedback, escape_dollars_outside_latex, send_amplitude_data
10
+
11
+ from vectara_agentic.agent import AgentStatusType
12
+ from agent import initialize_agent, get_agent_config
13
+
14
+ initial_prompt = "How can I help you today?"
15
+
16
+ # Setup for HTTP API Calls to Amplitude Analytics
17
+ if 'device_id' not in st.session_state:
18
+ st.session_state.device_id = str(uuid.uuid4())
19
+
20
+
21
+ if "feedback_key" not in st.session_state:
22
+ st.session_state.feedback_key = 0
23
+
24
+ def toggle_logs():
25
+ st.session_state.show_logs = not st.session_state.show_logs
26
+
27
+ def show_example_questions():
28
+ if len(st.session_state.example_messages) > 0 and st.session_state.first_turn:
29
+ selected_example = pills("Queries to Try:", st.session_state.example_messages, index=None)
30
+ if selected_example:
31
+ st.session_state.ex_prompt = selected_example
32
+ st.session_state.first_turn = False
33
+ return True
34
+ return False
35
+
36
+ def update_func(status_type: AgentStatusType, msg: str):
37
+ if status_type != AgentStatusType.AGENT_UPDATE:
38
+ output = f"{status_type.value} - {msg}"
39
+ st.session_state.log_messages.append(output)
40
+
41
+ async def launch_bot():
42
+ def reset():
43
+ st.session_state.messages = [{"role": "assistant", "content": initial_prompt, "avatar": "🦖"}]
44
+ st.session_state.thinking_message = "Agent at work..."
45
+ st.session_state.log_messages = []
46
+ st.session_state.prompt = None
47
+ st.session_state.ex_prompt = None
48
+ st.session_state.first_turn = True
49
+ st.session_state.logs_enabled = False
50
+ st.session_state.show_logs = False
51
+ if 'agent' not in st.session_state:
52
+ st.session_state.agent = initialize_agent(cfg, update_func=update_func)
53
+ else:
54
+ st.session_state.agent.clear_memory()
55
+
56
+ if 'cfg' not in st.session_state:
57
+ cfg = get_agent_config()
58
+ st.session_state.cfg = cfg
59
+ st.session_state.ex_prompt = None
60
+ example_messages = [example.strip() for example in cfg.examples.split(";")] if cfg.examples else []
61
+ st.session_state.example_messages = [em for em in example_messages if len(em)>0]
62
+ reset()
63
+
64
+ cfg = st.session_state.cfg
65
+
66
+ # left side content
67
+ with st.sidebar:
68
+ image = Image.open('Vectara-logo.png')
69
+ st.image(image, width=175)
70
+ st.markdown(f"## {cfg['demo_welcome']}")
71
+ st.markdown(f"{cfg['demo_description']}")
72
+
73
+ st.markdown("\n\n")
74
+ bc1, bc2 = st.columns([1, 1])
75
+ with bc1:
76
+ if st.button('Start Over'):
77
+ reset()
78
+ st.rerun()
79
+ with bc2: # Updated button for enabling/disabling logs
80
+ if st.session_state.logs_enabled:
81
+ if st.button('Disable Logs', key='disable_logs'):
82
+ st.session_state.logs_enabled = False
83
+ st.rerun()
84
+ else:
85
+ if st.button('Enable Logs', key='enable_logs'):
86
+ st.session_state.logs_enabled = True
87
+ st.rerun()
88
+
89
+ st.divider()
90
+ st.markdown(
91
+ "## How this works?\n"
92
+ "This app was built with [Vectara](https://vectara.com).\n\n"
93
+ "It demonstrates the use of Agentic RAG functionality with Vectara"
94
+ )
95
+
96
+ if "messages" not in st.session_state.keys():
97
+ reset()
98
+
99
+ # Display chat messages
100
+ for message in st.session_state.messages:
101
+ with st.chat_message(message["role"], avatar=message["avatar"]):
102
+ st.write(message["content"])
103
+
104
+ example_container = st.empty()
105
+ with example_container:
106
+ if show_example_questions():
107
+ example_container.empty()
108
+ st.session_state.first_turn = False
109
+ st.rerun()
110
+
111
+ # User-provided prompt
112
+ if st.session_state.ex_prompt:
113
+ prompt = st.session_state.ex_prompt
114
+ else:
115
+ prompt = st.chat_input()
116
+ if prompt:
117
+ st.session_state.messages.append({"role": "user", "content": prompt, "avatar": '🧑‍💻'})
118
+ st.session_state.prompt = prompt # Save the prompt in session state
119
+ st.session_state.log_messages = []
120
+ st.session_state.show_logs = False
121
+ with st.chat_message("user", avatar='🧑‍💻'):
122
+ print(f"Starting new question: {prompt}\n")
123
+ st.write(prompt)
124
+ st.session_state.ex_prompt = None
125
+
126
+ # Generate a new response if last message is not from assistant
127
+ if st.session_state.prompt:
128
+ with st.chat_message("assistant", avatar='🤖'):
129
+ with st.spinner(st.session_state.thinking_message):
130
+ res = st.session_state.agent.chat(st.session_state.prompt)
131
+ res = escape_dollars_outside_latex(res)
132
+ message = {"role": "assistant", "content": res, "avatar": '🤖'}
133
+ st.session_state.messages.append(message)
134
+ st.markdown(res)
135
+
136
+ send_amplitude_data(
137
+ user_query=st.session_state.messages[-2]["content"],
138
+ bot_response=st.session_state.messages[-1]["content"],
139
+ demo_name=cfg['demo_name']
140
+ )
141
+
142
+ st.session_state.ex_prompt = None
143
+ st.session_state.prompt = None
144
+ st.session_state.first_turn = False
145
+ st.rerun()
146
+
147
+ # Record user feedback
148
+ if (st.session_state.messages[-1]["role"] == "assistant") & (st.session_state.messages[-1]["content"] != initial_prompt):
149
+ if st.session_state.show_logs and st.session_state.logs_enabled: # Only show logs if enabled
150
+ streamlit_feedback(
151
+ feedback_type="thumbs", on_submit=thumbs_feedback, key=st.session_state.feedback_key,
152
+ kwargs={"user_query": st.session_state.messages[-2]["content"],
153
+ "bot_response": st.session_state.messages[-1]["content"],
154
+ "demo_name": cfg["demo_name"]}
155
+ )
156
+
157
+ log_placeholder = st.empty()
158
+ with log_placeholder.container():
159
+ if st.session_state.logs_enabled: # Show logs button only if log toggle is enabled
160
+ if st.session_state.show_logs:
161
+ st.button("Hide Logs", on_click=toggle_logs)
162
+ for msg in st.session_state.log_messages:
163
+ st.text(msg)
164
+ else:
165
+ if len(st.session_state.log_messages) > 0:
166
+ st.button("Show Logs", on_click=toggle_logs)
167
+
168
+
169
+ sys.stdout.flush()