Alibrown commited on
Commit
a43dae1
·
verified ·
1 Parent(s): a7f595a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -62
app.py CHANGED
@@ -1,37 +1,62 @@
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import os
3
  import json
4
  import datetime
5
  import openai
 
 
6
  from datasets import load_dataset, Dataset, concatenate_datasets
7
- from huggingface_hub import login
8
 
9
- # -- Einstellungen für Hugging Face Dataset Repository --
10
- # Ersetze "your_username/customer_memory" durch deinen eigenen Repository-Namen!
11
- DATASET_REPO = "AiCodeCarft/customer_memory"
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- # Hugging Face Login
14
- hf_token = st.sidebar.text_input("Enter your Hugging Face Token", type="password")
15
- if hf_token:
16
- login(token=hf_token)
17
- st.sidebar.success("Logged in to Hugging Face!")
18
 
19
- # Hilfsfunktion: Versuche, das Dataset vom HF Hub zu laden; falls nicht vorhanden, initialisiere es
20
  def load_memory_dataset():
 
 
 
 
 
21
  try:
22
  ds = load_dataset(DATASET_REPO, split="train")
23
  st.write("Dataset loaded from HF Hub.")
 
24
  except Exception as e:
25
  st.write("Dataset not found on HF Hub. Creating a new one...")
26
- # Leeres Dataset mit den Spalten: user_id, query, response
27
  data = {"user_id": [], "query": [], "response": []}
28
  ds = Dataset.from_dict(data)
29
  ds.push_to_hub(DATASET_REPO)
30
  st.write("New dataset created and pushed to HF Hub.")
 
31
  return ds
32
 
33
- # Hilfsfunktion: Füge einen neuen Eintrag (Memory) hinzu und pushe das aktualisierte Dataset
34
  def add_to_memory(user_id, query, response):
 
 
 
 
35
  ds = load_memory_dataset()
36
  # Neuer Eintrag als kleines Dataset
37
  new_entry = Dataset.from_dict({
@@ -41,71 +66,162 @@ def add_to_memory(user_id, query, response):
41
  })
42
  # Bestehendes Dataset mit dem neuen Eintrag zusammenführen
43
  updated_ds = concatenate_datasets([ds, new_entry])
44
- # Aktualisiere das Dataset auf HF Hub
45
  updated_ds.push_to_hub(DATASET_REPO)
46
  st.write("Memory updated.")
 
47
 
48
- # Hilfsfunktion: Filtere das Dataset nach einer bestimmten customer_id
49
  def get_memory(user_id):
 
 
 
 
50
  ds = load_memory_dataset()
51
- return ds.filter(lambda x: x["user_id"] == user_id)
 
 
52
 
53
- # OpenAI GPT-4 API-Anbindung
54
  def generate_response(prompt):
 
 
 
55
  response = openai.ChatCompletion.create(
56
- model="gpt-4",
57
  messages=[
58
  {"role": "system", "content": "You are a customer support AI for TechGadgets.com."},
59
  {"role": "user", "content": prompt}
60
  ]
61
  )
 
62
  return response.choices[0].message.content
63
 
64
- # Streamlit App UI
65
  st.title("AI Customer Support Agent with Memory 🛒")
66
  st.caption("Chat with a customer support assistant who remembers your past interactions.")
67
 
68
- # OpenAI API Key Eingabe
69
  openai_api_key = st.text_input("Enter OpenAI API Key", type="password")
70
  if openai_api_key:
71
- os.environ["OPENAI_API_KEY"] = openai_api_key
72
  openai.api_key = openai_api_key
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- # Sidebar: Customer ID und Optionen
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  st.sidebar.title("Enter your Customer ID:")
76
- customer_id = st.sidebar.text_input("Customer ID")
77
-
78
- # Optional: Synthetic Data generieren (Beispiel-Daten)
 
 
 
 
 
 
 
79
  if st.sidebar.button("Generate Synthetic Data"):
80
  if customer_id:
81
- synthetic_data = {
82
- "name": "Max Mustermann",
83
- "recent_order": {
84
- "product": "High-end Smartphone",
85
- "order_date": (datetime.datetime.now() - datetime.timedelta(days=10)).strftime("%B %d, %Y"),
86
- "delivery_date": (datetime.datetime.now() + datetime.timedelta(days=2)).strftime("%B %d, %Y"),
87
- "order_number": "ORD123456"
88
- },
89
- "previous_orders": [
90
- {"product": "Laptop", "order_date": "January 12, 2025"},
91
- {"product": "Tablet", "order_date": "March 01, 2025"}
92
- ],
93
- "customer_service_interactions": [
94
- "Asked about order status",
95
- "Inquired about warranty"
96
- ]
97
- }
98
- st.session_state.customer_data = synthetic_data
99
- st.sidebar.success("Synthetic data generated!")
100
  else:
101
  st.sidebar.error("Please enter a customer ID first.")
 
102
 
 
103
  if st.sidebar.button("View Customer Profile"):
104
- if "customer_data" in st.session_state and st.session_state.customer_data:
105
  st.sidebar.json(st.session_state.customer_data)
106
  else:
107
- st.sidebar.info("No synthetic data available.")
108
 
 
109
  if st.sidebar.button("View Memory Info"):
110
  if customer_id:
111
  memories = get_memory(customer_id)
@@ -115,33 +231,36 @@ if openai_api_key:
115
  else:
116
  st.sidebar.error("Please enter a customer ID.")
117
 
118
- # Initialisiere Chatverlauf in session_state
119
  if "messages" not in st.session_state:
120
  st.session_state.messages = []
121
 
122
- # Zeige bisherigen Chatverlauf
123
  for message in st.session_state.messages:
124
- st.chat_message(message["role"]).markdown(message["content"])
 
125
 
126
- # Haupt-Chat: Benutzer-Eingabe
127
  query = st.chat_input("How can I assist you today?")
128
  if query and customer_id:
129
- # Hole bisherigen Memory-Context
130
- memories = get_memory(customer_id)
131
- context = ""
132
- for mem in memories:
133
- context += f"Query: {mem['query']}\nResponse: {mem['response']}\n"
134
- # Kombiniere Kontext mit aktueller Anfrage
135
- full_prompt = context + f"\nCustomer: {query}\nSupport Agent:"
136
- with st.spinner("Generating response..."):
137
- answer = generate_response(full_prompt)
138
- # Aktualisiere den Chatverlauf
139
  st.session_state.messages.append({"role": "user", "content": query})
 
 
 
 
 
 
 
140
  st.session_state.messages.append({"role": "assistant", "content": answer})
141
- st.chat_message("assistant").markdown(answer)
142
- # Speicher die Interaktion in der Memory (Dataset)
143
- add_to_memory(customer_id, query, answer)
 
144
  elif query and not customer_id:
145
  st.error("Please enter a customer ID to start the chat.")
 
 
146
  else:
147
  st.warning("Please enter your OpenAI API key to use the customer support agent.")
 
 
1
+ # =============================================================================
2
+ # DON'T STEAL THE FREE CODE OF DEVS! Use it for free an do not touch credits!
3
+ # If you steal this code, in the future you will pay for apps like this!
4
+ # A bit of respect goes a long way – all rights reserved under German law.
5
+ # Copyright Volkan Kücükbudak https://github.com/volkansah
6
+ # Repo URL: https://github.com/AiCodeCraft
7
+ # =============================================================================
8
  import streamlit as st
9
  import os
10
  import json
11
  import datetime
12
  import openai
13
+ from datetime import timedelta
14
+ import logging
15
  from datasets import load_dataset, Dataset, concatenate_datasets
 
16
 
17
+ # ------------------ Logging konfigurieren ------------------
18
+ logging.basicConfig(
19
+ level=logging.INFO, # Log-Level auf INFO setzen
20
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
21
+ )
22
+ logger = logging.getLogger(__name__)
23
+ logger.info("Starte App mit HF-Dataset Memory...")
24
+
25
+ # ------------------ Hugging Face Token laden ------------------
26
+ HF_TOKEN_MEMORY = os.getenv('HF_TOKEN_MEMORY', '').strip()
27
+ if HF_TOKEN_MEMORY:
28
+ logger.info("Hugging Face Token gefunden.")
29
+ else:
30
+ logger.warning("Kein Hugging Face Token gefunden. Falls benötigt, bitte setzen!")
31
 
32
+ # ------------------ Einstellungen für das Memory-Dataset ------------------
33
+ DATASET_REPO = "AiCodeCarft/customer_memory"
 
 
 
34
 
 
35
  def load_memory_dataset():
36
+ """
37
+ Versucht, das Memory-Dataset vom HF Hub zu laden.
38
+ Falls nicht vorhanden, wird ein leeres Dataset mit den Spalten
39
+ 'user_id', 'query' und 'response' erstellt und gepusht.
40
+ """
41
  try:
42
  ds = load_dataset(DATASET_REPO, split="train")
43
  st.write("Dataset loaded from HF Hub.")
44
+ logger.info("Dataset erfolgreich vom HF Hub geladen.")
45
  except Exception as e:
46
  st.write("Dataset not found on HF Hub. Creating a new one...")
47
+ logger.info("Kein Dataset gefunden. Erstelle ein neues Dataset...")
48
  data = {"user_id": [], "query": [], "response": []}
49
  ds = Dataset.from_dict(data)
50
  ds.push_to_hub(DATASET_REPO)
51
  st.write("New dataset created and pushed to HF Hub.")
52
+ logger.info("Neues Dataset erfolgreich erstellt und gepusht.")
53
  return ds
54
 
 
55
  def add_to_memory(user_id, query, response):
56
+ """
57
+ Fügt einen neuen Eintrag (Query und Antwort) zum Memory-Dataset hinzu
58
+ und pusht das aktualisierte Dataset an den HF Hub.
59
+ """
60
  ds = load_memory_dataset()
61
  # Neuer Eintrag als kleines Dataset
62
  new_entry = Dataset.from_dict({
 
66
  })
67
  # Bestehendes Dataset mit dem neuen Eintrag zusammenführen
68
  updated_ds = concatenate_datasets([ds, new_entry])
69
+ # Push updated dataset to HF Hub
70
  updated_ds.push_to_hub(DATASET_REPO)
71
  st.write("Memory updated.")
72
+ logger.info("Memory-Dataset erfolgreich aktualisiert.")
73
 
 
74
  def get_memory(user_id):
75
+ """
76
+ Filtert das Memory-Dataset nach der angegebenen Customer ID
77
+ und gibt alle Einträge (Query und Antwort) zurück.
78
+ """
79
  ds = load_memory_dataset()
80
+ filtered_ds = ds.filter(lambda x: x["user_id"] == user_id)
81
+ logger.info(f"Memory für User {user_id} abgerufen. {len(filtered_ds)} Einträge gefunden.")
82
+ return filtered_ds
83
 
84
+ # ------------------ OpenAI GPT-4 API-Anbindung ------------------
85
  def generate_response(prompt):
86
+ """
87
+ Sendet den Prompt an die OpenAI API und gibt die Antwort zurück.
88
+ """
89
  response = openai.ChatCompletion.create(
90
+ model="gpt-3.5-turbo",
91
  messages=[
92
  {"role": "system", "content": "You are a customer support AI for TechGadgets.com."},
93
  {"role": "user", "content": prompt}
94
  ]
95
  )
96
+ logger.info("Antwort von OpenAI erhalten.")
97
  return response.choices[0].message.content
98
 
99
+ # ------------------ Streamlit App UI ------------------
100
  st.title("AI Customer Support Agent with Memory 🛒")
101
  st.caption("Chat with a customer support assistant who remembers your past interactions.")
102
 
103
+ # Eingabe des OpenAI API Keys
104
  openai_api_key = st.text_input("Enter OpenAI API Key", type="password")
105
  if openai_api_key:
106
+ os.environ['OPENAI_API_KEY'] = openai_api_key
107
  openai.api_key = openai_api_key
108
+ logger.info("OpenAI API Key gesetzt.")
109
+
110
+ # ------------------ Klasse: CustomerSupportAIAgent ------------------
111
+ class CustomerSupportAIAgent:
112
+ def __init__(self):
113
+ # Wir nutzen hier die HF Dataset Funktionen als Memory-Speicher
114
+ self.client = openai # OpenAI Client
115
+ self.app_id = "customer-support"
116
+
117
+ def handle_query(self, query, user_id=None):
118
+ try:
119
+ # Hole relevante Erinnerungen aus dem HF Dataset
120
+ memories = get_memory(user_id)
121
+ context = "Relevant past information:\n"
122
+ # Falls Einträge vorhanden sind, baue den Kontext
123
+ if len(memories) > 0:
124
+ for entry in memories:
125
+ context += f"- Query: {entry['query']}\n Response: {entry['response']}\n"
126
+ logger.info("Kontext aus Memory-Dataset erstellt.")
127
+
128
+ # Kombiniere Kontext und aktuelle Anfrage
129
+ full_prompt = f"{context}\nCustomer: {query}\nSupport Agent:"
130
+ logger.info("Vollständiger Prompt für OpenAI erstellt.")
131
+
132
+ # Generiere Antwort mit OpenAI
133
+ answer = generate_response(full_prompt)
134
+
135
+ # Speicher die Interaktion im Memory-Dataset
136
+ add_to_memory(user_id, query, answer)
137
+ logger.info("Interaktion im Memory-Dataset gespeichert.")
138
+
139
+ return answer
140
+ except Exception as e:
141
+ logger.error(f"Fehler bei handle_query: {e}")
142
+ st.error(f"An error occurred while handling the query: {e}")
143
+ return "Sorry, I encountered an error. Please try again later."
144
+
145
+ def generate_synthetic_data(self, user_id: str) -> dict | None:
146
+ try:
147
+ today = datetime.datetime.now()
148
+ order_date = (today - timedelta(days=10)).strftime("%B %d, %Y")
149
+ expected_delivery = (today + timedelta(days=2)).strftime("%B %d, %Y")
150
+
151
+ # Prompt zur Generierung synthetischer Kundendaten für einen Lieferservice
152
+ prompt = f"""Generate a detailed customer profile and order history for a DeliverItExpress customer with ID {user_id}. Include:
153
+ 1. Customer name and basic info (age, gender, and contact details)
154
+ 2. A recent order of a gourmet meal (placed on {order_date} and delivered by {expected_delivery})
155
+ 3. Order details including food items, total price, and order number
156
+ 4. Customer's delivery address
157
+ 5. 2-3 previous orders from the past year with different types of cuisines
158
+ 6. 2-3 customer service interactions regarding delivery issues (e.g., late delivery, missing items)
159
+ 7. Any preferences or patterns in their ordering behavior (e.g., favorite cuisines, peak ordering times)
160
 
161
+ Format the output as a JSON object."""
162
+ logger.info("Prompt for generating synthetic delivery service data created.")
163
+
164
+ response = self.client.ChatCompletion.create(
165
+ model="gpt-4",
166
+ messages=[
167
+ {"role": "system", "content": "You are a data generation AI that creates realistic customer profiles and order histories. Always respond with valid JSON."},
168
+ {"role": "user", "content": prompt}
169
+ ]
170
+ )
171
+ logger.info("Antwort für synthetische Daten von OpenAI erhalten.")
172
+ customer_data = json.loads(response.choices[0].message.content)
173
+
174
+ # Optional: Speichere auch diese Daten im Memory-Dataset
175
+ for key, value in customer_data.items():
176
+ if isinstance(value, list):
177
+ for item in value:
178
+ add_to_memory(user_id, f"{key} item", json.dumps(item))
179
+ else:
180
+ add_to_memory(user_id, key, json.dumps(value))
181
+ logger.info("Synthetische Daten im Memory-Dataset gespeichert.")
182
+ return customer_data
183
+ except Exception as e:
184
+ logger.error(f"Fehler bei generate_synthetic_data: {e}")
185
+ st.error(f"Failed to generate synthetic data: {e}")
186
+ return None
187
+
188
+ # ------------------ Initialisierung des CustomerSupportAIAgent ------------------
189
+ support_agent = CustomerSupportAIAgent()
190
+
191
+ # ------------------ Sidebar: Customer ID und Optionen ------------------
192
  st.sidebar.title("Enter your Customer ID:")
193
+ previous_customer_id = st.session_state.get("previous_customer_id", None)
194
+ customer_id = st.sidebar.text_input("Enter your Customer ID")
195
+
196
+ if customer_id != previous_customer_id:
197
+ st.session_state.messages = []
198
+ st.session_state.previous_customer_id = customer_id
199
+ st.session_state.customer_data = None
200
+ logger.info("Neue Customer ID erkannt – Chatverlauf und synthetische Daten zurückgesetzt.")
201
+
202
+ # Button: Synthetische Daten generieren
203
  if st.sidebar.button("Generate Synthetic Data"):
204
  if customer_id:
205
+ with st.spinner("Generating customer data..."):
206
+ st.session_state.customer_data = support_agent.generate_synthetic_data(customer_id)
207
+ if st.session_state.customer_data:
208
+ st.sidebar.success("Synthetic data generated successfully!")
209
+ logger.info("Synthetische Daten erfolgreich generiert.")
210
+ else:
211
+ st.sidebar.error("Failed to generate synthetic data.")
212
+ logger.error("Fehler beim Generieren synthetischer Daten.")
 
 
 
 
 
 
 
 
 
 
 
213
  else:
214
  st.sidebar.error("Please enter a customer ID first.")
215
+ logger.warning("Kein Customer ID eingegeben beim Versuch, synthetische Daten zu generieren.")
216
 
217
+ # Button: Customer Profile anzeigen
218
  if st.sidebar.button("View Customer Profile"):
219
+ if st.session_state.customer_data:
220
  st.sidebar.json(st.session_state.customer_data)
221
  else:
222
+ st.sidebar.info("No customer data generated yet. Click 'Generate Synthetic Data' first.")
223
 
224
+ # Button: Memory-Info anzeigen
225
  if st.sidebar.button("View Memory Info"):
226
  if customer_id:
227
  memories = get_memory(customer_id)
 
231
  else:
232
  st.sidebar.error("Please enter a customer ID.")
233
 
234
+ # ------------------ Chatverlauf initialisieren und anzeigen ------------------
235
  if "messages" not in st.session_state:
236
  st.session_state.messages = []
237
 
238
+ # Vorherige Nachrichten anzeigen
239
  for message in st.session_state.messages:
240
+ with st.chat_message(message["role"]):
241
+ st.markdown(message["content"])
242
 
243
+ # ------------------ Haupt-Chat: Benutzereingabe ------------------
244
  query = st.chat_input("How can I assist you today?")
245
  if query and customer_id:
246
+ # Benutzeranfrage zum Chatverlauf hinzufügen
 
 
 
 
 
 
 
 
 
247
  st.session_state.messages.append({"role": "user", "content": query})
248
+ with st.chat_message("user"):
249
+ st.markdown(query)
250
+ logger.info("Benutzeranfrage hinzugefügt.")
251
+
252
+ # Generiere Antwort und zeige sie an
253
+ with st.spinner("Generating response..."):
254
+ answer = support_agent.handle_query(query, user_id=customer_id)
255
  st.session_state.messages.append({"role": "assistant", "content": answer})
256
+ with st.chat_message("assistant"):
257
+ st.markdown(answer)
258
+ logger.info("Antwort des Assistenten hinzugefügt.")
259
+
260
  elif query and not customer_id:
261
  st.error("Please enter a customer ID to start the chat.")
262
+ logger.warning("Chat gestartet ohne Customer ID.")
263
+
264
  else:
265
  st.warning("Please enter your OpenAI API key to use the customer support agent.")
266
+ logger.info("Warte auf Eingabe des OpenAI API Keys.")