Aniq-63 commited on
Commit
1cf3841
·
verified ·
1 Parent(s): 1543adc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -203
app.py CHANGED
@@ -1,10 +1,10 @@
1
  import os
2
  import sqlite3
3
  import streamlit as st
4
- from datetime import datetime
5
  from werkzeug.security import generate_password_hash, check_password_hash
6
  from langchain_groq import ChatGroq
7
  from langchain_huggingface import HuggingFaceEmbeddings
 
8
  from langchain_text_splitters import RecursiveCharacterTextSplitter
9
  from langchain_core.vectorstores import InMemoryVectorStore
10
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
@@ -12,119 +12,81 @@ 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
  # --- Database Setup ---
 
 
16
  @st.cache_resource
17
  def init_db():
18
- conn = sqlite3.connect('app.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
- is_admin BOOLEAN DEFAULT 0,
27
  previous_chat_history TEXT,
28
  previous_products_bought TEXT)''')
29
-
30
- # Products Table
31
- c.execute('''CREATE TABLE IF NOT EXISTS products
32
- (id INTEGER PRIMARY KEY AUTOINCREMENT,
33
- name TEXT NOT NULL,
34
- description TEXT,
35
- price REAL,
36
- stock INTEGER,
37
- features TEXT,
38
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
39
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
40
-
41
  conn.commit()
42
  return conn
43
 
44
  conn = init_db()
45
 
46
- # --- Data Models ---
47
  class User:
48
- def __init__(self, id, username, password, is_admin=False, chat_history=None, products_bought=None):
49
  self.id = id
50
  self.username = username
51
  self.password = password
52
- self.is_admin = is_admin
53
  self.chat_history = chat_history or []
54
  self.products_bought = products_bought or []
55
 
 
56
  @classmethod
57
- def create(cls, username, password, is_admin=False):
58
  hashed_pw = generate_password_hash(password)
 
59
  c = conn.cursor()
60
- try:
61
- c.execute('INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)',
62
- (username, hashed_pw, int(is_admin)))
63
- conn.commit()
64
- return cls(c.lastrowid, username, hashed_pw, is_admin)
65
- except sqlite3.IntegrityError:
66
- raise ValueError("Username already exists")
67
 
 
68
  @classmethod
69
  def get_by_username(cls, username):
 
70
  c = conn.cursor()
71
  c.execute('SELECT * FROM users WHERE username = ?', (username,))
72
  user = c.fetchone()
 
73
  if user:
74
- return cls(user[0], user[1], user[2], bool(user[3]),
75
- eval(user[4]) if user[4] else [],
76
- eval(user[5]) if user[5] else [])
77
  return None
78
 
79
  def update_chat_history(self, new_messages):
 
80
  c = conn.cursor()
81
  updated_history = self.chat_history + new_messages
82
  c.execute('UPDATE users SET previous_chat_history = ? WHERE id = ?',
83
  (str(updated_history), self.id))
84
  conn.commit()
 
85
 
86
  def update_products_bought(self, new_products):
 
87
  c = conn.cursor()
88
  updated_products = self.products_bought + new_products
89
  c.execute('UPDATE users SET previous_products_bought = ? WHERE id = ?',
90
  (str(updated_products), self.id))
91
  conn.commit()
92
-
93
- class ProductManager:
94
- @staticmethod
95
- @st.cache_data(ttl=60, show_spinner=False)
96
- def get_all_products():
97
- c = conn.cursor()
98
- c.execute('SELECT * FROM products')
99
- return c.fetchall()
100
-
101
- @staticmethod
102
- def add_product(name, description, price, stock, features):
103
- c = conn.cursor()
104
- c.execute('''INSERT INTO products
105
- (name, description, price, stock, features)
106
- VALUES (?, ?, ?, ?, ?)''',
107
- (name, description, price, stock, str(features)))
108
- conn.commit()
109
- st.cache_data.clear()
110
-
111
- @staticmethod
112
- def update_product(product_id, **kwargs):
113
- c = conn.cursor()
114
- set_clause = ', '.join([f"{k} = ?" for k in kwargs])
115
- values = list(kwargs.values()) + [product_id]
116
- c.execute(f'UPDATE products SET {set_clause}, updated_at = CURRENT_TIMESTAMP WHERE id = ?', values)
117
- conn.commit()
118
- st.cache_data.clear()
119
-
120
- @staticmethod
121
- def delete_product(product_id):
122
- c = conn.cursor()
123
- c.execute('DELETE FROM products WHERE id = ?', (product_id,))
124
- conn.commit()
125
- st.cache_data.clear()
126
 
127
  # --- AI Agent Setup ---
 
128
  os.environ["GROQ_API_KEY"] = st.secrets["GROQ_API_KEY"]
129
  llm = ChatGroq(
130
  temperature=0.1,
@@ -132,148 +94,89 @@ llm = ChatGroq(
132
  api_key=st.secrets["GROQ_API_KEY"],
133
  )
134
 
 
135
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
136
 
137
- @st.cache_resource(show_spinner=False)
138
- def load_product_data():
 
 
 
139
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
140
- products = ProductManager.get_all_products()
141
-
142
- # Convert products to document format
143
- docs = [f"Name: {p[1]}\nDescription: {p[2]}\nPrice: ${p[3]}\nStock: {p[4]}\nFeatures: {p[5]}"
144
- for p in products]
145
-
146
  splits = text_splitter.split_documents(docs)
147
  vectorstore = InMemoryVectorStore.from_documents(documents=splits, embedding=embeddings)
148
  return vectorstore.as_retriever()
149
 
150
- retriever = load_product_data()
151
 
152
  def retrieve_query(query: str):
 
153
  return retriever.get_relevant_documents(query)
154
 
155
  tool = Tool(
156
- name="product_retriever",
157
  func=retrieve_query,
158
- description="Access real-time product information including pricing, availability, and features"
159
  )
160
 
161
- # Agent Configuration
 
162
  system_prompt = """
163
- You are {agent_name}, the AI Sales Assistant for {company_name} ({company_business}).
164
-
165
- Real-Time Product Updates:
166
- - Current Inventory: {product_count} items
167
- - Last Updated: {last_updated}
168
-
169
- Guidelines:
170
- 1. Always verify product availability before suggesting
171
- 2. Mention price changes immediately
172
- 3. Update recommendations based on stock levels
173
- 4. Alert users about restocked items
174
 
175
- Conversation Flow:
176
- 1. Introduction
177
- 2. Qualification
178
- 3. Understanding Needs
179
- 4. Needs Analysis
180
- 5. Solution Presentation
181
- 6. Confirmation
182
- 7. If the prospect agrees to purchase, thank them and provide the payment link: https://www.example.com/payment
183
 
184
- Guidelines:
185
- - Maintain natural, professional conversations
186
- - Follow company policies
187
- - Be helpful and polite
188
- """
 
 
 
189
 
 
 
 
 
 
 
190
  company_name = "TechElectronics"
191
  company_business = "Consumer Electronics Retailer"
192
  agent_name = "Alex"
 
193
 
194
- def get_agent_prompt():
195
- products = ProductManager.get_all_products()
196
- return system_prompt.format(
197
- agent_name=agent_name,
198
- company_name=company_name,
199
- company_business=company_business,
200
- product_count=len(products),
201
- last_updated=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
202
- )
203
 
204
  prompt = ChatPromptTemplate.from_messages([
205
- ("system", get_agent_prompt()),
206
  MessagesPlaceholder(variable_name="chat_history"),
207
  ("human", "{input}"),
208
  MessagesPlaceholder(variable_name="agent_scratchpad")
209
  ])
210
 
211
- agent = create_tool_calling_agent(llm, [tool], prompt)
212
- agent_executor = AgentExecutor(agent=agent, tools=[tool], verbose=True)
 
213
 
214
- # --- Streamlit UI ---
215
- def admin_dashboard():
216
- st.header("Product Management Dashboard")
217
-
218
- tab1, tab2, tab3 = st.tabs(["Add Product", "Edit Product", "Inventory"])
219
-
220
- with tab1:
221
- with st.form("Add Product"):
222
- name = st.text_input("Product Name")
223
- desc = st.text_area("Description")
224
- price = st.number_input("Price", min_value=0.0)
225
- stock = st.number_input("Stock", min_value=0)
226
- features = st.text_area("Features (comma-separated)")
227
- if st.form_submit_button("Add Product"):
228
- ProductManager.add_product(name, desc, price, stock, features)
229
- st.success("Product added successfully!")
230
-
231
- with tab2:
232
- products = ProductManager.get_all_products()
233
- selected = st.selectbox("Select Product", products, format_func=lambda x: x[1])
234
- if selected:
235
- with st.form("Edit Product"):
236
- new_name = st.text_input("Name", value=selected[1])
237
- new_desc = st.text_area("Description", value=selected[2])
238
- new_price = st.number_input("Price", value=selected[3])
239
- new_stock = st.number_input("Stock", value=selected[4])
240
- new_features = st.text_area("Features", value=selected[5])
241
- if st.form_submit_button("Update"):
242
- ProductManager.update_product(selected[0],
243
- name=new_name,
244
- description=new_desc,
245
- price=new_price,
246
- stock=new_stock,
247
- features=new_features
248
- )
249
- st.success("Product updated!")
250
-
251
- with tab3:
252
- st.dataframe(
253
- data=ProductManager.get_all_products(),
254
- column_config={
255
- "0": "ID",
256
- "1": "Name",
257
- "2": "Description",
258
- "3": "Price",
259
- "4": "Stock",
260
- "5": "Features",
261
- "6": "Created",
262
- "7": "Updated"
263
- },
264
- use_container_width=True
265
- )
266
-
267
 
 
268
  def main():
269
  st.title(f"{company_name} AI Sales Assistant 🤖")
270
 
 
271
  if 'user' not in st.session_state:
272
- st.session_state.update({
273
- 'user': None,
274
- 'chat_history': [],
275
- 'product_update_flag': False
276
- })
277
 
278
  # Authentication
279
  if not st.session_state.user:
@@ -287,66 +190,68 @@ def main():
287
  if st.form_submit_button("Login"):
288
  user = User.get_by_username(username)
289
  if user and check_password_hash(user.password, password):
 
290
  st.session_state.user = user
291
  st.session_state.chat_history = user.chat_history
292
  st.rerun()
 
 
293
 
294
  with tab2:
295
  with st.form("Register"):
296
  new_user = st.text_input("New Username")
297
  new_pass = st.text_input("New Password", type="password")
298
  if st.form_submit_button("Register"):
299
- try:
 
 
300
  user = User.create(new_user, new_pass)
301
  st.session_state.user = user
 
302
  st.rerun()
303
- except ValueError as e:
304
- st.error(str(e))
305
-
306
  else:
307
- if st.session_state.user.is_admin:
308
- admin_dashboard()
309
- st.divider()
310
-
311
  # Chat Interface
312
- st.header(f"Welcome {st.session_state.user.username}{' 👑' if st.session_state.user.is_admin else ''}")
 
313
 
314
- # Chat History
315
- for msg in st.session_state.chat_history:
316
- avatar = "🤖" if msg["type"] == "ai" else None
317
- with st.chat_message(msg["type"], avatar=avatar):
318
- st.write(msg["content"])
319
-
320
- # Input Handling
321
- if prompt := st.chat_input("How can I help you today?"):
322
- # User Message
 
 
323
  with st.chat_message("user"):
324
  st.write(prompt)
325
-
326
- # AI Response
327
- with st.chat_message("assistant", avatar="🤖"):
328
  response = agent_executor.invoke({
329
  "input": prompt,
330
- "chat_history": [
331
- HumanMessage(content=msg["content"]) if msg["type"] == "human"
332
- else AIMessage(content=msg["content"])
333
- for msg in st.session_state.chat_history
334
- ]
335
  })["output"]
336
-
337
  st.write(response)
 
 
338
  if "https://www.example.com/payment" in response:
339
  st.session_state.user.update_products_bought(["Latest Product"])
340
- st.success("Purchase recorded!")
341
-
342
- # Update History
343
  new_messages = [
344
  {"type": "human", "content": prompt},
345
  {"type": "ai", "content": response}
346
  ]
 
 
347
  st.session_state.user.update_chat_history(new_messages)
348
  st.session_state.chat_history += new_messages
349
 
350
  if __name__ == "__main__":
351
- # admin_dashboard()
352
- main()
 
1
  import os
2
  import sqlite3
3
  import streamlit as st
 
4
  from werkzeug.security import generate_password_hash, check_password_hash
5
  from langchain_groq import ChatGroq
6
  from langchain_huggingface import HuggingFaceEmbeddings
7
+ from langchain_community.document_loaders.csv_loader import CSVLoader
8
  from langchain_text_splitters import RecursiveCharacterTextSplitter
9
  from langchain_core.vectorstores import InMemoryVectorStore
10
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
 
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
  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)
 
 
 
 
 
 
106
  splits = text_splitter.split_documents(docs)
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
+ Conversation Flow:
133
+ 1. Introduction
134
+ 2. Qualification
135
+ 3. Understanding Needs
136
+ 4. Needs Analysis
137
+ 5. Solution Presentation
138
+ 6. Confirmation
139
+ 7. If the prospect agrees to purchase, thank them and provide the payment link: https://www.example.com/payment
140
 
141
+ Guidelines:
142
+ - Maintain natural, professional conversations
143
+ - Follow company policies
144
+ - Be helpful and polite
145
+ """
146
+ # Define the company and agent details
147
  company_name = "TechElectronics"
148
  company_business = "Consumer Electronics Retailer"
149
  agent_name = "Alex"
150
+ key_features = "Cutting-edge technology, Competitive pricing, Excellent customer service"
151
 
152
+ # Format the system prompt with the company and agent details
153
+ formatted_system_prompt = system_prompt.format(
154
+ agent_name=agent_name,
155
+ company_name=company_name,
156
+ company_business=company_business,
157
+ key_features=key_features
158
+ )
 
 
159
 
160
  prompt = ChatPromptTemplate.from_messages([
161
+ ("system", formatted_system_prompt),
162
  MessagesPlaceholder(variable_name="chat_history"),
163
  ("human", "{input}"),
164
  MessagesPlaceholder(variable_name="agent_scratchpad")
165
  ])
166
 
167
+ tools = [tool]
168
+ agent = create_tool_calling_agent(llm, tools, prompt)
169
+ agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ # --- Streamlit UI ---
173
  def main():
174
  st.title(f"{company_name} AI Sales Assistant 🤖")
175
 
176
+ # Initialize session state
177
  if 'user' not in st.session_state:
178
+ st.session_state.user = None
179
+ st.session_state.chat_history = []
 
 
 
180
 
181
  # Authentication
182
  if not st.session_state.user:
 
190
  if st.form_submit_button("Login"):
191
  user = User.get_by_username(username)
192
  if user and check_password_hash(user.password, password):
193
+ # If valid, the user is stored in st.session_state.user and their chat history is loaded.
194
  st.session_state.user = user
195
  st.session_state.chat_history = user.chat_history
196
  st.rerun()
197
+ else:
198
+ st.error("Invalid credentials")
199
 
200
  with tab2:
201
  with st.form("Register"):
202
  new_user = st.text_input("New Username")
203
  new_pass = st.text_input("New Password", type="password")
204
  if st.form_submit_button("Register"):
205
+ if User.get_by_username(new_user):
206
+ st.error("Username already exists")
207
+ else:
208
  user = User.create(new_user, new_pass)
209
  st.session_state.user = user
210
+ st.session_state.chat_history = []
211
  st.rerun()
212
+
 
 
213
  else:
 
 
 
 
214
  # Chat Interface
215
+ st.header(f"Welcome to {company_name}, {st.session_state.user.username}😊!")
216
+ st.subheader("Chat with our AI Sales Assistant")
217
 
218
+ # # Display chat history
219
+ # for msg in st.session_state.chat_history:
220
+ # if msg["type"] == "human":
221
+ # with st.chat_message("user"):
222
+ # st.write(msg["content"])
223
+ # else:
224
+ # with st.chat_message("assistant"):
225
+ # st.write(msg["content"])
226
+
227
+ if prompt := st.chat_input("Type you Message here..."):
228
+ #Add user message to chat
229
  with st.chat_message("user"):
230
  st.write(prompt)
231
+
232
+ # Get AI response
233
+ with st.chat_message("assistant"):
234
  response = agent_executor.invoke({
235
  "input": prompt,
236
+ "chat_history": [HumanMessage(content=msg["content"]) if msg["type"] == "human" else AIMessage(content=msg["content"])
237
+ for msg in st.session_state.chat_history]
 
 
 
238
  })["output"]
 
239
  st.write(response)
240
+
241
+ # Check if payment link is provided
242
  if "https://www.example.com/payment" in response:
243
  st.session_state.user.update_products_bought(["Latest Product"])
244
+ st.success("Product added to your purchases!")
245
+
246
+ # Update chat history in database
247
  new_messages = [
248
  {"type": "human", "content": prompt},
249
  {"type": "ai", "content": response}
250
  ]
251
+ # Both the user’s message and the assistant’s reply are appended to the persistent chat history
252
+ # (both in session and in the database), ensuring conversation continuity.
253
  st.session_state.user.update_chat_history(new_messages)
254
  st.session_state.chat_history += new_messages
255
 
256
  if __name__ == "__main__":
257
+ main()