Rulga commited on
Commit
9949f77
·
1 Parent(s): 80e6314

fix english 1

Browse files
Files changed (2) hide show
  1. app.py +49 -49
  2. src/knowledge_base/dataset.py +30 -30
app.py CHANGED
@@ -14,26 +14,26 @@ client = InferenceClient(
14
  token=HF_TOKEN
15
  )
16
 
17
- # Состояние для хранения контекста
18
  context_store = {}
19
 
20
  def get_context(message, conversation_id):
21
- """Получение контекста из базы знаний"""
22
  vector_store = load_vector_store()
23
  if vector_store is None:
24
- return "База знаний не найдена. Пожалуйста, создайте её сначала."
25
 
26
  try:
27
- # Извлечение контекста
28
  context_docs = vector_store.similarity_search(message, k=3)
29
- context_text = "\n\n".join([f"Из {doc.metadata.get('source', 'неизвестно')}: {doc.page_content}" for doc in context_docs])
30
 
31
- # Сохраняем контекст для этого разговора
32
  context_store[conversation_id] = context_text
33
 
34
  return context_text
35
  except Exception as e:
36
- print(f"Ошибка при получении контекста: {str(e)}")
37
  return ""
38
 
39
  def respond(
@@ -45,30 +45,30 @@ def respond(
45
  temperature,
46
  top_p,
47
  ):
48
- # Если это новый разговор, создаем ID
49
  if not conversation_id:
50
  import uuid
51
  conversation_id = str(uuid.uuid4())
52
 
53
- # Получаем контекст из базы знаний
54
  context = get_context(message, conversation_id)
55
 
56
- # Преобразуем историю из формата Gradio в формат OpenAI
57
  messages = [{"role": "system", "content": system_message}]
58
  if context:
59
- messages[0]["content"] += f"\n\nКонтекст для ответа:\n{context}"
60
 
61
- # Конвертируем историю в формат OpenAI
62
  for user_msg, assistant_msg in history:
63
  messages.extend([
64
  {"role": "user", "content": user_msg},
65
  {"role": "assistant", "content": assistant_msg}
66
  ])
67
 
68
- # Добавляем текущее сообщение пользователя
69
  messages.append({"role": "user", "content": message})
70
 
71
- # Отправляем запрос к API и стримим ответ
72
  response = ""
73
  is_complete = False
74
 
@@ -80,7 +80,7 @@ def respond(
80
  temperature=temperature,
81
  top_p=top_p,
82
  ):
83
- # Проверяем наличие finish_reason в chunk
84
  if hasattr(chunk.choices[0], 'finish_reason') and chunk.choices[0].finish_reason is not None:
85
  is_complete = True
86
  break
@@ -90,8 +90,8 @@ def respond(
90
  response += token
91
  yield [(message, response)], conversation_id
92
 
93
- # Если ответ завершен, сохраняем историю
94
- if is_complete or response: # добавляем проверку на наличие ответа как запасной вариант
95
  messages.append({"role": "assistant", "content": response})
96
  try:
97
  from src.knowledge_base.dataset import DatasetManager
@@ -108,32 +108,32 @@ def respond(
108
  print(traceback.format_exc()) # Print full traceback for debugging
109
 
110
  except Exception as e:
111
- print(f"Ошибка при генерации ответа: {str(e)}")
112
- yield [(message, "Произошла ошибка при генерации ответа.")], conversation_id
113
 
114
  def build_kb():
115
- """Функция для создания базы знаний"""
116
  try:
117
  success, message = create_vector_store()
118
  return message
119
  except Exception as e:
120
- return f"Ошибка при создании базы знаний: {str(e)}"
121
 
122
  def load_vector_store():
123
- """Загрузка базы знаний из датасета"""
124
  try:
125
  from src.knowledge_base.dataset import DatasetManager
126
  dataset = DatasetManager()
127
  success, store = dataset.download_vector_store()
128
  if success:
129
  return store
130
- print(f"Ошибка загрузки базы знаний: {store}")
131
  return None
132
  except Exception as e:
133
- print(f"Ошибка при загрузке базы знаний: {str(e)}")
134
  return None
135
 
136
- # Создаем интерфейс
137
  with gr.Blocks() as demo:
138
  gr.Markdown("# 🤖 Status Law Assistant")
139
 
@@ -142,40 +142,40 @@ with gr.Blocks() as demo:
142
  with gr.Row():
143
  with gr.Column(scale=3):
144
  chatbot = gr.Chatbot(
145
- label="Чат",
146
  bubble_full_width=False,
147
- avatar_images=["user.png", "assistant.png"] # опционально
148
  )
149
 
150
  with gr.Row():
151
  msg = gr.Textbox(
152
- label="Ваш вопрос",
153
- placeholder="Введите ваш вопрос...",
154
  scale=4
155
  )
156
- submit_btn = gr.Button("Отправить", variant="primary")
157
 
158
  with gr.Column(scale=1):
159
- gr.Markdown("### Управление базой знаний")
160
- build_kb_btn = gr.Button("Создать/обновить базу знаний", variant="primary")
161
- kb_status = gr.Textbox(label="Статус базы знаний", interactive=False)
162
 
163
- gr.Markdown("### Настройки генерации")
164
  max_tokens = gr.Slider(
165
  minimum=1,
166
  maximum=2048,
167
  value=512,
168
  step=1,
169
- label="Максимальная длина ответа",
170
- info="Ограничивает количество токенов в ответе. Больше токенов = длиннее ответ"
171
  )
172
  temperature = gr.Slider(
173
  minimum=0.1,
174
  maximum=2.0,
175
  value=0.7,
176
  step=0.1,
177
- label="Температура",
178
- info="Контролирует креативность. Ниже значение = более предсказуемые ответы"
179
  )
180
  top_p = gr.Slider(
181
  minimum=0.1,
@@ -183,10 +183,10 @@ with gr.Blocks() as demo:
183
  value=0.95,
184
  step=0.05,
185
  label="Top-p",
186
- info="Контролирует разнообразие. Ниже значение = более сфокусированные ответы"
187
  )
188
 
189
- clear_btn = gr.Button("Очистить историю чата")
190
 
191
  def respond_and_clear(
192
  message,
@@ -196,7 +196,7 @@ with gr.Blocks() as demo:
196
  temperature,
197
  top_p,
198
  ):
199
- # Используем существующую функцию respond
200
  response_generator = respond(
201
  message,
202
  history,
@@ -207,28 +207,28 @@ with gr.Blocks() as demo:
207
  top_p,
208
  )
209
 
210
- # Возвращаем результат и пустую строку для очистки поля ввода
211
  for response in response_generator:
212
- yield response[0], response[1], "" # chatbot, conversation_id, пустая строка для msg
213
 
214
- # Обработчики событий
215
  msg.submit(
216
  respond_and_clear,
217
  [msg, chatbot, conversation_id, max_tokens, temperature, top_p],
218
- [chatbot, conversation_id, msg] # Добавляем msg в выходные параметры
219
  )
220
  submit_btn.click(
221
  respond_and_clear,
222
  [msg, chatbot, conversation_id, max_tokens, temperature, top_p],
223
- [chatbot, conversation_id, msg] # Добавляем msg в выходные параметры
224
  )
225
  build_kb_btn.click(build_kb, None, kb_status)
226
  clear_btn.click(lambda: ([], None), None, [chatbot, conversation_id])
227
 
228
- # Запускаем приложение
229
  if __name__ == "__main__":
230
- # Проверяем доступность базы знаний в датасете
231
  if not load_vector_store():
232
- print("База знаний не найдена. Создайте её через интерфейс.")
233
 
234
  demo.launch()
 
14
  token=HF_TOKEN
15
  )
16
 
17
+ # State for storing context
18
  context_store = {}
19
 
20
  def get_context(message, conversation_id):
21
+ """Get context from knowledge base"""
22
  vector_store = load_vector_store()
23
  if vector_store is None:
24
+ return "Knowledge base not found. Please create it first."
25
 
26
  try:
27
+ # Extract context
28
  context_docs = vector_store.similarity_search(message, k=3)
29
+ context_text = "\n\n".join([f"From {doc.metadata.get('source', 'unknown')}: {doc.page_content}" for doc in context_docs])
30
 
31
+ # Save context for this conversation
32
  context_store[conversation_id] = context_text
33
 
34
  return context_text
35
  except Exception as e:
36
+ print(f"Error getting context: {str(e)}")
37
  return ""
38
 
39
  def respond(
 
45
  temperature,
46
  top_p,
47
  ):
48
+ # Create ID for new conversation
49
  if not conversation_id:
50
  import uuid
51
  conversation_id = str(uuid.uuid4())
52
 
53
+ # Get context from knowledge base
54
  context = get_context(message, conversation_id)
55
 
56
+ # Convert history from Gradio format to OpenAI format
57
  messages = [{"role": "system", "content": system_message}]
58
  if context:
59
+ messages[0]["content"] += f"\n\nContext for response:\n{context}"
60
 
61
+ # Convert history to OpenAI format
62
  for user_msg, assistant_msg in history:
63
  messages.extend([
64
  {"role": "user", "content": user_msg},
65
  {"role": "assistant", "content": assistant_msg}
66
  ])
67
 
68
+ # Add current user message
69
  messages.append({"role": "user", "content": message})
70
 
71
+ # Send API request and stream response
72
  response = ""
73
  is_complete = False
74
 
 
80
  temperature=temperature,
81
  top_p=top_p,
82
  ):
83
+ # Check for finish_reason in chunk
84
  if hasattr(chunk.choices[0], 'finish_reason') and chunk.choices[0].finish_reason is not None:
85
  is_complete = True
86
  break
 
90
  response += token
91
  yield [(message, response)], conversation_id
92
 
93
+ # Save history if response is complete
94
+ if is_complete or response: # add response check as fallback
95
  messages.append({"role": "assistant", "content": response})
96
  try:
97
  from src.knowledge_base.dataset import DatasetManager
 
108
  print(traceback.format_exc()) # Print full traceback for debugging
109
 
110
  except Exception as e:
111
+ print(f"Error generating response: {str(e)}")
112
+ yield [(message, "An error occurred while generating the response.")], conversation_id
113
 
114
  def build_kb():
115
+ """Function to create knowledge base"""
116
  try:
117
  success, message = create_vector_store()
118
  return message
119
  except Exception as e:
120
+ return f"Error creating knowledge base: {str(e)}"
121
 
122
  def load_vector_store():
123
+ """Load knowledge base from dataset"""
124
  try:
125
  from src.knowledge_base.dataset import DatasetManager
126
  dataset = DatasetManager()
127
  success, store = dataset.download_vector_store()
128
  if success:
129
  return store
130
+ print(f"Error loading knowledge base: {store}")
131
  return None
132
  except Exception as e:
133
+ print(f"Error loading knowledge base: {str(e)}")
134
  return None
135
 
136
+ # Create interface
137
  with gr.Blocks() as demo:
138
  gr.Markdown("# 🤖 Status Law Assistant")
139
 
 
142
  with gr.Row():
143
  with gr.Column(scale=3):
144
  chatbot = gr.Chatbot(
145
+ label="Chat",
146
  bubble_full_width=False,
147
+ avatar_images=["user.png", "assistant.png"] # optional
148
  )
149
 
150
  with gr.Row():
151
  msg = gr.Textbox(
152
+ label="Your question",
153
+ placeholder="Enter your question...",
154
  scale=4
155
  )
156
+ submit_btn = gr.Button("Send", variant="primary")
157
 
158
  with gr.Column(scale=1):
159
+ gr.Markdown("### Knowledge Base Management")
160
+ build_kb_btn = gr.Button("Create/Update Knowledge Base", variant="primary")
161
+ kb_status = gr.Textbox(label="Knowledge Base Status", interactive=False)
162
 
163
+ gr.Markdown("### Generation Settings")
164
  max_tokens = gr.Slider(
165
  minimum=1,
166
  maximum=2048,
167
  value=512,
168
  step=1,
169
+ label="Maximum Response Length",
170
+ info="Limits the number of tokens in response. More tokens = longer response"
171
  )
172
  temperature = gr.Slider(
173
  minimum=0.1,
174
  maximum=2.0,
175
  value=0.7,
176
  step=0.1,
177
+ label="Temperature",
178
+ info="Controls creativity. Lower value = more predictable responses"
179
  )
180
  top_p = gr.Slider(
181
  minimum=0.1,
 
183
  value=0.95,
184
  step=0.05,
185
  label="Top-p",
186
+ info="Controls diversity. Lower value = more focused responses"
187
  )
188
 
189
+ clear_btn = gr.Button("Clear Chat History")
190
 
191
  def respond_and_clear(
192
  message,
 
196
  temperature,
197
  top_p,
198
  ):
199
+ # Use existing respond function
200
  response_generator = respond(
201
  message,
202
  history,
 
207
  top_p,
208
  )
209
 
210
+ # Return result and empty string to clear input field
211
  for response in response_generator:
212
+ yield response[0], response[1], "" # chatbot, conversation_id, empty string for msg
213
 
214
+ # Event handlers
215
  msg.submit(
216
  respond_and_clear,
217
  [msg, chatbot, conversation_id, max_tokens, temperature, top_p],
218
+ [chatbot, conversation_id, msg] # Add msg to output parameters
219
  )
220
  submit_btn.click(
221
  respond_and_clear,
222
  [msg, chatbot, conversation_id, max_tokens, temperature, top_p],
223
+ [chatbot, conversation_id, msg] # Add msg to output parameters
224
  )
225
  build_kb_btn.click(build_kb, None, kb_status)
226
  clear_btn.click(lambda: ([], None), None, [chatbot, conversation_id])
227
 
228
+ # Launch application
229
  if __name__ == "__main__":
230
+ # Check knowledge base availability in dataset
231
  if not load_vector_store():
232
+ print("Knowledge base not found. Please create it through the interface.")
233
 
234
  demo.launch()
src/knowledge_base/dataset.py CHANGED
@@ -292,40 +292,40 @@ class DatasetManager:
292
  if os.path.exists(temp_name):
293
  os.unlink(temp_name)
294
 
295
- print(f"Successfully saved chat history: {filename}") # Добавляем лог для отладки
296
  return True, f"Chat history saved successfully as {filename}"
297
 
298
  except Exception as e:
299
- print(f"Error in save_chat_history: {str(e)}") # Добавляем лог для отладки
300
  return False, f"Failed to save chat history: {str(e)}"
301
 
302
  def get_chat_history(self, conversation_id: Optional[str] = None) -> Tuple[bool, Any]:
303
  """
304
- Получение истории чатов из датасета
305
 
306
  Args:
307
- conversation_id: Идентификатор беседы (если None, возвращает все чаты)
308
 
309
  Returns:
310
- (успех, история чатов или сообщение об ошибке)
311
  """
312
  try:
313
- # Получаем список файлов в директории chat_history
314
  files = self.api.list_repo_files(
315
  repo_id=self.dataset_name,
316
  repo_type="dataset",
317
  path="chat_history"
318
  )
319
 
320
- # Фильтруем файлы по conversation_id, если он указан
321
  if conversation_id:
322
  files = [f for f in files if f.startswith(f"chat_history/{conversation_id}_")]
323
 
324
- # Если файлов нет, возвращаем пустой список
325
  if not files or all(f.endswith(".gitkeep") for f in files):
326
  return True, []
327
 
328
- # Создаем временную директорию для загрузки файлов
329
  with tempfile.TemporaryDirectory() as temp_dir:
330
  chat_histories = []
331
 
@@ -333,7 +333,7 @@ class DatasetManager:
333
  if file.endswith(".gitkeep"):
334
  continue
335
 
336
- # Загружаем файл
337
  local_file = self.api.hf_hub_download(
338
  repo_id=self.dataset_name,
339
  filename=file,
@@ -341,42 +341,42 @@ class DatasetManager:
341
  local_dir=temp_dir
342
  )
343
 
344
- # Читаем содержимое файла
345
  with open(local_file, "r", encoding="utf-8") as f:
346
  chat_data = json.load(f)
347
  chat_histories.append(chat_data)
348
 
349
- # Сортируем по временной метке
350
  chat_histories.sort(key=lambda x: x.get("timestamp", ""), reverse=True)
351
 
352
  return True, chat_histories
353
  except Exception as e:
354
- return False, f"Ошибка при получении истории чатов: {str(e)}"
355
 
356
  def upload_document(self, file_path: str, document_id: Optional[str] = None) -> Tuple[bool, str]:
357
  """
358
- Загрузка документа в датасет
359
 
360
  Args:
361
- file_path: Путь к файлу документа
362
- document_id: Идентификатор документа (если None, используется имя файла)
363
 
364
  Returns:
365
- (успех, сообщение)
366
  """
367
  try:
368
  if not os.path.exists(file_path):
369
- return False, f"Файл не найден: {file_path}"
370
 
371
- # Если document_id не указан, используем имя файла
372
  if document_id is None:
373
  document_id = os.path.basename(file_path)
374
 
375
- # Добавляем в��еменную метку к имени файла
376
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
377
  filename = f"documents/{document_id}_{timestamp}{os.path.splitext(file_path)[1]}"
378
 
379
- # Загружаем файл
380
  self.api.upload_file(
381
  path_or_fileobj=file_path,
382
  path_in_repo=filename,
@@ -384,19 +384,19 @@ class DatasetManager:
384
  repo_type="dataset"
385
  )
386
 
387
- return True, f"Документ успешно загружен: {filename}"
388
  except Exception as e:
389
- return False, f"Ошибка при загрузке документа: {str(e)}"
390
 
391
  def test_dataset_connection(token: Optional[str] = None) -> Tuple[bool, str]:
392
  """
393
- Тестовая функция для проверки подключения к датасету
394
 
395
  Args:
396
- token: Токен доступа к Hugging Face Hub
397
 
398
  Returns:
399
- (успех, сообщение)
400
  """
401
  try:
402
  manager = DatasetManager(token=token)
@@ -405,13 +405,13 @@ def test_dataset_connection(token: Optional[str] = None) -> Tuple[bool, str]:
405
  if not success:
406
  return False, message
407
 
408
- print(f"Тест инициализации: {message}")
409
 
410
- return True, "Подключение к датасету работает"
411
  except Exception as e:
412
- return False, f"Ошибка подключения к датасету: {str(e)}"
413
 
414
  if __name__ == "__main__":
415
- # Тестируем подключение
416
  success, message = test_dataset_connection()
417
  print(message)
 
292
  if os.path.exists(temp_name):
293
  os.unlink(temp_name)
294
 
295
+ print(f"Successfully saved chat history: {filename}") # Adding a log for debugging
296
  return True, f"Chat history saved successfully as {filename}"
297
 
298
  except Exception as e:
299
+ print(f"Error in save_chat_history: {str(e)}") # Adding a log for debugging
300
  return False, f"Failed to save chat history: {str(e)}"
301
 
302
  def get_chat_history(self, conversation_id: Optional[str] = None) -> Tuple[bool, Any]:
303
  """
304
+ Get chat history from the dataset
305
 
306
  Args:
307
+ conversation_id: Conversation identifier (if None, returns all chats)
308
 
309
  Returns:
310
+ (success, chat history or error message)
311
  """
312
  try:
313
+ # Get list of files in chat_history directory
314
  files = self.api.list_repo_files(
315
  repo_id=self.dataset_name,
316
  repo_type="dataset",
317
  path="chat_history"
318
  )
319
 
320
+ # Filter files by conversation_id if specified
321
  if conversation_id:
322
  files = [f for f in files if f.startswith(f"chat_history/{conversation_id}_")]
323
 
324
+ # If no files found, return empty list
325
  if not files or all(f.endswith(".gitkeep") for f in files):
326
  return True, []
327
 
328
+ # Create temporary directory for downloading files
329
  with tempfile.TemporaryDirectory() as temp_dir:
330
  chat_histories = []
331
 
 
333
  if file.endswith(".gitkeep"):
334
  continue
335
 
336
+ # Download file
337
  local_file = self.api.hf_hub_download(
338
  repo_id=self.dataset_name,
339
  filename=file,
 
341
  local_dir=temp_dir
342
  )
343
 
344
+ # Read file content
345
  with open(local_file, "r", encoding="utf-8") as f:
346
  chat_data = json.load(f)
347
  chat_histories.append(chat_data)
348
 
349
+ # Sort by timestamp
350
  chat_histories.sort(key=lambda x: x.get("timestamp", ""), reverse=True)
351
 
352
  return True, chat_histories
353
  except Exception as e:
354
+ return False, f"Error getting chat history: {str(e)}"
355
 
356
  def upload_document(self, file_path: str, document_id: Optional[str] = None) -> Tuple[bool, str]:
357
  """
358
+ Upload document to the dataset
359
 
360
  Args:
361
+ file_path: Path to the document file
362
+ document_id: Document identifier (if None, uses filename)
363
 
364
  Returns:
365
+ (success, message)
366
  """
367
  try:
368
  if not os.path.exists(file_path):
369
+ return False, f"File not found: {file_path}"
370
 
371
+ # Use filename as document_id if not specified
372
  if document_id is None:
373
  document_id = os.path.basename(file_path)
374
 
375
+ # Add timestamp to filename
376
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
377
  filename = f"documents/{document_id}_{timestamp}{os.path.splitext(file_path)[1]}"
378
 
379
+ # Upload file
380
  self.api.upload_file(
381
  path_or_fileobj=file_path,
382
  path_in_repo=filename,
 
384
  repo_type="dataset"
385
  )
386
 
387
+ return True, f"Document uploaded successfully: {filename}"
388
  except Exception as e:
389
+ return False, f"Error uploading document: {str(e)}"
390
 
391
  def test_dataset_connection(token: Optional[str] = None) -> Tuple[bool, str]:
392
  """
393
+ Test function to check dataset connection
394
 
395
  Args:
396
+ token: Hugging Face Hub access token
397
 
398
  Returns:
399
+ (success, message)
400
  """
401
  try:
402
  manager = DatasetManager(token=token)
 
405
  if not success:
406
  return False, message
407
 
408
+ print(f"Initialization test: {message}")
409
 
410
+ return True, "Dataset connection is working"
411
  except Exception as e:
412
+ return False, f"Dataset connection error: {str(e)}"
413
 
414
  if __name__ == "__main__":
415
+ # Test connection
416
  success, message = test_dataset_connection()
417
  print(message)