Spaces:
Sleeping
Sleeping
Commit
·
5e55e06
1
Parent(s):
bb892cb
dockerfile added
Browse files
scripts/__pycache__/config.cpython-311.pyc
CHANGED
Binary files a/scripts/__pycache__/config.cpython-311.pyc and b/scripts/__pycache__/config.cpython-311.pyc differ
|
|
scripts/__pycache__/rag_engine.cpython-311.pyc
CHANGED
Binary files a/scripts/__pycache__/rag_engine.cpython-311.pyc and b/scripts/__pycache__/rag_engine.cpython-311.pyc differ
|
|
scripts/config_1.py
ADDED
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import google.generativeai as genai
|
3 |
+
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
|
4 |
+
from llama_index.llms.google_genai import GoogleGenAI
|
5 |
+
from llama_index.core import Settings
|
6 |
+
from llama_index.core.llms import ChatMessage, MessageRole
|
7 |
+
import os
|
8 |
+
|
9 |
+
EMBEDDING_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
|
10 |
+
RETRIEVER_TOP_K = 10
|
11 |
+
RETRIEVER_SIMILARITY_CUTOFF = 0.7
|
12 |
+
RAG_FILES_DIR = "processed_data"
|
13 |
+
PROCESSED_DATA_FILE = "processed_data/processed_chunks.csv"
|
14 |
+
|
15 |
+
UPLOAD_FOLDER = "UPLOADED_DOCUMENTS"
|
16 |
+
PROCESSED_DATA_FILE = "processed_data/processed_chunks.csv"
|
17 |
+
INDEX_STATE_FILE = "processed_data/index_store.json"
|
18 |
+
RAG_FILES_DIR = "processed_data"
|
19 |
+
|
20 |
+
GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY', "AIzaSyDemsCp7JIdRNDRyP6DkYdMox1DLZwPcPE")
|
21 |
+
LLM_MODEL = "gemini-2.0-flash"
|
22 |
+
|
23 |
+
CHUNK_SIZE = 1024
|
24 |
+
CHUNK_OVERLAP = 256
|
25 |
+
MAX_CHUNK_SIZE = 2048
|
26 |
+
MIN_CHUNK_SIZE = 750
|
27 |
+
SIMILARITY_THRESHOLD = 0.7
|
28 |
+
|
29 |
+
RETRIEVER_TOP_K = 15
|
30 |
+
RETRIEVER_SIMILARITY_CUTOFF = 0.7
|
31 |
+
|
32 |
+
def setup_llm_settings():
|
33 |
+
# Set embedding model first
|
34 |
+
Settings.embed_model = HuggingFaceEmbedding(model_name=EMBEDDING_MODEL)
|
35 |
+
|
36 |
+
# Only set LLM if API key is available
|
37 |
+
if GOOGLE_API_KEY:
|
38 |
+
try:
|
39 |
+
llm = GoogleGenAI(model=LLM_MODEL, api_key=GOOGLE_API_KEY)
|
40 |
+
Settings.llm = llm
|
41 |
+
except Exception as e:
|
42 |
+
print(f"Warning: Could not initialize Google GenAI LLM: {e}")
|
43 |
+
Settings.llm = None
|
44 |
+
else:
|
45 |
+
print("Warning: GOOGLE_API_KEY not found. Setting LLM to None.")
|
46 |
+
Settings.llm = None
|
47 |
+
|
48 |
+
# Intent Classification Prompt for preprocessing
|
49 |
+
INTENT_CLASSIFIER_PROMPT = """Проанализируй запрос пользователя и определи, к какой из следующих категорий он относится:
|
50 |
+
|
51 |
+
1. SUMMARY - Запрос на краткое изложение, саммари пункта, раздела или документа
|
52 |
+
Примеры: "кратко расскажи о разделе 5", "саммари главы про безопасность", "что говорится в пункте 3.2"
|
53 |
+
|
54 |
+
2. SEARCH - Поиск конкретной информации, документа или пункта
|
55 |
+
Примеры: "где найти информацию о...", "какой документ регулирует...", "в каком пункте говорится про..."
|
56 |
+
|
57 |
+
3. VALIDATION - Проверка корректности данных, соответствия требованиям
|
58 |
+
Примеры: "правильно ли...", "соответствует ли требованиям...", "проверь корректность данных..."
|
59 |
+
|
60 |
+
4. ACTION_PLAN - Составление плана действий на основе документации
|
61 |
+
Примеры: "составь план...", "какие шаги нужно предпринять...", "алгоритм действий для..."
|
62 |
+
|
63 |
+
Запрос пользователя: {user_query}
|
64 |
+
|
65 |
+
Ответь ТОЛЬКО одним словом: SUMMARY, SEARCH, VALIDATION или ACTION_PLAN"""
|
66 |
+
|
67 |
+
# Task-specific prompts
|
68 |
+
SUMMARY_PROMPT = """Ты специализированный помощник по анализу нормативной документации (НД) для создания кратких изложений и саммари.
|
69 |
+
|
70 |
+
Твоя задача: Предоставить краткое, структурированное изложение запрашиваемой информации из нормативных документов.
|
71 |
+
|
72 |
+
Правила создания саммари:
|
73 |
+
1. Обязательное указание источника: Всегда указывай источник информации в формате:
|
74 |
+
- Для конкретного раздела/подраздела: Согласно разделу [X] и подразделу [X.X]: [Саммари]
|
75 |
+
- Для общих пунктов: Согласно [Название документа] - [Номер и наименование пункта]: [Саммари]
|
76 |
+
|
77 |
+
2. Структурированность: Организуй информацию логично:
|
78 |
+
- Основные положения
|
79 |
+
- Ключевые требования
|
80 |
+
- Важные исключения или особенности
|
81 |
+
|
82 |
+
3. Краткость и полнота: Включи все существенные моменты, но избегай избыточных деталей
|
83 |
+
|
84 |
+
4. Сохранение терминологии НД: Используй точную терминологию из документов
|
85 |
+
|
86 |
+
5. Если информация отсутствует: Информация для создания саммари по вашему запросу не найдена в нормативной документации.
|
87 |
+
|
88 |
+
Контекст: {context_str}
|
89 |
+
|
90 |
+
Запрос: {query_str}
|
91 |
+
|
92 |
+
Саммари:"""
|
93 |
+
|
94 |
+
SEARCH_PROMPT = """Ты специализированный помощник по поиску информации в нормативной документации (НД).
|
95 |
+
|
96 |
+
Твоя задача: Найти и предоставить точную информацию, документы или пункты согласно запросу пользователя.
|
97 |
+
|
98 |
+
Правила поиска информации:
|
99 |
+
1. Точное указание источника: Обязательно укажи точное местоположение информации:
|
100 |
+
- Для конкретного раздела/подраздела: Согласно разделу [X] и подразделу [X.X]: [Найденная информация]
|
101 |
+
- Для общих пунктов: Согласно [Название документа] - [Номер и наименование пункта]: [Найденная информация]
|
102 |
+
|
103 |
+
2. Релевантность: Предоставляй именно ту информацию, которая отвечает на запрос
|
104 |
+
|
105 |
+
3. Полнота ответа: Если найдено несколько релевантных источников, укажи все
|
106 |
+
|
107 |
+
4. Точность цитирования: Используй формулировки непосредственно из НД
|
108 |
+
|
109 |
+
5. Если информация не найдена: Информация по вашему запросу не была найдена в нормативной документации.
|
110 |
+
|
111 |
+
Контекст: {context_str}
|
112 |
+
|
113 |
+
Поисковый запрос: {query_str}
|
114 |
+
|
115 |
+
Результат поиска:"""
|
116 |
+
|
117 |
+
VALIDATION_PROMPT = """Ты специализированный помощник по проверке соответствия требованиям нормативной документации (НД).
|
118 |
+
|
119 |
+
Твоя задача: Проанализировать предоставленные данные или информацию на соответствие требованиям НД и дать заключение о корректности.
|
120 |
+
|
121 |
+
Правила проведения проверки:
|
122 |
+
1. Источник требований: Четко укажи, согласно каким пунктам НД проводится проверка:
|
123 |
+
- Согласно разделу [X] и подразделу [X.X]: [Требование]
|
124 |
+
- Согласно [Название документа] - [Номер и наименование пункта]: [Требование]
|
125 |
+
|
126 |
+
2. Структура заключения:
|
127 |
+
- СООТВЕТСТВУЕТ/НЕ СООТВЕТСТВУЕТ требованиям
|
128 |
+
- Обоснование заключения со ссылками на конкретные пункты НД
|
129 |
+
- При несоответствии - указание на конкретные нарушения
|
130 |
+
- Рекомендации по устранению несоответствий (если применимо)
|
131 |
+
|
132 |
+
3. Объективность: Основывайся исключительно на требованиях НД, без субъективных оценок
|
133 |
+
|
134 |
+
4. Если требования не найдены: Требования для проверки данной информации не найдены в нормативной документации.
|
135 |
+
|
136 |
+
Контекст: {context_str}
|
137 |
+
|
138 |
+
Запрос на проверку: {query_str}
|
139 |
+
|
140 |
+
Заключение о соответствии:"""
|
141 |
+
|
142 |
+
ACTION_PLAN_PROMPT = """Ты специализированный помощник по составлению планов действий на основе нормативной документации (НД).
|
143 |
+
|
144 |
+
Твоя задача: Создать пошаговый план действий, основанный на требованиях и процедурах, описанных в НД.
|
145 |
+
|
146 |
+
Правила составления плана действий:
|
147 |
+
1. Источник каждого шага: Для каждого шага указывай источник в НД:
|
148 |
+
- Согласно разделу [X] и подразделу [X.X]: Шаг [N]
|
149 |
+
- Согласно [Название документа] - [Номер и наименование пункта]: Шаг [N]
|
150 |
+
|
151 |
+
2. Структура плана:
|
152 |
+
- Нумерованные шаги в логической последовательности
|
153 |
+
- Четкие действия для каждого шага
|
154 |
+
- Указание ответственных лиц/органов (если указано в НД)
|
155 |
+
- Временные рамки (если указаны в НД)
|
156 |
+
- Необходимые документы/материалы
|
157 |
+
|
158 |
+
3. Практичность: План должен быть выполнимым и соответствовать реальным процедурам
|
159 |
+
|
160 |
+
4. Полнота: Включи все обязательные этапы согласно НД
|
161 |
+
|
162 |
+
5. Если информация недостаточна: Недо��таточно информации в нормативной документации для составления полного плана действий по вашему запросу.
|
163 |
+
|
164 |
+
Контекст: {context_str}
|
165 |
+
|
166 |
+
Запрос на план: {query_str}
|
167 |
+
|
168 |
+
План действий:"""
|
169 |
+
|
170 |
+
# Dictionary mapping intents to prompts
|
171 |
+
TASK_PROMPTS = {
|
172 |
+
"SUMMARY": SUMMARY_PROMPT,
|
173 |
+
"SEARCH": SEARCH_PROMPT,
|
174 |
+
"VALIDATION": VALIDATION_PROMPT,
|
175 |
+
"ACTION_PLAN": ACTION_PLAN_PROMPT
|
176 |
+
}
|
177 |
+
|
178 |
+
LLM_MODEL_PREPROCESS = "gemini-1.5-flash"
|
179 |
+
|
180 |
+
def classify_intent(user_query, llm=None):
|
181 |
+
"""Classify user intent to determine appropriate prompt"""
|
182 |
+
if not llm:
|
183 |
+
llm = GoogleGenAI(model=LLM_MODEL_PREPROCESS, temperature=0.1)
|
184 |
+
|
185 |
+
try:
|
186 |
+
intent_prompt = INTENT_CLASSIFIER_PROMPT.format(user_query=user_query)
|
187 |
+
messages = [ChatMessage(role=MessageRole.USER, content=intent_prompt)]
|
188 |
+
response = llm.chat(messages)
|
189 |
+
intent = response.message.content.strip()
|
190 |
+
|
191 |
+
# Validate intent and return default if invalid
|
192 |
+
if intent in TASK_PROMPTS:
|
193 |
+
return intent
|
194 |
+
else:
|
195 |
+
print(f"Unknown intent: {intent}, defaulting to SEARCH")
|
196 |
+
return "SEARCH"
|
197 |
+
except Exception as e:
|
198 |
+
print(f"Intent classification failed: {e}, defaulting to SEARCH")
|
199 |
+
return "SEARCH"
|
200 |
+
|
201 |
+
def get_task_specific_prompt(intent, context_str, query_str):
|
202 |
+
"""Get the appropriate prompt template based on intent"""
|
203 |
+
prompt_template = TASK_PROMPTS.get(intent, SEARCH_PROMPT)
|
204 |
+
return prompt_template.format(context_str=context_str, query_str=query_str)
|
205 |
+
|
206 |
+
def preprocess_query_with_context(user_query, chat_history=None, llm=None):
|
207 |
+
if not chat_history:
|
208 |
+
return user_query
|
209 |
+
|
210 |
+
if not llm:
|
211 |
+
llm = GoogleGenAI(model=LLM_MODEL_PREPROCESS, temperature=0.1)
|
212 |
+
|
213 |
+
# Format chat history into a string for the prompt
|
214 |
+
history_context = "\n".join([
|
215 |
+
f"User: {item['user']}\nAssistant: {item['assistant']}"
|
216 |
+
for item in chat_history[-3:] # Consider only the last 3 exchanges for conciseness
|
217 |
+
])
|
218 |
+
|
219 |
+
preprocessing_prompt = f"""Analyze the user's current question in the context of their chat history and improve it for better document retrieval.
|
220 |
+
|
221 |
+
Chat History:
|
222 |
+
{history_context}
|
223 |
+
|
224 |
+
Current Question: {user_query}
|
225 |
+
|
226 |
+
Tasks:
|
227 |
+
1. If the question refers to previous context, make it self-contained.
|
228 |
+
2. Add relevant keywords that would help find documents.
|
229 |
+
3. Maintain the legal/regulatory focus.
|
230 |
+
4. Keep it concise but specific.
|
231 |
+
|
232 |
+
Return ONLY the improved question:"""
|
233 |
+
|
234 |
+
try:
|
235 |
+
messages = [ChatMessage(role=MessageRole.USER, content=preprocessing_prompt)]
|
236 |
+
response = llm.chat(messages)
|
237 |
+
improved_query = response.message.content.strip()
|
238 |
+
|
239 |
+
# Fallback to the original query if the preprocessing fails or provides an overly long response
|
240 |
+
if len(improved_query) > len(user_query) * 3 or not improved_query:
|
241 |
+
return user_query
|
242 |
+
|
243 |
+
return improved_query
|
244 |
+
except Exception as e:
|
245 |
+
print(f"Query preprocessing failed: {e}")
|
246 |
+
return user_query
|
247 |
+
|
248 |
+
def create_chat_context_prompt(base_response, chat_history=None):
|
249 |
+
if not chat_history:
|
250 |
+
return base_response
|
251 |
+
|
252 |
+
base_aware_response = base_response
|
253 |
+
|
254 |
+
if len(chat_history) > 0:
|
255 |
+
last_exchange = chat_history[-1]
|
256 |
+
if any(keyword in last_exchange['user'].lower() for keyword in ['закон', 'кодекс', 'статья']):
|
257 |
+
# Add a conversational prefix
|
258 |
+
base_aware_response = f"Продолжая тему нормативных документов: {base_response}"
|
259 |
+
|
260 |
+
return base_aware_response
|
261 |
+
|
262 |
+
# Example usage function
|
263 |
+
def process_user_query(user_query, context_str, chat_history=None):
|
264 |
+
# Step 1: Classify intent
|
265 |
+
intent = classify_intent(user_query)
|
266 |
+
print(f"Detected intent: {intent}")
|
267 |
+
|
268 |
+
# Step 2: Preprocess query if needed
|
269 |
+
processed_query = preprocess_query_with_context(user_query, chat_history)
|
270 |
+
|
271 |
+
# Step 3: Get appropriate prompt
|
272 |
+
task_prompt = get_task_specific_prompt(intent, context_str, processed_query)
|
273 |
+
|
274 |
+
return task_prompt, intent
|