neuralworm commited on
Commit
5e019c1
·
1 Parent(s): 5c5ad2b
Files changed (1) hide show
  1. app.py +31 -26
app.py CHANGED
@@ -1,7 +1,7 @@
1
- # app.py - v1.3
2
  # Beschreibung: State-of-the-Art RAG-Pipeline mit Gemma-3, FAISS.
3
- # (Fix: Gradio-Warnungen durch Umstellung auf type="messages"
4
- # und Entfernen veralteter Parameter behoben.)
5
 
6
  import os
7
  import torch
@@ -11,7 +11,8 @@ from typing import List, Tuple, Generator, Dict
11
  from threading import Thread
12
 
13
  # ML / Transformers
14
- from sentence_transformers import SentenceTransformer
 
15
  from transformers import AutoProcessor, Gemma3ForConditionalGeneration, TextStreamer
16
 
17
  # Dokumentenverarbeitung & RAG
@@ -19,6 +20,8 @@ from pypdf import PdfReader
19
  from langchain_core.documents import Document
20
  from langchain_text_splitters import RecursiveCharacterTextSplitter
21
  from langchain_community.vectorstores import FAISS
 
 
22
 
23
  # --------------------------------------------------------------------
24
  # Konfiguration
@@ -27,7 +30,8 @@ EMBED_MODEL_ID = "google/embeddinggemma-300m"
27
  LLM_MODEL_ID = "google/gemma-3-4b-it"
28
 
29
  # Globale States
30
- EMBED_MODEL: SentenceTransformer = None
 
31
  LLM_MODEL: Gemma3ForConditionalGeneration = None
32
  LLM_PROCESSOR: AutoProcessor = None
33
  VECTOR_STORE: FAISS = None
@@ -45,13 +49,20 @@ def get_device() -> torch.device:
45
  return torch.device("cpu")
46
 
47
 
48
- def get_embedding_model() -> SentenceTransformer:
49
- """Lädt und initialisiert das Embedding-Modell."""
50
- global EMBED_MODEL
51
- if EMBED_MODEL is None:
52
- device = "cuda" if torch.cuda.is_available() else "cpu"
53
- EMBED_MODEL = SentenceTransformer(EMBED_MODEL_ID, device=device)
54
- return EMBED_MODEL
 
 
 
 
 
 
 
55
 
56
 
57
  def get_llm() -> Tuple[Gemma3ForConditionalGeneration, AutoProcessor]:
@@ -123,7 +134,8 @@ def index_files(file_paths: List[str], progress=gr.Progress(track_tqdm=True)) ->
123
  if not file_paths:
124
  return "Keine Dateien zum Indexieren ausgewählt."
125
 
126
- embed_model = get_embedding_model()
 
127
  text_splitter = get_text_splitter()
128
 
129
  documents: List[Document] = []
@@ -146,7 +158,9 @@ def index_files(file_paths: List[str], progress=gr.Progress(track_tqdm=True)) ->
146
 
147
  progress(0.5, desc="2/2: Embeddings erstellen & FAISS Index aufbauen...")
148
 
149
- new_store = FAISS.from_documents(documents, embed_model)
 
 
150
 
151
  if VECTOR_STORE is None:
152
  VECTOR_STORE = new_store
@@ -251,7 +265,7 @@ def build_demo() -> gr.Blocks:
251
  with gr.Blocks(title="Gemma 3 RAG mit FAISS", theme="soft") as demo:
252
  gr.Markdown(
253
  """
254
- # 🔍 Gemma 3 RAG v1.3 – mit FAISS & Streaming
255
  **Eine "State of the Art" RAG-Pipeline mit `google/embeddinggemma-300m` und `google/gemma-3-4b-it`**
256
  1. Lade deine Dokumente hoch und klicke auf "Index aktualisieren".
257
  2. Stelle deine Fragen im Chatfenster. Die Antworten werden live gestreamt.
@@ -287,7 +301,7 @@ def build_demo() -> gr.Blocks:
287
  gr.Markdown("### 💬 Chat über deine Dokumente")
288
  chatbot = gr.Chatbot(
289
  label="Gemma-3 Chat",
290
- type="messages", # <-- GEÄNDERT: Moderner Nachrichtentyp
291
  show_copy_button=True,
292
  height=600,
293
  )
@@ -302,25 +316,16 @@ def build_demo() -> gr.Blocks:
302
  send_btn = gr.Button("Senden", variant="primary", scale=1)
303
 
304
  def chat_interface(message: str, history: list):
305
- """
306
- Passt sich dem neuen Gradio-Nachrichtenformat an.
307
- 'history' ist jetzt eine Liste von Dictionaries.
308
- """
309
  if not message or not message.strip():
310
  return history
311
 
312
- # User-Nachricht an den Verlauf anfügen
313
  history.append({"role": "user", "content": message})
314
- # Platzhalter für die Assistenten-Antwort hinzufügen
315
  history.append({"role": "assistant", "content": ""})
316
 
317
- # Stream die LLM-Antwort in den "content" des letzten Eintrags
318
  for token in answer_with_rag(message, history):
319
  history[-1]["content"] += token
320
  yield history
321
 
322
- # Event Listeners bleiben logisch gleich, funktionieren aber jetzt
323
- # mit dem neuen Chatbot-Format.
324
  msg_textbox.submit(
325
  fn=chat_interface,
326
  inputs=[msg_textbox, chatbot],
@@ -343,4 +348,4 @@ def build_demo() -> gr.Blocks:
343
 
344
  if __name__ == "__main__":
345
  app_demo = build_demo()
346
- app_demo.launch(share=False)
 
1
+ # app.py - v1.4
2
  # Beschreibung: State-of-the-Art RAG-Pipeline mit Gemma-3, FAISS.
3
+ # (Fix: API-Inkompatibilität zwischen SentenceTransformers und LangChain
4
+ # durch Verwendung des `SentenceTransformerEmbeddings`-Wrappers behoben.)
5
 
6
  import os
7
  import torch
 
11
  from threading import Thread
12
 
13
  # ML / Transformers
14
+ # SentenceTransformer ist hier nicht mehr direkt im Code nötig,
15
+ # da der LangChain-Wrapper die Nutzung kapselt.
16
  from transformers import AutoProcessor, Gemma3ForConditionalGeneration, TextStreamer
17
 
18
  # Dokumentenverarbeitung & RAG
 
20
  from langchain_core.documents import Document
21
  from langchain_text_splitters import RecursiveCharacterTextSplitter
22
  from langchain_community.vectorstores import FAISS
23
+ # <-- NEUER IMPORT: Der entscheidende Adapter zwischen den Bibliotheken
24
+ from langchain_community.embeddings import SentenceTransformerEmbeddings
25
 
26
  # --------------------------------------------------------------------
27
  # Konfiguration
 
30
  LLM_MODEL_ID = "google/gemma-3-4b-it"
31
 
32
  # Globale States
33
+ # <-- GEÄNDERT: Die Variable hält jetzt ein LangChain-kompatibles Objekt
34
+ EMBEDDING_FUNCTION = None
35
  LLM_MODEL: Gemma3ForConditionalGeneration = None
36
  LLM_PROCESSOR: AutoProcessor = None
37
  VECTOR_STORE: FAISS = None
 
49
  return torch.device("cpu")
50
 
51
 
52
+ def get_embedding_function():
53
+ """
54
+ Lädt das Embedding-Modell über den LangChain-Wrapper.
55
+ Dieser Wrapper sorgt für die API-Kompatibilität.
56
+ """
57
+ global EMBEDDING_FUNCTION
58
+ if EMBEDDING_FUNCTION is None:
59
+ # Der Wrapper kümmert sich um das Laden des Modells und die
60
+ # korrekte Bereitstellung der .embed_documents() Methode.
61
+ EMBEDDING_FUNCTION = SentenceTransformerEmbeddings(
62
+ model_name=EMBED_MODEL_ID,
63
+ model_kwargs={'device': get_device()}
64
+ )
65
+ return EMBEDDING_FUNCTION
66
 
67
 
68
  def get_llm() -> Tuple[Gemma3ForConditionalGeneration, AutoProcessor]:
 
134
  if not file_paths:
135
  return "Keine Dateien zum Indexieren ausgewählt."
136
 
137
+ # <-- GEÄNDERT: Holt jetzt die korrekte Wrapper-Instanz
138
+ embedding_function = get_embedding_function()
139
  text_splitter = get_text_splitter()
140
 
141
  documents: List[Document] = []
 
158
 
159
  progress(0.5, desc="2/2: Embeddings erstellen & FAISS Index aufbauen...")
160
 
161
+ # <-- GEÄNDERT: Übergibt das LangChain-kompatible Embedding-Objekt.
162
+ # Dieser Aufruf wird jetzt erfolgreich sein.
163
+ new_store = FAISS.from_documents(documents, embedding_function)
164
 
165
  if VECTOR_STORE is None:
166
  VECTOR_STORE = new_store
 
265
  with gr.Blocks(title="Gemma 3 RAG mit FAISS", theme="soft") as demo:
266
  gr.Markdown(
267
  """
268
+ # 🔍 Gemma 3 RAG v1.4 – mit FAISS & Streaming
269
  **Eine "State of the Art" RAG-Pipeline mit `google/embeddinggemma-300m` und `google/gemma-3-4b-it`**
270
  1. Lade deine Dokumente hoch und klicke auf "Index aktualisieren".
271
  2. Stelle deine Fragen im Chatfenster. Die Antworten werden live gestreamt.
 
301
  gr.Markdown("### 💬 Chat über deine Dokumente")
302
  chatbot = gr.Chatbot(
303
  label="Gemma-3 Chat",
304
+ type="messages",
305
  show_copy_button=True,
306
  height=600,
307
  )
 
316
  send_btn = gr.Button("Senden", variant="primary", scale=1)
317
 
318
  def chat_interface(message: str, history: list):
 
 
 
 
319
  if not message or not message.strip():
320
  return history
321
 
 
322
  history.append({"role": "user", "content": message})
 
323
  history.append({"role": "assistant", "content": ""})
324
 
 
325
  for token in answer_with_rag(message, history):
326
  history[-1]["content"] += token
327
  yield history
328
 
 
 
329
  msg_textbox.submit(
330
  fn=chat_interface,
331
  inputs=[msg_textbox, chatbot],
 
348
 
349
  if __name__ == "__main__":
350
  app_demo = build_demo()
351
+ app_demo.launch()