Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
305 lines (255 loc) Β· 11.1 KB
/
Copy pathapp.py
File metadata and controls
305 lines (255 loc) Β· 11.1 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
import streamlit as st
import re
import time
from pathlib import Path
import tempfile
from src.agent import Agent
# Page config
st.set_page_config(
page_title="Chartwell Insurance AI Assistant",
page_icon="π’",
layout="wide"
)
@st.cache_resource
def initialize_agent(
chunk_size=512,
chunk_overlap=50,
similarity_top_k=5,
system_prompt_override=None
):
"""Initialize the agent and connect to existing Pinecone index."""
agent = Agent(
name="Chartwell Insurance Assistant",
use_pinecone=True,
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
similarity_top_k=similarity_top_k,
system_prompt_override=system_prompt_override
)
# Try to connect to existing index first
try:
agent.connect_to_existing_index()
st.session_state.agent_status = "Connected to existing index"
return agent
except Exception as e:
st.session_state.agent_status = f"Failed to connect to existing index: {str(e)}"
return agent
def copy_to_clipboard(text):
"""Create a copy button for text content."""
# Clean up the text
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text) # Remove markdown bold
text = text.lstrip()
copy_button_html = f"""
<style>
.copy-button {{
background-color: rgb(19, 101, 168);
border: none;
color: white;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
border-radius: 5px;
width: 80px;
height: 35px;
display: inline-flex;
justify-content: center;
align-items: center;
}}
</style>
<button
class="copy-button"
onclick='navigator.clipboard.writeText(`{text}`)'>
Copy
</button>
"""
st.components.v1.html(copy_button_html, height=50)
def format_as_email(content, subject="Insurance Inquiry", recipient="Customer", sender="Chartwell Team"):
"""Format AI response as a professional email."""
email_content = f"""Subject: {subject}
Dear {recipient},
{content}
Best regards,
{sender}
Chartwell Insurance"""
return email_content
def clear_conversation():
"""Clear the conversation history."""
st.session_state.messages = []
# Initialize agent
if 'agent' not in st.session_state:
st.session_state.agent = initialize_agent()
# Sidebar
st.sidebar.image("https://www.chartwellins.com/img/~www.chartwellins.com/layout-assets/logo.png", use_container_width=True)
st.sidebar.title("Chartwell Insurance AI Assistant")
# Display agent status
if 'agent_status' in st.session_state:
if "Connected" in st.session_state.agent_status:
st.sidebar.success(st.session_state.agent_status)
else:
st.sidebar.error(st.session_state.agent_status)
# Navigation
st.sidebar.header("Navigation")
page = st.sidebar.radio("Go to", ["Chatbot", "Document Upload", "Index Status", "FAQ"])
# Document Upload Page
if page == "Document Upload":
st.header("π Document Upload")
st.write("Upload documents to enhance the AI assistant's knowledge base.")
uploaded_files = st.file_uploader(
"Choose PDF or TXT files",
type=["pdf", "txt", "csv"],
accept_multiple_files=True,
help="Upload multiple files to add to the knowledge base."
)
if st.button("Upload and Index Documents", type="primary"):
if uploaded_files:
# Create temporary directory for uploaded files
with tempfile.TemporaryDirectory() as temp_dir:
file_paths = []
for uploaded_file in uploaded_files:
file_path = Path(temp_dir) / uploaded_file.name
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
file_paths.append(str(file_path))
st.success(f"Saved {uploaded_file.name}")
# Ingest documents using the agent
with st.spinner('Processing and indexing documents...'):
progress_bar = st.progress(0)
try:
st.session_state.agent.ingest_directory(temp_dir)
progress_bar.progress(100)
st.success("β
Documents successfully indexed!")
# Update status
st.session_state.agent_status = f"Index updated with {len(uploaded_files)} new documents"
st.rerun()
except Exception as e:
st.error(f"β Error indexing documents: {str(e)}")
progress_bar.progress(0)
else:
st.warning("Please upload at least one file.")
# Chatbot Page
elif page == "Chatbot":
st.header("π¬ AI Assistant")
# Check if agent is ready
if st.session_state.agent.agent is None:
st.warning("β οΈ Agent not connected to index. Please upload documents or check your Pinecone configuration.")
st.stop()
# Initialize messages
if "messages" not in st.session_state:
st.session_state.messages = []
# Email formatting options in sidebar
st.sidebar.subheader("π§ Email Formatting")
subject = st.sidebar.text_input("Subject", value="Insurance Inquiry")
recipient = st.sidebar.text_input("Recipient", value="Customer")
sender = st.sidebar.text_input("Sender", value="Chartwell Team")
format_email = st.sidebar.checkbox("Format as Email", value=True)
# Chat interface
chat_container = st.container()
with chat_container:
for message in st.session_state.messages:
with st.chat_message(message["role"], avatar="π§βπΌ" if message["role"] == "user" else "π€"):
st.markdown(message['content'])
# User input
if user_input := st.chat_input("Ask about insurance policies, coverage, claims..."):
# Add user message
st.session_state.messages.append({"role": "user", "content": user_input})
with st.chat_message("user", avatar="π§βπΌ"):
st.markdown(user_input)
# Generate response
with st.chat_message("assistant", avatar="π€"):
message_placeholder = st.empty()
with st.spinner('π€ Analyzing documents and generating response...'):
try:
# Get response from agent
response = st.session_state.agent.chat(user_input)
# Format as email if requested
if format_email:
response = format_as_email(response, subject, recipient, sender)
# Simulate typing effect
full_response = ""
for char in response:
full_response += char
time.sleep(0.01)
message_placeholder.markdown(full_response + "β")
message_placeholder.markdown(full_response)
# Add to conversation history
st.session_state.messages.append({"role": "assistant", "content": full_response})
# Copy button
copy_to_clipboard(full_response)
except Exception as e:
st.error(f"β Error generating response: {str(e)}")
# Clear conversation button
if st.sidebar.button("ποΈ Clear Conversation", on_click=clear_conversation):
st.rerun()
# Index Status Page
elif page == "Index Status":
st.header("π Index Status")
# Get agent stats
stats = st.session_state.agent.get_index_stats()
col1, col2 = st.columns(2)
with col1:
st.subheader("Agent Information")
st.write(f"**Agent Name:** {stats.get('agent_name', 'N/A')}")
st.write(f"**Storage Type:** {stats.get('storage_type', 'N/A')}")
st.write(f"**Has Index:** {'β
Yes' if stats.get('has_index') else 'β No'}")
st.write(f"**Agent Ready:** {'β
Yes' if stats.get('has_agent') else 'β No'}")
with col2:
st.subheader("Configuration")
st.write(f"**Pinecone Configured:** {'β
Yes' if stats.get('pinecone_configured') else 'β No'}")
st.write(f"**Config Status:** {stats.get('config_status', 'N/A')}")
# Agent actions
st.subheader("Actions")
col3, col4 = st.columns(2)
with col3:
if st.button("π Reconnect to Index"):
try:
result = st.session_state.agent.connect_to_existing_index()
st.success(result)
st.rerun()
except Exception as e:
st.error(f"Failed to reconnect: {str(e)}")
with col4:
if st.button("ποΈ Reset Agent"):
st.session_state.agent.reset()
st.session_state.messages = []
st.success("Agent reset successfully!")
st.rerun()
# FAQ Page
elif page == "FAQ":
st.header("β Frequently Asked Questions")
faqs = [
{
"question": "How does the AI assistant work?",
"answer": "The AI assistant uses advanced language models and retrieves information from indexed insurance documents to provide accurate, contextual responses to your queries."
},
{
"question": "What documents are in the knowledge base?",
"answer": "The knowledge base contains various insurance policies, contracts, and documentation including Berkley One policies, Chubb contracts, and other insurance-related materials."
},
{
"question": "How do I upload new documents?",
"answer": "Go to the 'Document Upload' page, select your PDF or TXT files, and click 'Upload and Index Documents'. The AI will process and add them to its knowledge base."
},
{
"question": "Can I format responses as emails?",
"answer": "Yes! In the Chatbot page, use the sidebar options to customize email formatting including subject, recipient, and sender information."
},
{
"question": "What if the assistant can't find relevant information?",
"answer": "The assistant will let you know if it cannot find relevant information in the indexed documents. You may need to upload additional documents or rephrase your question."
},
{
"question": "How do I clear my conversation history?",
"answer": "Use the 'ποΈ Clear Conversation' button in the sidebar of the Chatbot page to start a fresh conversation."
}
]
for faq in faqs:
with st.expander(faq["question"]):
st.write(faq["answer"])
# Footer
st.markdown("---")
st.markdown("""
<div style='text-align: center;'>
<p>Β© 2024 <strong>Chartwell Insurance</strong>. All rights reserved.</p>
<p><i>Disclaimer: This AI assistant is a tool and may provide inaccurate information. Always verify important details with official documentation.</i></p>
</div>
""", unsafe_allow_html=True)