Агент с RAG‑памятью: init_loader.py
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<|channel|>final code<|message|>import os
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from langchain_ollama import OllamaEmbeddings
|
||||
from langchain_qdrant import QdrantVectorStore
|
||||
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
||||
from langchain.document_loaders import TextLoader, DirectoryLoader
|
||||
|
||||
|
||||
def _get_documents_from_dir(directory: str) -> List[str]:
|
||||
"""
|
||||
Возвращает список путей к текстовым файлам в указанной директории.
|
||||
"""
|
||||
dir_path = Path(directory)
|
||||
if not dir_path.is_dir():
|
||||
raise ValueError(f"Путь {directory} не является директорией.")
|
||||
# Поддерживаем только .txt, .md и .pdf (если понадобится)
|
||||
files = list(dir_path.rglob("*"))
|
||||
return [str(p) for p in files if p.suffix.lower() in {".txt", ".md"}]
|
||||
|
||||
|
||||
def _load_documents(file_paths: List[str]) -> List[dict]:
|
||||
"""
|
||||
Загружает содержимое файлов в список словарей с полями 'content' и 'metadata'.
|
||||
"""
|
||||
documents = []
|
||||
for path in file_paths:
|
||||
loader = TextLoader(path, encoding="utf-8")
|
||||
docs = loader.load()
|
||||
# LangChain возвращает объекты Document; преобразуем их в dict
|
||||
for doc in docs:
|
||||
documents.append(
|
||||
{
|
||||
"content": doc.page_content,
|
||||
"metadata": {"source": path},
|
||||
}
|
||||
)
|
||||
return documents
|
||||
|
||||
|
||||
def _chunk_documents(documents: List[dict], chunk_size: int = 1000, chunk_overlap: int = 200) -> List[str]:
|
||||
"""
|
||||
Разбивает документы на чанки с помощью RecursiveCharacterTextSplitter.
|
||||
Возвращает список строк-чанков.
|
||||
"""
|
||||
splitter = RecursiveCharacterTextSplitter(
|
||||
chunk_size=chunk_size,
|
||||
chunk_overlap=chunk_overlap,
|
||||
)
|
||||
chunks = []
|
||||
for doc in documents:
|
||||
splits = splitter.split_text(doc["content"])
|
||||
# Добавляем метаданные в конец чанка для удобства поиска
|
||||
for s in splits:
|
||||
chunks.append(s)
|
||||
return chunks
|
||||
|
||||
|
||||
def _embed_and_store(chunks: List[str], collection_name: str, host: str = "localhost", port: int = 6333):
|
||||
"""
|
||||
Создаёт клиент Qdrant и сохраняет чанки с эмбеддингами Ollama.
|
||||
"""
|
||||
# Инициализация векторного хранилища
|
||||
embeddings = OllamaEmbeddings(model="nomic-embed-text")
|
||||
vectorstore = QdrantVectorStore(
|
||||
client_kwargs={"host": host, "port": port},
|
||||
collection_name=collection_name,
|
||||
embedding_function=embeddings,
|
||||
)
|
||||
# Добавляем чанки в коллекцию
|
||||
vectorstore.add_texts(chunks)
|
||||
|
||||
|
||||
def load_directory_to_qdrant(directory: str, collection_name: str = "knowledge_base"):
|
||||
"""
|
||||
Полный пайплайн загрузки документов из директории в Qdrant.
|
||||
"""
|
||||
file_paths = _get_documents_from_dir(directory)
|
||||
if not file_paths:
|
||||
print(f"В каталоге {directory} не найдено текстовых файлов.")
|
||||
return
|
||||
|
||||
documents = _load_documents(file_paths)
|
||||
chunks = _chunk_documents(documents)
|
||||
|
||||
_embed_and_store(chunks, collection_name)
|
||||
|
||||
print(
|
||||
f"Загружено {len(chunks)} чанков из {len(file_paths)} документов в коллекцию '{collection_name}'."
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Загрузка документов в Qdrant.")
|
||||
parser.add_argument("directory", help="Путь к директории с документами")
|
||||
parser.add_argument(
|
||||
"--collection",
|
||||
default="knowledge_base",
|
||||
help="Имя коллекции в Qdrant (по умолчанию: knowledge_base)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
load_directory_to_qdrant(args.directory, args.collection)
|
||||
Reference in New Issue
Block a user