MrSimple01 commited on
Commit
43fc13e
·
verified ·
1 Parent(s): 7329ea6

adding a new window for chunks

Browse files
Files changed (1) hide show
  1. app.py +273 -219
app.py CHANGED
@@ -1,220 +1,274 @@
1
- import gradio as gr
2
- import os
3
- from llama_index.core import Settings
4
- from documents_prep import load_json_documents, load_table_data, load_image_data, load_csv_chunks
5
- from utils import get_llm_model, get_embedding_model, get_reranker_model, answer_question
6
- from my_logging import log_message
7
- from index_retriever import create_vector_index, create_query_engine
8
- import sys
9
- from config import (
10
- HF_REPO_ID, HF_TOKEN, DOWNLOAD_DIR, CHUNKS_FILENAME,
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,
17
- use_json_instead_csv=False):
18
- try:
19
- log_message("Инициализация системы")
20
- os.makedirs(download_dir, exist_ok=True)
21
-
22
- embed_model = get_embedding_model()
23
- llm = get_llm_model(DEFAULT_MODEL)
24
- reranker = get_reranker_model()
25
-
26
- Settings.embed_model = embed_model
27
- Settings.llm = llm
28
-
29
- all_documents = []
30
- chunks_df = None
31
-
32
- if use_json_instead_csv and json_files_dir:
33
- log_message("Используем JSON файлы вместо CSV")
34
- json_documents = load_json_documents(repo_id, hf_token, json_files_dir, download_dir)
35
- all_documents.extend(json_documents)
36
- else:
37
- if chunks_filename:
38
- log_message("Загружаем данные из CSV")
39
- csv_documents, chunks_df = load_csv_chunks(repo_id, hf_token, chunks_filename, download_dir)
40
- all_documents.extend(csv_documents)
41
-
42
- if table_data_dir:
43
- log_message("Добавляю табличные данные")
44
- table_documents = load_table_data(repo_id, hf_token, table_data_dir)
45
- all_documents.extend(table_documents)
46
-
47
- if image_data_dir:
48
- log_message("Добавляю данные изображений")
49
- image_documents = load_image_data(repo_id, hf_token, image_data_dir)
50
- all_documents.extend(image_documents)
51
-
52
- log_message(f"Всего документов: {len(all_documents)}")
53
-
54
- vector_index = create_vector_index(all_documents)
55
- query_engine = create_query_engine(vector_index)
56
-
57
- log_message(f"Система успешно инициализирована")
58
- return query_engine, chunks_df, reranker, vector_index
59
-
60
- except Exception as e:
61
- log_message(f"Ошибка инициализации: {str(e)}")
62
- return None, None, None, None
63
-
64
- def switch_model(model_name, vector_index):
65
- from llama_index.core import Settings
66
- from index_retriever import create_query_engine
67
-
68
- try:
69
- log_message(f"Переключение на модель: {model_name}")
70
-
71
- new_llm = get_llm_model(model_name)
72
- Settings.llm = new_llm
73
-
74
- if vector_index is not None:
75
- new_query_engine = create_query_engine(vector_index)
76
- log_message(f"Модель успешно переключена на: {model_name}")
77
- return new_query_engine, f"✅ Модель переключена на: {model_name}"
78
- else:
79
- return None, "❌ Ошибка: система не инициализирована"
80
-
81
- except Exception as e:
82
- error_msg = f"Ошибка переключения модели: {str(e)}"
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("""
90
- # AIEXP - Artificial Intelligence Expert
91
-
92
- ## Инструмент для работы с нормативной документацией
93
- """)
94
-
95
- with gr.Tab("🏠 Поиск по нормативным документам"):
96
- gr.Markdown("### Задайте вопрос по нормативной документации")
97
-
98
- with gr.Row():
99
- with gr.Column(scale=2):
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="Статус модели",
111
- interactive=False
112
- )
113
-
114
- with gr.Row():
115
- with gr.Column(scale=3):
116
- question_input = gr.Textbox(
117
- label="Ваш вопрос к базе знаний",
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
- )
133
-
134
- with gr.Row():
135
- with gr.Column(scale=2):
136
- answer_output = gr.HTML(
137
- label="",
138
- value=f"<div style='background-color: #2d3748; color: white; padding: 20px; border-radius: 10px; text-align: center;'>Здесь появится ответ на ваш вопрос...<br><small>Текущая модель: {current_model}</small></div>",
139
- )
140
-
141
- with gr.Column(scale=1):
142
- sources_output = gr.HTML(
143
- label="",
144
- value="<div style='background-color: #2d3748; color: white; padding: 20px; border-radius: 10px; text-align: center;'>Здесь появятся источники...</div>",
145
- )
146
-
147
- switch_btn.click(
148
- fn=switch_model_func,
149
- inputs=[model_dropdown],
150
- outputs=[model_status]
151
- )
152
-
153
- ask_btn.click(
154
- fn=answer_question_func,
155
- inputs=[question_input],
156
- outputs=[answer_output, sources_output]
157
- )
158
-
159
- question_input.submit(
160
- fn=answer_question_func,
161
- inputs=[question_input],
162
- outputs=[answer_output, sources_output]
163
- )
164
-
165
- return demo
166
-
167
- query_engine = None
168
- chunks_df = None
169
- reranker = None
170
- vector_index = None
171
- current_model = DEFAULT_MODEL
172
-
173
- def main_answer_question(question):
174
- global query_engine, reranker, current_model, chunks_df
175
- return answer_question(question, query_engine, reranker, current_model, chunks_df)
176
-
177
- def main_switch_model(model_name):
178
- global query_engine, vector_index, current_model
179
-
180
- new_query_engine, status_message = switch_model(model_name, vector_index)
181
- if new_query_engine:
182
- query_engine = new_query_engine
183
- current_model = model_name
184
-
185
- return status_message
186
-
187
- def main():
188
- global query_engine, chunks_df, reranker, vector_index, current_model
189
-
190
- log_message("Запуск AIEXP - AI Expert для нормативной документации")
191
-
192
- query_engine, chunks_df, reranker, vector_index = initialize_system(
193
- repo_id=HF_REPO_ID,
194
- hf_token=HF_TOKEN,
195
- download_dir=DOWNLOAD_DIR,
196
- json_files_dir=JSON_FILES_DIR,
197
- table_data_dir=TABLE_DATA_DIR,
198
- image_data_dir=IMAGE_DATA_DIR,
199
- use_json_instead_csv=True,
200
- )
201
-
202
- if query_engine:
203
- log_message("Запуск веб-интерфейса")
204
- demo = create_demo_interface(
205
- answer_question_func=main_answer_question,
206
- switch_model_func=main_switch_model,
207
- current_model=current_model
208
- )
209
- demo.launch(
210
- server_name="0.0.0.0",
211
- server_port=7860,
212
- share=True,
213
- debug=False
214
- )
215
- else:
216
- log_message("Невозможно запустить приложение из-за ошибки иници��лизации")
217
- sys.exit(1)
218
-
219
- if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  main()
 
1
+ import gradio as gr
2
+ import os
3
+ from llama_index.core import Settings
4
+ from documents_prep import load_json_documents, load_table_data, load_image_data, load_csv_chunks
5
+ from utils import get_llm_model, get_embedding_model, get_reranker_model, answer_question
6
+ from my_logging import log_message
7
+ from index_retriever import create_vector_index, create_query_engine
8
+ import sys
9
+ from config import (
10
+ HF_REPO_ID, HF_TOKEN, DOWNLOAD_DIR, CHUNKS_FILENAME,
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; color: black;'>Нет данных о чанках</div>"
17
+
18
+ html = "<div style='max-height: 500px; overflow-y: auto; padding: 10px; color: black;'>"
19
+ html += f"<h4 style='color: black;'>Найдено релевантных чанков: {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; color: black;'>
25
+ <strong style='color: black;'>Документ:</strong> <span style='color: black;'>{chunk['document_id']}</span><br>
26
+ <strong style='color: black;'>Раздел:</strong> <span style='color: black;'>{chunk.get('section_id', 'unknown')}</span><br>
27
+ <strong style='color: black;'>Содержание:</strong><br>
28
+ <div style='background-color: white; padding: 8px; margin-top: 5px; border-radius: 3px; font-family: monospace; font-size: 12px; color: black; max-height: 200px; overflow-y: auto;'>
29
+ {chunk['chunk_text']}
30
+ </div>
31
+ </div>
32
+ """
33
+
34
+ html += "</div>"
35
+ return html
36
+
37
+ def initialize_system(repo_id, hf_token, download_dir, chunks_filename=None,
38
+ json_files_dir=None, table_data_dir=None, image_data_dir=None,
39
+ use_json_instead_csv=False):
40
+ try:
41
+ log_message("Инициализация системы")
42
+ os.makedirs(download_dir, exist_ok=True)
43
+
44
+ embed_model = get_embedding_model()
45
+ llm = get_llm_model(DEFAULT_MODEL)
46
+ reranker = get_reranker_model()
47
+
48
+ Settings.embed_model = embed_model
49
+ Settings.llm = llm
50
+
51
+ all_documents = []
52
+ chunks_df = None
53
+ chunk_info = []
54
+
55
+ if use_json_instead_csv and json_files_dir:
56
+ log_message("Используем JSON файлы вместо CSV")
57
+ json_documents, json_chunk_info = load_json_documents(repo_id, hf_token, json_files_dir, download_dir)
58
+ all_documents.extend(json_documents)
59
+ chunk_info.extend(json_chunk_info)
60
+ else:
61
+ if chunks_filename:
62
+ log_message("Загружаем данные из CSV")
63
+ csv_documents, chunks_df = load_csv_chunks(repo_id, hf_token, chunks_filename, download_dir)
64
+ all_documents.extend(csv_documents)
65
+
66
+ if table_data_dir:
67
+ log_message("Добавляю табличные данные")
68
+ table_documents = load_table_data(repo_id, hf_token, table_data_dir)
69
+ all_documents.extend(table_documents)
70
+
71
+ if image_data_dir:
72
+ log_message("Добавляю данные изображений")
73
+ image_documents = load_image_data(repo_id, hf_token, image_data_dir)
74
+ all_documents.extend(image_documents)
75
+
76
+ log_message(f"Всего документов: {len(all_documents)}")
77
+
78
+ vector_index = create_vector_index(all_documents)
79
+ query_engine = create_query_engine(vector_index)
80
+
81
+ log_message(f"Система успешно инициализирована")
82
+ return query_engine, chunks_df, reranker, vector_index, chunk_info
83
+
84
+ except Exception as e:
85
+ log_message(f"Ошибка инициализации: {str(e)}")
86
+ return None, None, None, None, []
87
+
88
+ def switch_model(model_name, vector_index):
89
+ from llama_index.core import Settings
90
+ from index_retriever import create_query_engine
91
+
92
+ try:
93
+ log_message(f"Переключение на модель: {model_name}")
94
+
95
+ new_llm = get_llm_model(model_name)
96
+ Settings.llm = new_llm
97
+
98
+ if vector_index is not None:
99
+ new_query_engine = create_query_engine(vector_index)
100
+ log_message(f"Модель успешно переключена на: {model_name}")
101
+ return new_query_engine, f"✅ Модель переключена на: {model_name}"
102
+ else:
103
+ return None, " Ошибка: система не инициализирована"
104
+
105
+ except Exception as e:
106
+ error_msg = f"Ошибка переключения модели: {str(e)}"
107
+ log_message(error_msg)
108
+ return None, f"❌ {error_msg}"
109
+
110
+ def main_answer_question(question):
111
+ global query_engine, reranker, current_model, chunks_df
112
+ if not question.strip():
113
+ return ("<div style='color: black;'>Пожалуйста, введите вопрос</div>",
114
+ "<div style='color: black;'>Источники появятся после обработки запроса</div>",
115
+ "<div style='color: black;'>Чанки появятся после обработки запроса</div>")
116
+
117
+ try:
118
+ # Call the answer_question function which returns 3 values
119
+ answer_html, sources_html, chunks_html = answer_question(question, query_engine, reranker, current_model, chunks_df)
120
+ return answer_html, sources_html, chunks_html
121
+
122
+ except Exception as e:
123
+ log_message(f"Ошибка при ответе на вопрос: {str(e)}")
124
+ return (f"<div style='color: red;'>Ошибка: {str(e)}</div>",
125
+ "<div style='color: black;'>Источники недоступны из-за ошибки</div>",
126
+ "<div style='color: black;'>Чанки недоступны из-за ошибки</div>")
127
+
128
+
129
+
130
+ def create_demo_interface(answer_question_func, switch_model_func, current_model, chunk_info=None):
131
+ with gr.Blocks(title="AIEXP - AI Expert для нормативной документации", theme=gr.themes.Soft()) as demo:
132
+
133
+ gr.Markdown("""
134
+ # AIEXP - Artificial Intelligence Expert
135
+
136
+ ## Инструмент для работы с нормативной документацией
137
+ """)
138
+
139
+ with gr.Tab("Поиск по нормативным документам"):
140
+ gr.Markdown("### Задайте вопрос по нормативной документации")
141
+
142
+ with gr.Row():
143
+ with gr.Column(scale=2):
144
+ model_dropdown = gr.Dropdown(
145
+ choices=list(AVAILABLE_MODELS.keys()),
146
+ value=current_model,
147
+ label="Выберите языковую модель",
148
+ info="Выберите модель для генерации ответов"
149
+ )
150
+ with gr.Column(scale=1):
151
+ switch_btn = gr.Button("Переключить модель", variant="secondary")
152
+ model_status = gr.Textbox(
153
+ value=f"Текущая модель: {current_model}",
154
+ label="Статус модели",
155
+ interactive=False
156
+ )
157
+
158
+ with gr.Row():
159
+ with gr.Column(scale=3):
160
+ question_input = gr.Textbox(
161
+ label="Ваш вопрос к базе знаний",
162
+ placeholder="Введите вопрос по нормативным документам...",
163
+ lines=3
164
+ )
165
+ ask_btn = gr.Button("Найти ответ", variant="primary", size="lg")
166
+
167
+ gr.Examples(
168
+ examples=[
169
+ чем этот рисунок: ГОСТ Р 50.04.07-2022 Приложение Л. Л.1.5 Рисунок Л.2",
170
+ "Л.9 Формула в ГОСТ Р 50.04.07 - 2022 что и о чем там?",
171
+ "Какой стандарт устанавливает порядок признания протоколов испытаний продукции в области использования атомной энергии?",
172
+ "Кто несет ответственность за организацию и проведение признания протоколов испытаний продукции?",
173
+ каких случаях могут быть признаны протоколы испытаний, проведенные лабораториями?",
174
+ ],
175
+ inputs=question_input
176
+ )
177
+
178
+ with gr.Row():
179
+ with gr.Column(scale=2):
180
+ answer_output = gr.HTML(
181
+ label="",
182
+ value=f"<div style='background-color: #2d3748; color: white; padding: 20px; border-radius: 10px; text-align: center;'>Здесь появится ответ на ваш вопрос...<br><small>Текущая модель: {current_model}</small></div>",
183
+ )
184
+
185
+ with gr.Column(scale=1):
186
+ sources_output = gr.HTML(
187
+ label="",
188
+ value="<div style='background-color: #2d3748; color: white; padding: 20px; border-radius: 10px; text-align: center;'>Здесь появятся релевантные чанки...</div>",
189
+ )
190
+
191
+ with gr.Column(scale=1):
192
+ chunks_output = gr.HTML(
193
+ label="Релевантные чанки",
194
+ value="<div style='background-color: #2d3748; color: white; padding: 20px; border-radius: 10px; text-align: center;'>Здесь появятся релевантные чанки...</div>",
195
+ )
196
+
197
+ switch_btn.click(
198
+ fn=switch_model_func,
199
+ inputs=[model_dropdown],
200
+ outputs=[model_status]
201
+ )
202
+
203
+ ask_btn.click(
204
+ fn=answer_question_func,
205
+ inputs=[question_input],
206
+ outputs=[answer_output, sources_output, chunks_output]
207
+ )
208
+
209
+ question_input.submit(
210
+ fn=answer_question_func,
211
+ inputs=[question_input],
212
+ outputs=[answer_output, sources_output, chunks_output]
213
+ )
214
+ return demo
215
+
216
+
217
+ query_engine = None
218
+ chunks_df = None
219
+ reranker = None
220
+ vector_index = None
221
+ current_model = DEFAULT_MODEL
222
+
223
+ def main_answer_question(question):
224
+ global query_engine, reranker, current_model, chunks_df
225
+ answer_html, sources_html, chunks_html = answer_question(
226
+ question, query_engine, reranker, current_model, chunks_df
227
+ )
228
+ return answer_html, sources_html, chunks_html
229
+
230
+ def main_switch_model(model_name):
231
+ global query_engine, vector_index, current_model
232
+
233
+ new_query_engine, status_message = switch_model(model_name, vector_index)
234
+ if new_query_engine:
235
+ query_engine = new_query_engine
236
+ current_model = model_name
237
+
238
+ return status_message
239
+
240
+ def main():
241
+ global query_engine, chunks_df, reranker, vector_index, current_model
242
+
243
+ log_message("Запуск AIEXP - AI Expert для нормативной документации")
244
+
245
+ query_engine, chunks_df, reranker, vector_index, chunk_info = initialize_system(
246
+ repo_id=HF_REPO_ID,
247
+ hf_token=HF_TOKEN,
248
+ download_dir=DOWNLOAD_DIR,
249
+ json_files_dir=JSON_FILES_DIR,
250
+ table_data_dir=TABLE_DATA_DIR,
251
+ image_data_dir=IMAGE_DATA_DIR,
252
+ use_json_instead_csv=True,
253
+ )
254
+
255
+ if query_engine:
256
+ log_message("Запуск веб-интерфейса")
257
+ demo = create_demo_interface(
258
+ answer_question_func=main_answer_question,
259
+ switch_model_func=main_switch_model,
260
+ current_model=current_model,
261
+ chunk_info=chunk_info
262
+ )
263
+ demo.launch(
264
+ server_name="0.0.0.0",
265
+ server_port=7860,
266
+ share=True,
267
+ debug=False
268
+ )
269
+ else:
270
+ log_message("Невозможно запустить приложение из-за ошибки инициализации")
271
+ sys.exit(1)
272
+
273
+ if __name__ == "__main__":
274
  main()