From 5c8c09720c0ff61ea7ec03d864df5c0c97df898a Mon Sep 17 00:00:00 2001 From: "ki.sagidullin" Date: Wed, 1 Apr 2026 09:15:29 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B8=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=85=D1=80=D0=B0=D0=BD=D1=8F=D1=82=D1=81=D1=8F=20=D0=BE=D1=82?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agentic_rag_interface.py | 62 +++++++++++++++++++++++++++++++++------- local_knowledge_base.py | 33 +++++++++++++++++++-- 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/agentic_rag_interface.py b/agentic_rag_interface.py index 03b60d5..02862e6 100644 --- a/agentic_rag_interface.py +++ b/agentic_rag_interface.py @@ -65,8 +65,11 @@ class AgenticRAGInterface: self.conversation_history = [] return "История очищена", "" - def index_documents(self, folder_path: str): - """Индексация документов из указанной папки""" + def index_documents(self, project_name: str, folder_path: str): + """Индексация документов из указанной папки для проекта""" + if not project_name: + return "❌ Укажите имя проекта", "" + if not folder_path: return "❌ Укажите путь к папке", "" @@ -77,17 +80,28 @@ class AgenticRAGInterface: return f"❌ Указанный путь не является папкой: {folder_path}", "" try: + # Переключаемся на проект (создаст новую коллекцию) + self.kb.set_project(project_name) + + # Индексируем документы chunks = self.kb.load_documents(folder_path) - return f"✅ Успешно! Индексировано чанков: {len(chunks)}", folder_path + return f"✅ Проект '{project_name}': индексировано чанков: {len(chunks)}", folder_path except Exception as e: return f"❌ Ошибка при индексации: {str(e)}", "" -# Инициализируем базу -kb = LocalKnowledgeBase() -# Загружаем документы (если есть) -if os.path.exists("./documents"): - kb.load_documents("./documents") + def switch_project(self, project_name: str): + """Переключиться на другой проект""" + if not project_name: + return "❌ Укажите имя проекта", "" + + try: + self.kb.set_project(project_name) + return f"✅ Переключено на проект: {project_name}", project_name + except Exception as e: + return f"❌ Ошибка: {str(e)}", "" +# Инициализируем базу +kb = LocalKnowledgeBase(project_name="default") # Создаем интерфейс interface = AgenticRAGInterface(create_agent_graph(), kb) @@ -141,9 +155,28 @@ def create_gradio_interface(): label="Примеры запросов" ) + # Секция управления проектами + gr.Markdown("---") + gr.Markdown("### 📂 Управление проектами") + + with gr.Row(): + with gr.Column(scale=2): + project_input = gr.Textbox( + label="Имя проекта", + placeholder="my_cpp_project", + lines=1 + ) + switch_btn = gr.Button("🔄 Переключить", variant="secondary") + with gr.Column(scale=1): + project_status = gr.Textbox( + label="Текущий проект", + lines=1, + interactive=False + ) + # Секция индексации документов gr.Markdown("---") - gr.Markdown("### 📂 Индексация документов") + gr.Markdown("### 📥 Индексация документов") with gr.Row(): with gr.Column(scale=3): @@ -153,7 +186,7 @@ def create_gradio_interface(): lines=1 ) with gr.Column(scale=1): - index_btn = gr.Button("📥 Индексировать", variant="secondary") + index_btn = gr.Button("📥 Индексировать", variant="primary") status_output = gr.Textbox( label="Статус индексации", @@ -180,10 +213,17 @@ def create_gradio_interface(): outputs=[answer_output, history_output] ) + # Обработчик переключения проекта + switch_btn.click( + fn=interface.switch_project, + inputs=[project_input], + outputs=[project_status, project_input] + ) + # Обработчик индексации index_btn.click( fn=interface.index_documents, - inputs=[folder_input], + inputs=[project_input, folder_input], outputs=[status_output, folder_input] ) diff --git a/local_knowledge_base.py b/local_knowledge_base.py index 395de90..b3897df 100644 --- a/local_knowledge_base.py +++ b/local_knowledge_base.py @@ -18,21 +18,48 @@ def should_skip(path: str) -> bool: class LocalKnowledgeBase: - def __init__(self, collection_name="documents", persist_dir="./qdrant_data"): + def __init__(self, project_name: str = "default", persist_dir="./qdrant_data"): # Инициализируем клиент Qdrant self.client = QdrantClient( path=persist_dir, prefer_grpc=True # Локальное хранение ) - self.collection_name = collection_name + self.persist_dir = persist_dir + self.set_project(project_name) # Инициализация эмбеддингов self.embeddings = OllamaEmbeddings( model="nomic-embed-text", # Хорошие локальные эмбеддинги ) - # Создаем коллекцию если её нет + def set_project(self, project_name: str): + """Переключиться на проект (создать/выбрать коллекцию)""" + # Очищаем имя от недопустимых символов + safe_name = "".join(c for c in project_name if c.isalnum() or c in "-_") + self.collection_name = safe_name self._create_collection() + print(f"Переключено на проект: {self.collection_name}") + + def get_current_project(self) -> str: + """Получить имя текущего проекта""" + return self.collection_name + + def list_projects(self) -> list: + """Список всех проектов (коллекций)""" + try: + collections = self.client.get_collections() + return [c.name for c in collections.collections] + except: + return [] + + def delete_project(self, project_name: str = None): + """Удалить проект (коллекцию)""" + name = project_name or self.collection_name + try: + self.client.delete_collection(collection_name=name) + print(f"Удалена коллекция: {name}") + except Exception as e: + print(f"Не удалось удалить коллекцию {name}: {e}") def _create_collection(self): try: