MrSimple07 commited on
Commit
d490230
·
1 Parent(s): a5d5837

added new window for chunking results + added hybrid approach for chunking max limit is 2048"

Browse files
Files changed (2) hide show
  1. app.py +36 -7
  2. documents_prep.py +66 -3
app.py CHANGED
@@ -11,6 +11,29 @@ from config import (
11
  JSON_FILES_DIR, TABLE_DATA_DIR, IMAGE_DATA_DIR, DEFAULT_MODEL, AVAILABLE_MODELS
12
  )
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  def initialize_system(repo_id, hf_token, download_dir, chunks_filename=None,
16
  json_files_dir=None, table_data_dir=None, image_data_dir=None,
@@ -83,7 +106,7 @@ def switch_model(model_name, vector_index):
83
  log_message(error_msg)
84
  return None, f"❌ {error_msg}"
85
 
86
- def create_demo_interface(answer_question_func, switch_model_func, current_model):
87
  with gr.Blocks(title="AIEXP - AI Expert для нормативной документации", theme=gr.themes.Soft()) as demo:
88
 
89
  gr.Markdown("""
@@ -92,7 +115,7 @@ def create_demo_interface(answer_question_func, switch_model_func, current_model
92
  ## Инструмент для работы с нормативной документацией
93
  """)
94
 
95
- with gr.Tab("🏠 Поиск по нормативным документам"):
96
  gr.Markdown("### Задайте вопрос по нормативной документации")
97
 
98
  with gr.Row():
@@ -100,11 +123,11 @@ def create_demo_interface(answer_question_func, switch_model_func, current_model
100
  model_dropdown = gr.Dropdown(
101
  choices=list(AVAILABLE_MODELS.keys()),
102
  value=current_model,
103
- label="🤖 Выберите языковую модель",
104
  info="Выберите модель для генерации ответов"
105
  )
106
  with gr.Column(scale=1):
107
- switch_btn = gr.Button("🔄 Переключить модель", variant="secondary")
108
  model_status = gr.Textbox(
109
  value=f"Текущая модель: {current_model}",
110
  label="Статус модели",
@@ -118,15 +141,13 @@ def create_demo_interface(answer_question_func, switch_model_func, current_model
118
  placeholder="Введите вопрос по нормативным документам...",
119
  lines=3
120
  )
121
- ask_btn = gr.Button("🔍 Найти ответ", variant="primary", size="lg")
122
 
123
  gr.Examples(
124
  examples=[
125
  "О чем этот рисунок: ГОСТ Р 50.04.07-2022 Приложение Л. Л.1.5 Рисунок Л.2",
126
  "Л.9 Формула в ГОСТ Р 50.04.07 - 2022 что и о чем там?",
127
  "Какой стандарт устанавливает порядок признания протоколов испытаний продукции в области использования атомной энергии?",
128
- "Кто несет ответственность за организацию и проведение признания протоколов испытаний продукции?",
129
- "В каких случаях могут быть признаны протоколы испытаний, проведенные лабораториями?",
130
  ],
131
  inputs=question_input
132
  )
@@ -161,6 +182,14 @@ def create_demo_interface(answer_question_func, switch_model_func, current_model
161
  inputs=[question_input],
162
  outputs=[answer_output, sources_output]
163
  )
 
 
 
 
 
 
 
 
164
 
165
  return demo
166
 
 
11
  JSON_FILES_DIR, TABLE_DATA_DIR, IMAGE_DATA_DIR, DEFAULT_MODEL, AVAILABLE_MODELS
12
  )
13
 
14
+ def create_chunks_display_html(chunk_info):
15
+ if not chunk_info:
16
+ return "<div style='padding: 20px; text-align: center;'>Нет данных о чанках</div>"
17
+
18
+ html = "<div style='max-height: 500px; overflow-y: auto; padding: 10px;'>"
19
+ html += f"<h4>Всего чанков: {len(chunk_info)}</h4>"
20
+
21
+ for i, chunk in enumerate(chunk_info):
22
+ bg_color = "#f8f9fa" if i % 2 == 0 else "#e9ecef"
23
+ html += f"""
24
+ <div style='background-color: {bg_color}; padding: 10px; margin: 5px 0; border-radius: 5px; border-left: 4px solid #007bff;'>
25
+ <strong>Документ:</strong> {chunk['document_id']}<br>
26
+ <strong>Раздел:</strong> {chunk['section_id']}<br>
27
+ <strong>Чанк:</strong> {chunk['chunk_id']} | <strong>Размер:</strong> {chunk['chunk_size']} символов<br>
28
+ <strong>Содержание:</strong><br>
29
+ <div style='background-color: white; padding: 8px; margin-top: 5px; border-radius: 3px; font-family: monospace; font-size: 12px;'>
30
+ {chunk['chunk_preview']}
31
+ </div>
32
+ </div>
33
+ """
34
+
35
+ html += "</div>"
36
+ return html
37
 
38
  def initialize_system(repo_id, hf_token, download_dir, chunks_filename=None,
39
  json_files_dir=None, table_data_dir=None, image_data_dir=None,
 
106
  log_message(error_msg)
107
  return None, f"❌ {error_msg}"
108
 
109
+ def create_demo_interface(answer_question_func, switch_model_func, current_model, chunk_info=None):
110
  with gr.Blocks(title="AIEXP - AI Expert для нормативной документации", theme=gr.themes.Soft()) as demo:
111
 
112
  gr.Markdown("""
 
115
  ## Инструмент для работы с нормативной документацией
116
  """)
117
 
118
+ with gr.Tab("Поиск по нормативным документам"):
119
  gr.Markdown("### Задайте вопрос по нормативной документации")
120
 
121
  with gr.Row():
 
123
  model_dropdown = gr.Dropdown(
124
  choices=list(AVAILABLE_MODELS.keys()),
125
  value=current_model,
126
+ label="Выберите языковую модель",
127
  info="Выберите модель для генерации ответов"
128
  )
129
  with gr.Column(scale=1):
130
+ switch_btn = gr.Button("Переключить модель", variant="secondary")
131
  model_status = gr.Textbox(
132
  value=f"Текущая модель: {current_model}",
133
  label="Статус модели",
 
141
  placeholder="Введите вопрос по нормативным документам...",
142
  lines=3
143
  )
144
+ ask_btn = gr.Button("Найти ответ", variant="primary", size="lg")
145
 
146
  gr.Examples(
147
  examples=[
148
  "О чем этот рисунок: ГОСТ Р 50.04.07-2022 Приложение Л. Л.1.5 Рисунок Л.2",
149
  "Л.9 Формула в ГОСТ Р 50.04.07 - 2022 что и о чем там?",
150
  "Какой стандарт устанавливает порядок признания протоколов испытаний продукции в области использования атомной энергии?",
 
 
151
  ],
152
  inputs=question_input
153
  )
 
182
  inputs=[question_input],
183
  outputs=[answer_output, sources_output]
184
  )
185
+
186
+ with gr.Tab("Просмотр чанков"):
187
+ gr.Markdown("### Содержание обработанных чанков документов")
188
+
189
+ chunks_display = gr.HTML(
190
+ value=create_chunks_display_html(chunk_info),
191
+ label="Информация о чанках"
192
+ )
193
 
194
  return demo
195
 
documents_prep.py CHANGED
@@ -4,8 +4,67 @@ import pandas as pd
4
  from huggingface_hub import hf_hub_download, list_repo_files
5
  from llama_index.core import Document
6
  from my_logging import log_message
 
 
7
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  def extract_text_from_json(data, document_id, document_name):
10
  documents = []
11
 
@@ -162,12 +221,16 @@ def load_json_documents(repo_id, hf_token, json_files_dir, download_dir):
162
  log_message(f"Ошибка обработки файла {file_path}: {str(e)}")
163
  continue
164
 
165
- log_message(f"Всего создано {len(all_documents)} текстовых документов")
166
- return all_documents
 
 
 
 
167
 
168
  except Exception as e:
169
  log_message(f"Ошибка загрузки JSON документов: {str(e)}")
170
- return []
171
 
172
 
173
  def extract_section_title(section_text):
 
4
  from huggingface_hub import hf_hub_download, list_repo_files
5
  from llama_index.core import Document
6
  from my_logging import log_message
7
+ from llama_index.core.text_splitter import SentenceSplitter
8
+ from config import CHUNK_SIZE, CHUNK_OVERLAP
9
 
10
 
11
+ def chunk_document(doc, chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP):
12
+ text_splitter = SentenceSplitter(
13
+ chunk_size=chunk_size,
14
+ chunk_overlap=chunk_overlap,
15
+ separator=" "
16
+ )
17
+
18
+ text_chunks = text_splitter.split_text(doc.text)
19
+
20
+ chunked_docs = []
21
+ for i, chunk_text in enumerate(text_chunks):
22
+ chunk_metadata = doc.metadata.copy()
23
+ chunk_metadata.update({
24
+ "chunk_id": i,
25
+ "total_chunks": len(text_chunks),
26
+ "chunk_size": len(chunk_text),
27
+ "original_doc_id": doc.id_ if hasattr(doc, 'id_') else None
28
+ })
29
+
30
+ chunked_doc = Document(
31
+ text=chunk_text,
32
+ metadata=chunk_metadata
33
+ )
34
+ chunked_docs.append(chunked_doc)
35
+
36
+ return chunked_docs
37
+
38
+
39
+ def process_documents_with_chunking(documents):
40
+ all_chunked_docs = []
41
+ chunk_info = []
42
+
43
+ for doc in documents:
44
+ if len(doc.text) > CHUNK_SIZE:
45
+ chunked_docs = chunk_document(doc)
46
+ all_chunked_docs.extend(chunked_docs)
47
+
48
+ for i, chunk_doc in enumerate(chunked_docs):
49
+ chunk_info.append({
50
+ 'document_id': chunk_doc.metadata.get('document_id', 'unknown'),
51
+ 'section_id': chunk_doc.metadata.get('section_id', 'unknown'),
52
+ 'chunk_id': i,
53
+ 'chunk_size': len(chunk_doc.text),
54
+ 'chunk_preview': chunk_doc.text[:200] + "..." if len(chunk_doc.text) > 200 else chunk_doc.text
55
+ })
56
+ else:
57
+ all_chunked_docs.append(doc)
58
+ chunk_info.append({
59
+ 'document_id': doc.metadata.get('document_id', 'unknown'),
60
+ 'section_id': doc.metadata.get('section_id', 'unknown'),
61
+ 'chunk_id': 0,
62
+ 'chunk_size': len(doc.text),
63
+ 'chunk_preview': doc.text[:200] + "..." if len(doc.text) > 200 else doc.text
64
+ })
65
+
66
+ return all_chunked_docs, chunk_info
67
+
68
  def extract_text_from_json(data, document_id, document_name):
69
  documents = []
70
 
 
221
  log_message(f"Ошибка обработки файла {file_path}: {str(e)}")
222
  continue
223
 
224
+ chunked_documents, chunk_info = process_documents_with_chunking(all_documents)
225
+
226
+ log_message(f"Всего создано {len(all_documents)} исходных документов")
227
+ log_message(f"После chunking получено {len(chunked_documents)} чанков")
228
+
229
+ return chunked_documents, chunk_info
230
 
231
  except Exception as e:
232
  log_message(f"Ошибка загрузки JSON документов: {str(e)}")
233
+ return [], []
234
 
235
 
236
  def extract_section_title(section_text):