antimoda1 commited on
Commit
3592961
·
1 Parent(s): cf07b83

remove table

Browse files
Files changed (1) hide show
  1. app.py +89 -51
app.py CHANGED
@@ -94,7 +94,7 @@ def create_heatmap(scores, chunk_ids, top_k_indices=None):
94
  return fig
95
 
96
  def perform_search(query, top_k):
97
- """Этап 1: Поиск и отображение heatmap"""
98
 
99
  if not query:
100
  return None, None, [], [], "Введите вопрос для поиска"
@@ -105,16 +105,13 @@ def perform_search(query, top_k):
105
  # Получаем индексы чанков
106
  chunk_ids = list(range(len(scores)))
107
 
108
- # Находим top-k индексов
109
  top_k = min(top_k, len(scores))
110
  top_k_indices = list(reversed(np.argsort(scores)[-top_k:]))
111
 
112
- # Создаем heatmap
113
- heatmap_fig = create_heatmap(scores, chunk_ids, top_k_indices)
114
-
115
- status = f"Найдено {len(scores)} чанков. Top-{top_k} выделены в heatmap."
116
 
117
- return heatmap_fig, scores, chunk_ids, top_k_indices, status
118
 
119
  def filter_chunks_by_documents(top_k_indices, all_scores, selected_docs):
120
  """Фильтрует чанки по выбранным документам"""
@@ -139,44 +136,71 @@ def filter_chunks_by_documents(top_k_indices, all_scores, selected_docs):
139
 
140
  return filtered_indices
141
 
142
- def update_display_after_filter(filtered_indices, all_scores):
143
- """Обновляет отображение после применения фильтра"""
144
- if len(filtered_indices)==0:
145
- return []
146
 
147
- # Сортируем чанки для отображения
 
 
 
 
148
  chunks_with_info = []
149
- for idx in filtered_indices:
150
  if idx >= len(retrieval.docs_metadata) or idx >= len(all_scores):
151
  continue
152
 
153
  doc_id = retrieval.docs_metadata[idx]
154
  doc_name = retrieval.docs_names[doc_id] if doc_id < len(retrieval.docs_names) else "Неизвестный документ"
155
- score = all_scores[idx]
156
- chunk_text = retrieval.chunks[idx][:100] + "..."
157
 
158
  chunks_with_info.append({
159
  'index': idx,
160
  'doc_name': doc_name,
161
  'doc_id': doc_id,
162
- 'score': score,
163
- 'text': chunk_text
164
  })
165
 
166
- # Сортируем по документу и индексу чанка
167
- chunks_with_info.sort(key=lambda x: (x['doc_name'], x['index']))
168
-
169
- # Форматируем для вывода в таблицу
170
- formatted_chunks = []
171
- for chunk in chunks_with_info:
172
- formatted_chunks.append([
173
- chunk['index'],
174
- chunk['doc_name'],
175
- f"{chunk['score']:.3f}",
176
- chunk['text']
177
- ])
178
-
179
- return formatted_chunks
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  def ask_llm(query, filtered_indices_state):
182
  """Этап 2: Отправка отфильтрованных чанков в LLM с потоковой выдачей"""
@@ -248,14 +272,14 @@ with gr.Blocks(title="RAG Application", theme=gr.themes.Soft()) as iface:
248
  lines=1
249
  )
250
 
251
- # Фильтр ДО поиска
252
  with gr.Row():
253
  top_k_slider = gr.Slider(
254
  minimum=1,
255
  maximum=100,
256
  value=30,
257
  step=1,
258
- label="Top-k чанков"
259
  )
260
 
261
  # Кнопка поиска
@@ -266,24 +290,31 @@ with gr.Blocks(title="RAG Application", theme=gr.themes.Soft()) as iface:
266
 
267
  with gr.Row():
268
  with gr.Column(scale=1):
269
- # Фильтр ПОСЛЕ поиска
270
  docs_after = gr.CheckboxGroup(
271
  choices=retrieval.docs_names,
272
- label="Фильтр после поиска",
273
- info="Выберите документы для отображения (если ничего не выбрано - показываются все)"
274
  )
275
 
276
- # Список найденных чанков
277
- chunks_display = gr.Dataframe(
278
- headers=["Чанк", "Документ", "Score", "Превью"],
279
- label="Найденные чанки",
280
- interactive=False,
281
- visible=True,
 
282
  )
283
 
284
  with gr.Column(scale=2):
285
- # Heatmap
286
- heatmap_output = gr.Plot(label="Heatmap релевантности")
 
 
 
 
 
 
287
 
288
  with gr.Row():
289
  with gr.Column(scale=1):
@@ -314,15 +345,15 @@ with gr.Blocks(title="RAG Application", theme=gr.themes.Soft()) as iface:
314
  search_btn.click(
315
  fn=perform_search,
316
  inputs=[search_query_input, top_k_slider],
317
- outputs=[heatmap_output, all_scores_state, all_chunk_ids_state, top_k_indices_state, search_status]
318
  ).then(
319
  fn=filter_chunks_by_documents,
320
  inputs=[top_k_indices_state, all_scores_state, docs_after],
321
  outputs=[filtered_indices_state]
322
  ).then(
323
- fn=update_display_after_filter,
324
- inputs=[filtered_indices_state, all_scores_state],
325
- outputs=[chunks_display]
326
  )
327
 
328
  # Обработчик изменения фильтра документов
@@ -331,9 +362,16 @@ with gr.Blocks(title="RAG Application", theme=gr.themes.Soft()) as iface:
331
  inputs=[top_k_indices_state, all_scores_state, docs_after],
332
  outputs=[filtered_indices_state]
333
  ).then(
334
- fn=update_display_after_filter,
335
- inputs=[filtered_indices_state, all_scores_state],
336
- outputs=[chunks_display]
 
 
 
 
 
 
 
337
  )
338
 
339
  # Отправка в LLM с потоковой выдачей
 
94
  return fig
95
 
96
  def perform_search(query, top_k):
97
+ """Этап 1: Поиск и возврат результатов"""
98
 
99
  if not query:
100
  return None, None, [], [], "Введите вопрос для поиска"
 
105
  # Получаем индексы чанков
106
  chunk_ids = list(range(len(scores)))
107
 
108
+ # Находим top-k индексов (сортируем по релевантности)
109
  top_k = min(top_k, len(scores))
110
  top_k_indices = list(reversed(np.argsort(scores)[-top_k:]))
111
 
112
+ status = f"Найдено {len(scores)} чанков. Top-{top_k} выбраны."
 
 
 
113
 
114
+ return None, scores, chunk_ids, top_k_indices, status
115
 
116
  def filter_chunks_by_documents(top_k_indices, all_scores, selected_docs):
117
  """Фильтрует чанки по выбранным документам"""
 
136
 
137
  return filtered_indices
138
 
139
+ def format_retrieval_results(filtered_indices, all_scores, top_k_results):
140
+ """Форматирует результаты retrieval для отображения в текстовом поле"""
141
+ if len(filtered_indices) == 0:
142
+ return "Нет результатов"
143
 
144
+ # Берем только top_k результатов
145
+ top_k_results = min(top_k_results, len(filtered_indices))
146
+ selected_indices = filtered_indices[:top_k_results]
147
+
148
+ # Сортируем по документу и индексу чанка
149
  chunks_with_info = []
150
+ for idx in selected_indices:
151
  if idx >= len(retrieval.docs_metadata) or idx >= len(all_scores):
152
  continue
153
 
154
  doc_id = retrieval.docs_metadata[idx]
155
  doc_name = retrieval.docs_names[doc_id] if doc_id < len(retrieval.docs_names) else "Неизвестный документ"
 
 
156
 
157
  chunks_with_info.append({
158
  'index': idx,
159
  'doc_name': doc_name,
160
  'doc_id': doc_id,
161
+ 'chunk_text': retrieval.chunks[idx]
 
162
  })
163
 
164
+ if not chunks_with_info:
165
+ return "Нет валидных чанков"
166
+
167
+ # Группируем чанки по документам
168
+ docs_chunks = {}
169
+ for chunk_info in chunks_with_info:
170
+ doc_name = chunk_info['doc_name']
171
+ if doc_name not in docs_chunks:
172
+ docs_chunks[doc_name] = []
173
+ docs_chunks[doc_name].append(chunk_info['index'])
174
+
175
+ # Форматируем вывод
176
+ result_lines = []
177
+ for doc_name in sorted(docs_chunks.keys()):
178
+ chunk_indices = sorted(docs_chunks[doc_name])
179
+
180
+ # Группируем подряд идущие индексы
181
+ groups = []
182
+ current_group = [chunk_indices[0]]
183
+
184
+ for i in range(1, len(chunk_indices)):
185
+ if chunk_indices[i] == chunk_indices[i-1] + 1:
186
+ current_group.append(chunk_indices[i])
187
+ else:
188
+ groups.append(current_group)
189
+ current_group = [chunk_indices[i]]
190
+ groups.append(current_group)
191
+
192
+ # Собираем текст для каждой группы
193
+ group_texts = []
194
+ for group in groups:
195
+ sentences = [retrieval.chunks[idx] for idx in group]
196
+ group_texts.append(", ".join(sentences))
197
+
198
+ # Выводим документ с многоточием между группами
199
+ doc_output = f"Документ {doc_name}:\n" + " ... ".join(group_texts)
200
+ result_lines.append(doc_output)
201
+ result_lines.append("") # Пустая строка между документами
202
+
203
+ return "\n".join(result_lines)
204
 
205
  def ask_llm(query, filtered_indices_state):
206
  """Этап 2: Отправка отфильтрованных чанков в LLM с потоковой выдачей"""
 
272
  lines=1
273
  )
274
 
275
+ # Фильтры ДО поиска
276
  with gr.Row():
277
  top_k_slider = gr.Slider(
278
  minimum=1,
279
  maximum=100,
280
  value=30,
281
  step=1,
282
+ label="Top-k чанков для поиска"
283
  )
284
 
285
  # Кнопка поиска
 
290
 
291
  with gr.Row():
292
  with gr.Column(scale=1):
293
+ # Фильтр ПОСЛЕ поиска для документов
294
  docs_after = gr.CheckboxGroup(
295
  choices=retrieval.docs_names,
296
+ label="Фильтр по документам",
297
+ info="Выберите документы (если ничего не выбрано - показываются все)"
298
  )
299
 
300
+ # Слайдер для выбора числа чанков к отображению
301
+ display_k_slider = gr.Slider(
302
+ minimum=1,
303
+ maximum=100,
304
+ value=10,
305
+ step=1,
306
+ label="Число чанков к отображению"
307
  )
308
 
309
  with gr.Column(scale=2):
310
+ # Большое текстовое поле для результатов retrieval
311
+ retrieval_results = gr.Textbox(
312
+ label="Результаты retrieval",
313
+ placeholder="Результаты поиска появятся здесь",
314
+ lines=15,
315
+ max_lines=30,
316
+ interactive=False
317
+ )
318
 
319
  with gr.Row():
320
  with gr.Column(scale=1):
 
345
  search_btn.click(
346
  fn=perform_search,
347
  inputs=[search_query_input, top_k_slider],
348
+ outputs=[None, all_scores_state, all_chunk_ids_state, top_k_indices_state, search_status]
349
  ).then(
350
  fn=filter_chunks_by_documents,
351
  inputs=[top_k_indices_state, all_scores_state, docs_after],
352
  outputs=[filtered_indices_state]
353
  ).then(
354
+ fn=format_retrieval_results,
355
+ inputs=[filtered_indices_state, all_scores_state, display_k_slider],
356
+ outputs=[retrieval_results]
357
  )
358
 
359
  # Обработчик изменения фильтра документов
 
362
  inputs=[top_k_indices_state, all_scores_state, docs_after],
363
  outputs=[filtered_indices_state]
364
  ).then(
365
+ fn=format_retrieval_results,
366
+ inputs=[filtered_indices_state, all_scores_state, display_k_slider],
367
+ outputs=[retrieval_results]
368
+ )
369
+
370
+ # Обработчик изменения слайдера отображения
371
+ display_k_slider.change(
372
+ fn=format_retrieval_results,
373
+ inputs=[filtered_indices_state, all_scores_state, display_k_slider],
374
+ outputs=[retrieval_results]
375
  )
376
 
377
  # Отправка в LLM с потоковой выдачей