Aniq-63 commited on
Commit
5e67bfb
·
verified ·
1 Parent(s): 76ef955

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +164 -151
app.py CHANGED
@@ -12,81 +12,47 @@ from langchain.tools import Tool
12
  from langchain.agents import AgentExecutor, create_tool_calling_agent
13
  from langchain_core.messages import HumanMessage, AIMessage
14
 
15
-
16
  # --- Database Setup ---
17
-
18
- # Database initialization with caching
19
  @st.cache_resource
20
  def init_db():
21
  conn = sqlite3.connect('users.db', check_same_thread=False)
22
  c = conn.cursor()
 
 
23
  c.execute('''CREATE TABLE IF NOT EXISTS users
24
  (id INTEGER PRIMARY KEY AUTOINCREMENT,
25
  username TEXT UNIQUE NOT NULL,
26
  password TEXT NOT NULL,
27
  previous_chat_history TEXT,
28
  previous_products_bought TEXT)''')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  conn.commit()
30
  return conn
31
 
32
  conn = init_db()
33
 
34
-
35
  class User:
36
- def __init__(self, id, username, password, chat_history = None, products_bought = None):
37
- self.id = id
38
- self.username = username
39
- self.password = password
40
- self.chat_history = chat_history or []
41
- self.products_bought = products_bought or []
42
-
43
- # To register a new user
44
- @classmethod
45
- def create(cls, username, password):
46
- hashed_pw = generate_password_hash(password)
47
- conn = sqlite3.connect('users.db')
48
- c = conn.cursor()
49
- c.execute('INSERT INTO users (username, password) VALUES (?, ?)',(username, hashed_pw))
50
- user_id = c.lastrowid
51
- conn.commit()
52
- conn.close()
53
- return cls(user_id, username, hashed_pw)
54
-
55
- # To retrieve an existing user from the database by username.
56
- @classmethod
57
- def get_by_username(cls, username):
58
- conn = sqlite3.connect('users.db')
59
- c = conn.cursor()
60
- c.execute('SELECT * FROM users WHERE username = ?', (username,))
61
- user = c.fetchone()
62
- conn.close()
63
- if user:
64
- return cls(user[0], user[1], user[2],
65
- eval(user[3]) if user[3] else [],
66
- eval(user[4]) if user[4] else [])
67
- return None
68
-
69
- def update_chat_history(self, new_messages):
70
- conn = sqlite3.connect('users.db')
71
- c = conn.cursor()
72
- updated_history = self.chat_history + new_messages
73
- c.execute('UPDATE users SET previous_chat_history = ? WHERE id = ?',
74
- (str(updated_history), self.id))
75
- conn.commit()
76
- conn.close()
77
-
78
- def update_products_bought(self, new_products):
79
- conn = sqlite3.connect('users.db')
80
- c = conn.cursor()
81
- updated_products = self.products_bought + new_products
82
- c.execute('UPDATE users SET previous_products_bought = ? WHERE id = ?',
83
- (str(updated_products), self.id))
84
- conn.commit()
85
- conn.close()
86
-
87
 
88
  # --- AI Agent Setup ---
89
- # Load the LLM model from Groq
90
  os.environ["GROQ_API_KEY"] = st.secrets["GROQ_API_KEY"]
91
  llm = ChatGroq(
92
  temperature=0.1,
@@ -94,12 +60,10 @@ llm = ChatGroq(
94
  api_key=st.secrets["GROQ_API_KEY"],
95
  )
96
 
97
- # Load the HuggingFace Embeddings
98
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
99
 
100
- # Load and process CSV data
101
  @st.cache_resource
102
- def load_data():
103
  loader = CSVLoader(file_path="electronics_products.csv")
104
  docs = loader.load()
105
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
@@ -107,88 +71,86 @@ def load_data():
107
  vectorstore = InMemoryVectorStore.from_documents(documents=splits, embedding=embeddings)
108
  return vectorstore.as_retriever()
109
 
110
- retriever = load_data()
111
-
112
- def retrieve_query(query: str):
113
- """Retrieves documents related to the query."""
114
- return retriever.get_relevant_documents(query)
115
-
116
- tool = Tool(
117
- name="retriever",
118
- func=retrieve_query,
119
- description="Useful for retrieving product information"
120
- )
121
-
122
- # Agent setup
123
- # System prompt template
124
- system_prompt = """
125
- You are {agent_name}, the AI Sales Assistant for {company_name} ({company_business}).
126
-
127
- Company Profile:
128
- - Company Name: {company_name}
129
- - Business: {company_business}
130
- - Key Features: {key_features}
131
-
132
- Product Availability:
133
- - Only recommend and discuss products listed in the provided in document.
134
- - Do not suggest unavailable or out-of-stock products.
135
- - Always verify product availability before making recommendations.
136
-
137
- Conversation Flow:
138
- 1. Introduction
139
- 2. Qualification
140
- 3. Understanding Needs
141
- 4. Needs Analysis
142
- 5. Solution Presentation (Only recommend available products)
143
- 6. Confirmation
144
- 7. If the prospect agrees to purchase, thank them and provide the payment link: https://www.example.com/payment
145
-
146
- Guidelines:
147
- - Maintain natural, professional conversations
148
- - Follow company policies
149
- - Be helpful and polite
150
- - Always cross-check product recommendations with the available inventory in the CSV document
151
- """
152
-
153
- # Define the company and agent details
154
- company_name = "TechElectronics"
155
- company_business = "Consumer Electronics Retailer"
156
- agent_name = "Alex"
157
- key_features = "Cutting-edge technology, Competitive pricing, Excellent customer service"
158
 
159
- # Format the system prompt with the company and agent details
160
- formatted_system_prompt = system_prompt.format(
161
- agent_name=agent_name,
162
- company_name=company_name,
163
- company_business=company_business,
164
- key_features=key_features
165
- )
 
 
 
 
 
166
 
167
- prompt = ChatPromptTemplate.from_messages([
168
- ("system", formatted_system_prompt),
169
- MessagesPlaceholder(variable_name="chat_history"),
170
- ("human", "{input}"),
171
- MessagesPlaceholder(variable_name="agent_scratchpad")
172
- ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
- tools = [tool]
175
- agent = create_tool_calling_agent(llm, tools, prompt)
176
- agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
 
 
 
 
 
 
 
 
 
177
 
 
 
 
178
 
179
  # --- Streamlit UI ---
180
  def main():
181
- st.title(f"{company_name} AI Sales Assistant 🤖")
182
 
183
- # Initialize session state
184
  if 'user' not in st.session_state:
185
  st.session_state.user = None
186
  st.session_state.chat_history = []
187
-
 
 
 
 
 
 
 
 
 
188
  # Authentication
189
  if not st.session_state.user:
190
  st.header("Login/Register")
191
- tab1, tab2 = st.tabs(["Login", "Register"])
192
 
193
  with tab1:
194
  with st.form("Login"):
@@ -197,7 +159,6 @@ def main():
197
  if st.form_submit_button("Login"):
198
  user = User.get_by_username(username)
199
  if user and check_password_hash(user.password, password):
200
- # If valid, the user is stored in st.session_state.user and their chat history is loaded.
201
  st.session_state.user = user
202
  st.session_state.chat_history = user.chat_history
203
  st.rerun()
@@ -216,49 +177,101 @@ def main():
216
  st.session_state.user = user
217
  st.session_state.chat_history = []
218
  st.rerun()
 
 
 
 
 
 
 
 
 
 
219
 
220
  else:
221
- # Chat Interface
222
- st.header(f"Welcome to {company_name}, {st.session_state.user.username}😊!")
223
- st.subheader("Chat with our AI Sales Assistant")
224
 
225
- # # Display chat history
226
- # for msg in st.session_state.chat_history:
227
- # if msg["type"] == "human":
228
- # with st.chat_message("user"):
229
- # st.write(msg["content"])
230
- # else:
231
- # with st.chat_message("assistant"):
232
- # st.write(msg["content"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
234
- if prompt := st.chat_input("Type you Message here..."):
235
- #Add user message to chat
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  with st.chat_message("user"):
237
- st.write(prompt)
238
 
239
  # Get AI response
240
  with st.chat_message("assistant"):
241
  response = agent_executor.invoke({
242
- "input": prompt,
243
  "chat_history": [HumanMessage(content=msg["content"]) if msg["type"] == "human" else AIMessage(content=msg["content"])
244
  for msg in st.session_state.chat_history]
245
  })["output"]
246
  st.write(response)
247
 
248
- # Check if payment link is provided
249
  if "https://www.example.com/payment" in response:
250
  st.session_state.user.update_products_bought(["Latest Product"])
251
- st.success("Product added to your purchases!")
252
-
253
- # Update chat history in database
254
  new_messages = [
255
- {"type": "human", "content": prompt},
256
  {"type": "ai", "content": response}
257
  ]
258
- # Both the user’s message and the assistant’s reply are appended to the persistent chat history
259
- # (both in session and in the database), ensuring conversation continuity.
260
  st.session_state.user.update_chat_history(new_messages)
261
  st.session_state.chat_history += new_messages
262
 
263
  if __name__ == "__main__":
264
- main()
 
12
  from langchain.agents import AgentExecutor, create_tool_calling_agent
13
  from langchain_core.messages import HumanMessage, AIMessage
14
 
 
15
  # --- Database Setup ---
 
 
16
  @st.cache_resource
17
  def init_db():
18
  conn = sqlite3.connect('users.db', check_same_thread=False)
19
  c = conn.cursor()
20
+
21
+ # Users table
22
  c.execute('''CREATE TABLE IF NOT EXISTS users
23
  (id INTEGER PRIMARY KEY AUTOINCREMENT,
24
  username TEXT UNIQUE NOT NULL,
25
  password TEXT NOT NULL,
26
  previous_chat_history TEXT,
27
  previous_products_bought TEXT)''')
28
+
29
+ # Company settings table
30
+ c.execute('''CREATE TABLE IF NOT EXISTS company_settings
31
+ (id INTEGER PRIMARY KEY AUTOINCREMENT,
32
+ company_name TEXT,
33
+ company_business TEXT,
34
+ agent_name TEXT,
35
+ key_features TEXT)''')
36
+
37
+ # Insert default settings if empty
38
+ c.execute('SELECT COUNT(*) FROM company_settings')
39
+ if c.fetchone()[0] == 0:
40
+ c.execute('''INSERT INTO company_settings
41
+ (company_name, company_business, agent_name, key_features)
42
+ VALUES (?, ?, ?, ?)''',
43
+ ("TechElectronics",
44
+ "Consumer Electronics Retailer",
45
+ "Alex",
46
+ "Cutting-edge technology, Competitive pricing, Excellent customer service"))
47
  conn.commit()
48
  return conn
49
 
50
  conn = init_db()
51
 
 
52
  class User:
53
+ # ... (existing User class remains unchanged) ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  # --- AI Agent Setup ---
 
56
  os.environ["GROQ_API_KEY"] = st.secrets["GROQ_API_KEY"]
57
  llm = ChatGroq(
58
  temperature=0.1,
 
60
  api_key=st.secrets["GROQ_API_KEY"],
61
  )
62
 
 
63
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
64
 
 
65
  @st.cache_resource
66
+ def load_data(data_version):
67
  loader = CSVLoader(file_path="electronics_products.csv")
68
  docs = loader.load()
69
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
 
71
  vectorstore = InMemoryVectorStore.from_documents(documents=splits, embedding=embeddings)
72
  return vectorstore.as_retriever()
73
 
74
+ # Initialize with default data version
75
+ retriever = load_data(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ def get_company_settings():
78
+ conn = sqlite3.connect('users.db')
79
+ c = conn.cursor()
80
+ c.execute('SELECT * FROM company_settings WHERE id=1')
81
+ settings = c.fetchone()
82
+ conn.close()
83
+ return {
84
+ 'company_name': settings[1],
85
+ 'company_business': settings[2],
86
+ 'agent_name': settings[3],
87
+ 'key_features': settings[4]
88
+ }
89
 
90
+ # --- Admin Dashboard ---
91
+ def admin_dashboard():
92
+ st.header("Admin Dashboard")
93
+
94
+ # Company Settings Form
95
+ with st.expander("Company Settings"):
96
+ settings = get_company_settings()
97
+
98
+ with st.form("company_settings"):
99
+ new_name = st.text_input("Company Name", value=settings['company_name'])
100
+ new_business = st.text_input("Business", value=settings['company_business'])
101
+ new_agent = st.text_input("Agent Name", value=settings['agent_name'])
102
+ new_features = st.text_area("Key Features", value=settings['key_features'])
103
+
104
+ if st.form_submit_button("Save Settings"):
105
+ conn = sqlite3.connect('users.db')
106
+ c = conn.cursor()
107
+ c.execute('''UPDATE company_settings SET
108
+ company_name=?, company_business=?, agent_name=?, key_features=?
109
+ WHERE id=1''',
110
+ (new_name, new_business, new_agent, new_features))
111
+ conn.commit()
112
+ conn.close()
113
+ st.success("Settings updated!")
114
 
115
+ # Product Management
116
+ with st.expander("Product Management"):
117
+ st.subheader("Update Product Catalog")
118
+ uploaded_file = st.file_uploader("Upload new CSV", type="csv")
119
+
120
+ if uploaded_file is not None:
121
+ # Save the uploaded file
122
+ with open("electronics_products.csv", "wb") as f:
123
+ f.write(uploaded_file.getbuffer())
124
+ # Update data version to refresh cache
125
+ st.session_state.data_version = st.session_state.get("data_version", 0) + 1
126
+ st.success("Product catalog updated!")
127
 
128
+ if st.button("Back to Main"):
129
+ st.session_state.show_admin = False
130
+ st.rerun()
131
 
132
  # --- Streamlit UI ---
133
  def main():
134
+ st.set_page_config(page_title="AI Sales Assistant", layout="wide")
135
 
136
+ # Initialize session states
137
  if 'user' not in st.session_state:
138
  st.session_state.user = None
139
  st.session_state.chat_history = []
140
+ if 'show_admin' not in st.session_state:
141
+ st.session_state.show_admin = False
142
+ if 'data_version' not in st.session_state:
143
+ st.session_state.data_version = 0
144
+
145
+ # Check admin status first
146
+ if st.session_state.show_admin:
147
+ admin_dashboard()
148
+ return
149
+
150
  # Authentication
151
  if not st.session_state.user:
152
  st.header("Login/Register")
153
+ tab1, tab2, tab3 = st.tabs(["Login", "Register", "Admin"])
154
 
155
  with tab1:
156
  with st.form("Login"):
 
159
  if st.form_submit_button("Login"):
160
  user = User.get_by_username(username)
161
  if user and check_password_hash(user.password, password):
 
162
  st.session_state.user = user
163
  st.session_state.chat_history = user.chat_history
164
  st.rerun()
 
177
  st.session_state.user = user
178
  st.session_state.chat_history = []
179
  st.rerun()
180
+
181
+ with tab3:
182
+ with st.form("Admin Login"):
183
+ admin_key = st.text_input("Admin Key", type="password")
184
+ if st.form_submit_button("Enter Admin Dashboard"):
185
+ if admin_key == st.secrets.get("ADMIN_KEY", "default_admin_key"):
186
+ st.session_state.show_admin = True
187
+ st.rerun()
188
+ else:
189
+ st.error("Invalid Admin Key")
190
 
191
  else:
192
+ # Main Chat Interface
193
+ settings = get_company_settings()
194
+ st.title(f"{settings['company_name']} AI Sales Assistant 🤖")
195
 
196
+ st.header(f"Welcome to {settings['company_name']}, {st.session_state.user.username} 😊!")
197
+
198
+ # Reload data with current version
199
+ global retriever
200
+ retriever = load_data(st.session_state.data_version)
201
+
202
+ # Dynamic system prompt
203
+ system_prompt = f"""
204
+ You are {settings['agent_name']}, the AI Sales Assistant for {settings['company_name']} ({settings['company_business']}).
205
+
206
+ Company Profile:
207
+ - Company Name: {settings['company_name']}
208
+ - Business: {settings['company_business']}
209
+ - Key Features: {settings['key_features']}
210
+
211
+ Product Availability:
212
+ - Only recommend and discuss products listed in the provided document.
213
+ - Do not suggest unavailable or out-of-stock products.
214
+ - Always verify product availability before making recommendations.
215
+
216
+ Conversation Flow:
217
+ 1. Introduction
218
+ 2. Qualification
219
+ 3. Understanding Needs
220
+ 4. Needs Analysis
221
+ 5. Solution Presentation (Only recommend available products)
222
+ 6. Confirmation
223
+ 7. If the prospect agrees to purchase, thank them and provide the payment link: https://www.example.com/payment
224
 
225
+ Guidelines:
226
+ - Maintain natural, professional conversations
227
+ - Follow company policies
228
+ - Be helpful and polite
229
+ - Always cross-check product recommendations with the available inventory in the CSV document
230
+ """
231
+
232
+ # Agent setup with dynamic prompt
233
+ prompt = ChatPromptTemplate.from_messages([
234
+ ("system", system_prompt),
235
+ MessagesPlaceholder(variable_name="chat_history"),
236
+ ("human", "{input}"),
237
+ MessagesPlaceholder(variable_name="agent_scratchpad")
238
+ ])
239
+
240
+ tool = Tool(
241
+ name="retriever",
242
+ func=lambda q: retriever.get_relevant_documents(q),
243
+ description="Useful for retrieving product information"
244
+ )
245
+
246
+ agent = create_tool_calling_agent(llm, [tool], prompt)
247
+ agent_executor = AgentExecutor(agent=agent, tools=[tool], verbose=True)
248
+
249
+ # Chat handling
250
+ if prompt_input := st.chat_input("Type your message here..."):
251
+ # Add user message
252
  with st.chat_message("user"):
253
+ st.write(prompt_input)
254
 
255
  # Get AI response
256
  with st.chat_message("assistant"):
257
  response = agent_executor.invoke({
258
+ "input": prompt_input,
259
  "chat_history": [HumanMessage(content=msg["content"]) if msg["type"] == "human" else AIMessage(content=msg["content"])
260
  for msg in st.session_state.chat_history]
261
  })["output"]
262
  st.write(response)
263
 
 
264
  if "https://www.example.com/payment" in response:
265
  st.session_state.user.update_products_bought(["Latest Product"])
266
+ st.success("Product added to your purchases!")
267
+
268
+ # Update chat history
269
  new_messages = [
270
+ {"type": "human", "content": prompt_input},
271
  {"type": "ai", "content": response}
272
  ]
 
 
273
  st.session_state.user.update_chat_history(new_messages)
274
  st.session_state.chat_history += new_messages
275
 
276
  if __name__ == "__main__":
277
+ main()