Добавил возможность индексации директории, указываемой из интерфейса
This commit is contained in:
@@ -65,6 +65,23 @@ class AgenticRAGInterface:
|
|||||||
self.conversation_history = []
|
self.conversation_history = []
|
||||||
return "История очищена", ""
|
return "История очищена", ""
|
||||||
|
|
||||||
|
def index_documents(self, folder_path: str):
|
||||||
|
"""Индексация документов из указанной папки"""
|
||||||
|
if not folder_path:
|
||||||
|
return "❌ Укажите путь к папке", ""
|
||||||
|
|
||||||
|
if not os.path.exists(folder_path):
|
||||||
|
return f"❌ Папка не существует: {folder_path}", ""
|
||||||
|
|
||||||
|
if not os.path.isdir(folder_path):
|
||||||
|
return f"❌ Указанный путь не является папкой: {folder_path}", ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
chunks = self.kb.load_documents(folder_path)
|
||||||
|
return f"✅ Успешно! Индексировано чанков: {len(chunks)}", folder_path
|
||||||
|
except Exception as e:
|
||||||
|
return f"❌ Ошибка при индексации: {str(e)}", ""
|
||||||
|
|
||||||
# Инициализируем базу
|
# Инициализируем базу
|
||||||
kb = LocalKnowledgeBase()
|
kb = LocalKnowledgeBase()
|
||||||
# Загружаем документы (если есть)
|
# Загружаем документы (если есть)
|
||||||
@@ -124,6 +141,26 @@ def create_gradio_interface():
|
|||||||
label="Примеры запросов"
|
label="Примеры запросов"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Секция индексации документов
|
||||||
|
gr.Markdown("---")
|
||||||
|
gr.Markdown("### 📂 Индексация документов")
|
||||||
|
|
||||||
|
with gr.Row():
|
||||||
|
with gr.Column(scale=3):
|
||||||
|
folder_input = gr.Textbox(
|
||||||
|
label="Путь к папке с файлами",
|
||||||
|
placeholder="./documents или /home/user/my_project",
|
||||||
|
lines=1
|
||||||
|
)
|
||||||
|
with gr.Column(scale=1):
|
||||||
|
index_btn = gr.Button("📥 Индексировать", variant="secondary")
|
||||||
|
|
||||||
|
status_output = gr.Textbox(
|
||||||
|
label="Статус индексации",
|
||||||
|
lines=2,
|
||||||
|
interactive=False
|
||||||
|
)
|
||||||
|
|
||||||
# Обработчики событий
|
# Обработчики событий
|
||||||
submit_btn.click(
|
submit_btn.click(
|
||||||
fn=interface.process_query,
|
fn=interface.process_query,
|
||||||
@@ -143,4 +180,11 @@ def create_gradio_interface():
|
|||||||
outputs=[answer_output, history_output]
|
outputs=[answer_output, history_output]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Обработчик индексации
|
||||||
|
index_btn.click(
|
||||||
|
fn=interface.index_documents,
|
||||||
|
inputs=[folder_input],
|
||||||
|
outputs=[status_output, folder_input]
|
||||||
|
)
|
||||||
|
|
||||||
return demo
|
return demo
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
from qdrant_client import QdrantClient
|
from qdrant_client import QdrantClient
|
||||||
from qdrant_client.models import Distance, VectorParams, PointStruct
|
from qdrant_client.models import Distance, VectorParams, PointStruct
|
||||||
from langchain_community.document_loaders import (
|
from langchain_community.document_loaders import (
|
||||||
@@ -10,6 +11,12 @@ from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
|
|||||||
from langchain_community.embeddings import OllamaEmbeddings
|
from langchain_community.embeddings import OllamaEmbeddings
|
||||||
|
|
||||||
|
|
||||||
|
def should_skip(path: str) -> bool:
|
||||||
|
"""Проверяет, нужно ли пропустить путь (системные папки)"""
|
||||||
|
skip_dirs = {'.git', 'build', 'vendor', 'node_modules', '__pycache__', '.venv', 'venv'}
|
||||||
|
return any(part in skip_dirs for part in Path(path).parts)
|
||||||
|
|
||||||
|
|
||||||
class LocalKnowledgeBase:
|
class LocalKnowledgeBase:
|
||||||
def __init__(self, collection_name="documents", persist_dir="./qdrant_data"):
|
def __init__(self, collection_name="documents", persist_dir="./qdrant_data"):
|
||||||
# Инициализируем клиент Qdrant
|
# Инициализируем клиент Qdrant
|
||||||
@@ -43,28 +50,33 @@ class LocalKnowledgeBase:
|
|||||||
print(f"Создана коллекция {self.collection_name}")
|
print(f"Создана коллекция {self.collection_name}")
|
||||||
|
|
||||||
def load_documents(self, directory_path: str):
|
def load_documents(self, directory_path: str):
|
||||||
"""Загрузка документов из директории"""
|
"""Загрузка документов из директории (рекурсивно)"""
|
||||||
loaders = {
|
loaders = {
|
||||||
".pdf": PyPDFLoader,
|
".pdf": PyPDFLoader,
|
||||||
".txt": lambda path: DirectoryLoader(path, glob="**/*.txt"),
|
".txt": lambda path: TextLoader(path, encoding="utf-8"),
|
||||||
".docx": lambda path: DirectoryLoader(path, glob="**/*.docx"),
|
".docx": lambda path: DirectoryLoader(path, glob="**/*.docx"),
|
||||||
".hpp": lambda path: TextLoader(path, encoding="utf-8"),
|
".hpp": lambda path: TextLoader(path, encoding="utf-8"),
|
||||||
".cpp": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
".cpp": lambda path: TextLoader(path, encoding="utf-8"),
|
||||||
".h": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
".h": lambda path: TextLoader(path, encoding="utf-8"),
|
||||||
".cc": lambda path: TextLoader(path, encoding="utf-8"), # добавить
|
".cc": lambda path: TextLoader(path, encoding="utf-8"),
|
||||||
}
|
}
|
||||||
|
|
||||||
all_documents = []
|
all_documents = []
|
||||||
|
|
||||||
for ext, loader_class in loaders.items():
|
# Рекурсивный обход с фильтрацией папок
|
||||||
for file_path in os.listdir(directory_path):
|
for root, dirs, files in os.walk(directory_path):
|
||||||
if file_path.endswith(ext):
|
# Фильтруем директории на месте
|
||||||
full_path = os.path.join(directory_path, file_path)
|
dirs[:] = [d for d in dirs if not should_skip(os.path.join(root, d))]
|
||||||
|
|
||||||
|
for file_path in files:
|
||||||
|
ext = os.path.splitext(file_path)[1]
|
||||||
|
if ext in loaders:
|
||||||
|
full_path = os.path.join(root, file_path)
|
||||||
try:
|
try:
|
||||||
loader = loader_class(full_path)
|
loader = loaders[ext](full_path)
|
||||||
documents = loader.load()
|
documents = loader.load()
|
||||||
all_documents.extend(documents)
|
all_documents.extend(documents)
|
||||||
print(f"Загружен {file_path}: {len(documents)} страниц")
|
print(f"Загружен {file_path}: {len(documents)} документов")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Ошибка загрузки {file_path}: {e}")
|
print(f"Ошибка загрузки {file_path}: {e}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user