jaczad commited on
Commit
2a89cf0
·
1 Parent(s): fa696d9

Działający zestaw

Browse files
Files changed (4) hide show
  1. .DS_Store +0 -0
  2. .gradio/certificate.pem +31 -0
  3. README.md +83 -1
  4. app.py +30 -25
.DS_Store ADDED
Binary file (6.15 kB). View file
 
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
31
+ -----END CERTIFICATE-----
README.md CHANGED
@@ -10,5 +10,87 @@ pinned: false
10
  license: cc-by-4.0
11
  short_description: Chatbot korzystający z zasobów serwisu mojaszuflada.pl
12
  ---
 
 
13
 
14
- An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  license: cc-by-4.0
11
  short_description: Chatbot korzystający z zasobów serwisu mojaszuflada.pl
12
  ---
13
+
14
+ # Szuflada
15
 
16
+ Czatbot korzystający z zasobów serwisu [mojaszuflada.pl](https://mojaszuflada.pl), wykorzystujący Gradio oraz RAG z lokalną bazą Chroma i Hugging Face Inference API.
17
+
18
+ ## Instalacja
19
+
20
+ 1. Sklonuj repozytorium:
21
+
22
+ ```bash
23
+ git clone https://github.com/<użytkownik>/szuflada.git
24
+ cd szuflada
25
+ ```
26
+
27
+ 2. Utwórz i aktywuj środowisko wirtualne:
28
+
29
+ ```bash
30
+ python3 -m venv venv
31
+ source venv/bin/activate # Linux/macOS
32
+ venv\Scripts\activate # Windows
33
+ ```
34
+
35
+ 3. Zainstaluj zależności:
36
+
37
+ ```bash
38
+ pip install -r requirements.txt
39
+ ```
40
+
41
+ 4. Zaloguj się do Hugging Face (jeśli korzystasz z API):
42
+
43
+ ```bash
44
+ huggingface-cli login
45
+ ```
46
+
47
+ 5. (Opcjonalnie) Ustaw zmienną środowiskową z tokenem:
48
+
49
+ ```bash
50
+ export HUGGINGFACEHUB_API_TOKEN=Twój_Token
51
+ ```
52
+
53
+ ## Użycie
54
+
55
+ Uruchom aplikację lokalnie:
56
+
57
+ ```bash
58
+ python app.py
59
+ ```
60
+
61
+ Aplikacja będzie dostępna pod adresem <http://localhost:7860>. Otwórz tę stronę w przeglądarce, aby rozpocząć czat.
62
+
63
+ ## Osadzanie na innych stronach internetowych
64
+
65
+ ### Metoda 1: iframe
66
+
67
+ ```html
68
+ <iframe src="http://adres_twojej_aplikacji:7860" width="700" height="800" frameborder="0"></iframe>
69
+ ```
70
+
71
+ ### Metoda 2: Embed Gradio (Hugging Face Spaces)
72
+
73
+ Jeśli aplikacja jest wdrożona jako Space na Hugging Face, użyj oficjalnego skryptu:
74
+
75
+ ```html
76
+ <script src="https://cdn.jsdelivr.net/npm/@gradio/embed"></script>
77
+ <gradio-embed
78
+ src="username/szuflada" <!-- zastąp username swoją nazwą użytkownika/Space -->
79
+ width="700"
80
+ height="800"
81
+ ></gradio-embed>
82
+ ```
83
+
84
+ ### Metoda 3: JavaScript SDK
85
+
86
+ ```html
87
+ <script type="module">
88
+ import Gradio from "https://cdn.jsdelivr.net/npm/@gradio/embed@2.0.0/+esm";
89
+ new Gradio.Embed("https://huggingface.co/embed/username/szuflada", {
90
+ container: document.getElementById("gradio-container"),
91
+ width: 700,
92
+ height: 800
93
+ });
94
+ </script>
95
+ <div id="gradio-container"></div>
96
+ ```
app.py CHANGED
@@ -10,8 +10,10 @@ from langchain_community.chat_message_histories import ChatMessageHistory
10
  from langchain_core.runnables.history import RunnableWithMessageHistory
11
 
12
  # --- 1. Inicjalizacja modeli i retrievera ---
13
- llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
 
14
  embedder = OpenAIEmbeddings(model="text-embedding-3-small")
 
15
  baza = Chroma(
16
  collection_name="szuflada",
17
  embedding_function=embedder,
@@ -22,13 +24,13 @@ baza = Chroma(
22
  # - "mmr" (Maximal Marginal Relevance)
23
  # - "similarity_score_threshold" (z progiem score_threshold)
24
 
25
- # Przykład zmiany na standardowe wyszukiwanie podobieństw:
26
  retriever = baza.as_retriever(
27
- search_type="similarity", # <- zmień na "similarity" lub "mmr" jeśli chcesz
28
- search_kwargs={"k": 5}
29
  )
30
 
31
  # --- 2. Tworzenie łańcucha RAG z historią ---
 
32
  contextualize_q_system_prompt = (
33
  "Biorąc pod uwagę historię czatu i ostatnie pytanie użytkownika, "
34
  "które może odnosić się do kontekstu w historii czatu, "
@@ -43,15 +45,17 @@ contextualize_q_prompt = ChatPromptTemplate.from_messages(
43
  ("human", "{input}"),
44
  ]
45
  )
 
46
  history_aware_retriever = create_history_aware_retriever(
47
  llm, retriever, contextualize_q_prompt
48
  )
49
 
 
50
  qa_system_prompt = (
51
  "Jesteś asystentem do zadawania pytań i odpowiedzi na temat treści ze strony mojaszuflada.pl. "
52
  "Użyj poniższych fragmentów odzyskanego kontekstu, aby odpowiedzieć na pytanie. "
53
  "Odpowiadaj zawsze w języku polskim. "
54
- "Jeśli nie znasz odpowiedzi, po prostu powiedz, że nie wiesz. "
55
  "Zachowaj zwięzłość odpowiedzi, ale bądź pomocny i przyjazny."
56
  "\n\n{context}"
57
  )
@@ -62,17 +66,22 @@ qa_prompt = ChatPromptTemplate.from_messages(
62
  ("human", "{input}"),
63
  ]
64
  )
 
65
  question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
66
 
 
67
  rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
68
 
 
69
  store = {}
70
 
71
  def get_session_history(session_id: str) -> BaseChatMessageHistory:
 
72
  if session_id not in store:
73
  store[session_id] = ChatMessageHistory()
74
  return store[session_id]
75
 
 
76
  conversational_rag_chain = RunnableWithMessageHistory(
77
  rag_chain,
78
  get_session_history,
@@ -83,8 +92,9 @@ conversational_rag_chain = RunnableWithMessageHistory(
83
 
84
  # --- 3. Funkcje pomocnicze dla Gradio ---
85
  def format_sources(source_docs):
 
86
  if not source_docs:
87
- return "_Brak źródeł do wyświetlenia._"
88
 
89
  sources = []
90
  for doc in source_docs:
@@ -98,8 +108,6 @@ def format_sources(source_docs):
98
  sources.append(f"- [{title}]({source_url}) ({pub_date})")
99
  else:
100
  sources.append(f"- [{title}]({source_url})")
101
- # Dodaj informację o liczbie chunków (debug)
102
- sources.append(f"\n_Znaleziono chunków: {len(source_docs)}_")
103
  return "\n".join(sources)
104
 
105
  # --- 4. Budowa interfejsu Gradio ---
@@ -107,15 +115,17 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Szuflada Chatbot
107
  session_id = gr.State(lambda: str(uuid.uuid4()))
108
 
109
  gr.Markdown(
110
- """# Czat z Szufladą\n### Zadaj pytanie na temat treści ze strony [mojaszuflada.pl](https://mojaszuflada.pl)
111
  """
112
  )
113
 
 
114
  chatbot = gr.Chatbot(
115
  label="Rozmowa",
116
  height=500,
117
  )
118
 
 
119
  with gr.Row():
120
  msg = gr.Textbox(
121
  show_label=False,
@@ -125,27 +135,32 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Szuflada Chatbot
125
  )
126
  submit_btn = gr.Button("Wyślij", variant="primary", scale=1)
127
 
 
128
  def respond(message, chat_history, sess_id):
 
129
  response = conversational_rag_chain.invoke(
130
  {"input": message},
131
  config={"configurable": {"session_id": sess_id}},
132
  )
133
- # Dodaj logowanie score dla debugowania
134
  context_docs = response.get("context", [])
135
- for i, doc in enumerate(context_docs):
136
- score = doc.metadata.get("score", "brak score")
137
- print(f"Chunk {i+1}: score={score}, title={doc.metadata.get('title')}")
 
138
  sources_md = format_sources(context_docs)
139
- answer_with_sources = response["answer"] + "\n\n**Źródła:**\n" + sources_md
 
140
  chat_history.append((message, answer_with_sources))
141
  return chat_history
142
 
 
143
  submit_btn.click(
144
  respond,
145
  [msg, chatbot, session_id],
146
  [chatbot]
147
  ).then(lambda: gr.update(value=""), None, [msg], queue=False)
148
 
 
149
  msg.submit(
150
  respond,
151
  [msg, chatbot, session_id],
@@ -154,15 +169,5 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), title="Szuflada Chatbot
154
 
155
  # --- 5. Uruchomienie aplikacji ---
156
  if __name__ == "__main__":
157
- # --- TEST: sprawdź bezpośrednio retriever ---
158
- test_query = "test" # <- wpisz tu frazę, która powinna być w bazie
159
- print("\n=== TEST RETRIEVER ===")
160
- docs = retriever.get_relevant_documents(test_query)
161
- print(f"Znaleziono {len(docs)} dokumentów dla zapytania: '{test_query}'")
162
- for i, doc in enumerate(docs):
163
- score = doc.metadata.get("score", "brak score")
164
- print(f"Chunk {i+1}: score={score}, title={doc.metadata.get('title')}, source={doc.metadata.get('source')}")
165
- print("=== KONIEC TESTU ===\n")
166
- # --- KONIEC TESTU ---
167
-
168
  demo.launch(inbrowser=True)
 
10
  from langchain_core.runnables.history import RunnableWithMessageHistory
11
 
12
  # --- 1. Inicjalizacja modeli i retrievera ---
13
+ # Inicjalizacja modelu językowego oraz embeddera
14
+ llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
15
  embedder = OpenAIEmbeddings(model="text-embedding-3-small")
16
+ # Inicjalizacja bazy Chroma z embeddingami
17
  baza = Chroma(
18
  collection_name="szuflada",
19
  embedding_function=embedder,
 
24
  # - "mmr" (Maximal Marginal Relevance)
25
  # - "similarity_score_threshold" (z progiem score_threshold)
26
 
27
+ # Retriever do wyszukiwania podobnych fragmentów
28
  retriever = baza.as_retriever(
29
+ search_kwargs={"k": 3}
 
30
  )
31
 
32
  # --- 2. Tworzenie łańcucha RAG z historią ---
33
+ # Prompt do kontekstualizacji pytania na podstawie historii czatu
34
  contextualize_q_system_prompt = (
35
  "Biorąc pod uwagę historię czatu i ostatnie pytanie użytkownika, "
36
  "które może odnosić się do kontekstu w historii czatu, "
 
45
  ("human", "{input}"),
46
  ]
47
  )
48
+ # Łańcuch do kontekstualizacji pytania z historią
49
  history_aware_retriever = create_history_aware_retriever(
50
  llm, retriever, contextualize_q_prompt
51
  )
52
 
53
+ # Prompt do generowania odpowiedzi na podstawie kontekstu
54
  qa_system_prompt = (
55
  "Jesteś asystentem do zadawania pytań i odpowiedzi na temat treści ze strony mojaszuflada.pl. "
56
  "Użyj poniższych fragmentów odzyskanego kontekstu, aby odpowiedzieć na pytanie. "
57
  "Odpowiadaj zawsze w języku polskim. "
58
+ "Jeśli nie znasz odpowiedzi, po prostu powiedz, że tego nie wiesz. "
59
  "Zachowaj zwięzłość odpowiedzi, ale bądź pomocny i przyjazny."
60
  "\n\n{context}"
61
  )
 
66
  ("human", "{input}"),
67
  ]
68
  )
69
+ # Łańcuch generujący odpowiedź na podstawie dokumentów
70
  question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
71
 
72
+ # Połączenie retrievera z generatorem odpowiedzi
73
  rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
74
 
75
+ # Słownik do przechowywania historii czatu dla sesji
76
  store = {}
77
 
78
  def get_session_history(session_id: str) -> BaseChatMessageHistory:
79
+ # Zwraca historię czatu dla danej sesji (tworzy jeśli nie istnieje)
80
  if session_id not in store:
81
  store[session_id] = ChatMessageHistory()
82
  return store[session_id]
83
 
84
+ # Łańcuch RAG z obsługą historii wiadomości
85
  conversational_rag_chain = RunnableWithMessageHistory(
86
  rag_chain,
87
  get_session_history,
 
92
 
93
  # --- 3. Funkcje pomocnicze dla Gradio ---
94
  def format_sources(source_docs):
95
+ # Formatuje listę źródeł do wyświetlenia w odpowiedzi
96
  if not source_docs:
97
+ return "?"
98
 
99
  sources = []
100
  for doc in source_docs:
 
108
  sources.append(f"- [{title}]({source_url}) ({pub_date})")
109
  else:
110
  sources.append(f"- [{title}]({source_url})")
 
 
111
  return "\n".join(sources)
112
 
113
  # --- 4. Budowa interfejsu Gradio ---
 
115
  session_id = gr.State(lambda: str(uuid.uuid4()))
116
 
117
  gr.Markdown(
118
+ """# Czat z Moją Szufladą\n### Zadaj pytanie na temat treści ze strony [mojaszuflada.pl](https://mojaszuflada.pl)
119
  """
120
  )
121
 
122
+ # Komponent czatu
123
  chatbot = gr.Chatbot(
124
  label="Rozmowa",
125
  height=500,
126
  )
127
 
128
+ # Pole tekstowe i przycisk do wysyłania wiadomości
129
  with gr.Row():
130
  msg = gr.Textbox(
131
  show_label=False,
 
135
  )
136
  submit_btn = gr.Button("Wyślij", variant="primary", scale=1)
137
 
138
+ # Funkcja obsługująca odpowiedź na wiadomość użytkownika
139
  def respond(message, chat_history, sess_id):
140
+ # Wywołanie łańcucha RAG z historią
141
  response = conversational_rag_chain.invoke(
142
  {"input": message},
143
  config={"configurable": {"session_id": sess_id}},
144
  )
 
145
  context_docs = response.get("context", [])
146
+ # Debug: wypisz poziom podobieństwa dla znalezionych chunków
147
+ debug_scores = baza.similarity_search_with_score(message, k=len(context_docs))
148
+ for i, (doc, score) in enumerate(debug_scores):
149
+ print(f"Chunk {i+1}: similarity_score={score}, title={doc.metadata.get('title')}")
150
  sources_md = format_sources(context_docs)
151
+ answer = response.get("answer") or ""
152
+ answer_with_sources = answer + "\n\n**Źródła:**\n" + sources_md
153
  chat_history.append((message, answer_with_sources))
154
  return chat_history
155
 
156
+ # Obsługa kliknięcia przycisku "Wyślij"
157
  submit_btn.click(
158
  respond,
159
  [msg, chatbot, session_id],
160
  [chatbot]
161
  ).then(lambda: gr.update(value=""), None, [msg], queue=False)
162
 
163
+ # Obsługa wysłania wiadomości enterem
164
  msg.submit(
165
  respond,
166
  [msg, chatbot, session_id],
 
169
 
170
  # --- 5. Uruchomienie aplikacji ---
171
  if __name__ == "__main__":
172
+ # Uruchom aplikację Gradio z publicznym linkiem
 
 
 
 
 
 
 
 
 
 
173
  demo.launch(inbrowser=True)