k96beni commited on
Commit
bf9300f
·
verified ·
1 Parent(s): 9279dd3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -19
app.py CHANGED
@@ -12,9 +12,14 @@ import uuid
12
  from user_agents import parse as parse_ua
13
  import schedule
14
  import threading
 
 
 
15
 
16
  # --- Konfiguration ---
17
  CHARGENODE_URL = "https://www.chargenode.eu"
 
 
18
 
19
  # Kontrollera om vi kör i Hugging Face-miljön
20
  IS_HUGGINGFACE = os.environ.get("SPACE_ID") is not None
@@ -57,7 +62,13 @@ scheduler = CommitScheduler(
57
 
58
  # --- Globala variabler ---
59
  last_log = None # Sparar loggdata från senaste svar för feedback
60
- full_context = None # Används för att spara hela kontexten
 
 
 
 
 
 
61
 
62
  # --- Förbättrad loggfunktion ---
63
  def safe_append_to_log(log_entry):
@@ -143,22 +154,69 @@ def load_prompt():
143
  print(f"Fel vid inläsning av prompt.txt: {e}, använder standardprompt")
144
  return "Du är ChargeNode's AI-assistent. Svara på frågor om ChargeNode's produkter och tjänster baserat på den tillhandahållna informationen."
145
 
146
- def load_full_context():
147
- """Laddar hela kontexten en gång och cachar resultatet."""
148
- global full_context
149
- if full_context is None:
150
- print("Laddar alla textfiler till fullständig kontext...")
151
- full_context = load_local_files()
152
- print(f"Laddade {len(full_context)} tecken till kontext")
153
- return full_context
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
  # Ladda prompt template
156
  prompt_template = load_prompt()
157
 
158
  def generate_answer(query):
159
- """Genererar svar baserat på fråga med hela kontexten."""
160
- # Hämta hela kontexten
161
- context = load_full_context()
162
 
163
  if not context.strip():
164
  return "Jag hittar ingen relevant information i mina källor.\n\nDetta är ett AI genererat svar."
@@ -166,16 +224,16 @@ def generate_answer(query):
166
  # System-prompts och användarfråga
167
  system_prompt = prompt_template
168
 
169
- # Skapa ett renare användarmeddelande
170
  user_message = f"""Jag har en fråga om ChargeNode.
171
 
172
- Hela dataunderlaget du kan använda för att svara:
173
  {context}
174
 
175
  Min fråga är: {query}"""
176
 
177
  try:
178
- # Använd Claude Haiku med hela kontexten
179
  response = anthropic_client.messages.create(
180
  model="claude-3-haiku-20240307",
181
  max_tokens=500,
@@ -786,10 +844,10 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
786
  [chat_interface, support_interface, success_interface, chat_preview]
787
  )
788
 
789
- # Ladda kontexten direkt vid uppstart
790
- print("Förbereder hela kontexten vid uppstart...")
791
- load_full_context()
792
- print("Kontext laddad och redo!")
793
 
794
  if __name__ == "__main__":
795
  app.launch(share=True)
 
12
  from user_agents import parse as parse_ua
13
  import schedule
14
  import threading
15
+ from sentence_transformers import SentenceTransformer
16
+ import numpy as np
17
+ import faiss
18
 
19
  # --- Konfiguration ---
20
  CHARGENODE_URL = "https://www.chargenode.eu"
21
+ MAX_CHUNK_SIZE = 1024 # Storlek på chunker för indexering
22
+ RETRIEVAL_K = 3 # Antal chunker att hämta vid varje sökning
23
 
24
  # Kontrollera om vi kör i Hugging Face-miljön
25
  IS_HUGGINGFACE = os.environ.get("SPACE_ID") is not None
 
62
 
63
  # --- Globala variabler ---
64
  last_log = None # Sparar loggdata från senaste svar för feedback
65
+
66
+ # Globala variabler för embeddings
67
+ embedder = None
68
+ embeddings = None
69
+ index = None
70
+ chunks = []
71
+ chunk_sources = []
72
 
73
  # --- Förbättrad loggfunktion ---
74
  def safe_append_to_log(log_entry):
 
154
  print(f"Fel vid inläsning av prompt.txt: {e}, använder standardprompt")
155
  return "Du är ChargeNode's AI-assistent. Svara på frågor om ChargeNode's produkter och tjänster baserat på den tillhandahållna informationen."
156
 
157
+ # Förbered textsegment
158
+ def prepare_chunks(text_data):
159
+ """Delar upp texten i mindre segment för embedding och sökning."""
160
+ chunks, sources = [], []
161
+ for source, text in text_data.items():
162
+ paragraphs = [p for p in text.split("\n") if p.strip()]
163
+ chunk = ""
164
+ for para in paragraphs:
165
+ if len(chunk) + len(para) + 1 <= MAX_CHUNK_SIZE:
166
+ chunk += " " + para
167
+ else:
168
+ if chunk.strip():
169
+ chunks.append(chunk.strip())
170
+ sources.append(source)
171
+ chunk = para
172
+ if chunk.strip():
173
+ chunks.append(chunk.strip())
174
+ sources.append(source)
175
+ return chunks, sources
176
+
177
+ def initialize_embeddings():
178
+ """Initierar SentenceTransformer och FAISS-index vid första anrop."""
179
+ global embedder, embeddings, index, chunks, chunk_sources
180
+
181
+ if embedder is None:
182
+ print("Initierar SentenceTransformer och FAISS-index...")
183
+ # Ladda och förbered lokal data
184
+ print("Laddar textdata...")
185
+ text_data = {"local_files": load_local_files()}
186
+ print("Förbereder textsegment...")
187
+ chunks, chunk_sources = prepare_chunks(text_data)
188
+ print(f"{len(chunks)} segment laddade")
189
+
190
+ print("Skapar embeddings...")
191
+ embedder = SentenceTransformer('all-MiniLM-L6-v2')
192
+ embeddings = embedder.encode(chunks, convert_to_numpy=True)
193
+ embeddings /= np.linalg.norm(embeddings, axis=1, keepdims=True)
194
+ index = faiss.IndexFlatIP(embeddings.shape[1])
195
+ index.add(embeddings)
196
+ print("FAISS-index klart")
197
+
198
+ def retrieve_context(query, k=RETRIEVAL_K):
199
+ """Hämtar relevant kontext för frågor."""
200
+ # Säkerställ att modeller är laddade
201
+ initialize_embeddings()
202
+
203
+ query_embedding = embedder.encode([query], convert_to_numpy=True)
204
+ query_embedding /= np.linalg.norm(query_embedding)
205
+ D, I = index.search(query_embedding, k)
206
+ retrieved, sources = [], set()
207
+ for idx in I[0]:
208
+ if idx < len(chunks):
209
+ retrieved.append(chunks[idx])
210
+ sources.add(chunk_sources[idx])
211
+ return " ".join(retrieved), list(sources)
212
 
213
  # Ladda prompt template
214
  prompt_template = load_prompt()
215
 
216
  def generate_answer(query):
217
+ """Genererar svar baserat på fråga och retrieval-baserad kontext med Claude Haiku."""
218
+ # Hämta relevant kontext via RAG istället för hela databasen
219
+ context, sources = retrieve_context(query)
220
 
221
  if not context.strip():
222
  return "Jag hittar ingen relevant information i mina källor.\n\nDetta är ett AI genererat svar."
 
224
  # System-prompts och användarfråga
225
  system_prompt = prompt_template
226
 
227
+ # Skapa ett renare användarmeddelande med bara den relevanta kontexten
228
  user_message = f"""Jag har en fråga om ChargeNode.
229
 
230
+ Relevant kontext för frågan:
231
  {context}
232
 
233
  Min fråga är: {query}"""
234
 
235
  try:
236
+ # Använd Claude Haiku med RAG-baserad kontext
237
  response = anthropic_client.messages.create(
238
  model="claude-3-haiku-20240307",
239
  max_tokens=500,
 
844
  [chat_interface, support_interface, success_interface, chat_preview]
845
  )
846
 
847
+ # Initialisera embeddings vid uppstart
848
+ print("Förbereder embedding-modell och index...")
849
+ initialize_embeddings()
850
+ print("Embedding-modell och index redo!")
851
 
852
  if __name__ == "__main__":
853
  app.launch(share=True)