Экзамен: RAG-агент с ChromaDB и веб-поиском: vectorstore.py
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
# vectorstore.py
|
||||
"""
|
||||
Модуль для работы с ChromaDB и OllamaEmbeddings.
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
from langchain_ollama.embeddings import OllamaEmbeddings
|
||||
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
||||
from langchain_chroma import Chroma
|
||||
from langchain.docstore.document import Document
|
||||
|
||||
|
||||
def create_vectorstore(persist_directory: str = "./chroma_db") -> Chroma:
|
||||
"""
|
||||
Создаёт (или загружает) коллекцию ChromaDB с OllamaEmbeddings.
|
||||
|
||||
Args:
|
||||
persist_directory: Путь, где будет храниться база данных.
|
||||
Если директория не существует – создаётся автоматически.
|
||||
|
||||
Returns:
|
||||
Chroma объект, готовый к работе.
|
||||
"""
|
||||
# Создаём путь и при необходимости создаём папку
|
||||
path = Path(persist_directory)
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Инициализируем эмбеддер Ollama
|
||||
embeddings = OllamaEmbeddings(model="nomic-embed-text")
|
||||
|
||||
# Создаём/загружаем коллекцию Chroma
|
||||
vectorstore = Chroma(
|
||||
persist_directory=str(path),
|
||||
embedding_function=embeddings,
|
||||
)
|
||||
return vectorstore
|
||||
|
||||
|
||||
def load_documents(directory: str | Path, vectorstore: Chroma) -> None:
|
||||
"""
|
||||
Читает все .txt и .md файлы из указанной директории, разбивает их на чанки
|
||||
и добавляет в коллекцию ChromaDB.
|
||||
|
||||
Args:
|
||||
directory: Путь к папке с документами.
|
||||
vectorstore: Объект Chroma, куда будут загружены документы.
|
||||
"""
|
||||
# Подготовка текстового разделителя
|
||||
splitter = RecursiveCharacterTextSplitter(
|
||||
chunk_size=1000,
|
||||
chunk_overlap=200,
|
||||
)
|
||||
|
||||
docs_to_add: list[Document] = []
|
||||
|
||||
# Ищем файлы .txt и .md рекурсивно
|
||||
for file_path in Path(directory).rglob("*"):
|
||||
if not file_path.is_file():
|
||||
continue
|
||||
if file_path.suffix.lower() not in {".txt", ".md"}:
|
||||
continue
|
||||
|
||||
try:
|
||||
text = file_path.read_text(encoding="utf-8")
|
||||
except Exception as exc:
|
||||
# Если файл не читается – пропускаем и выводим предупреждение
|
||||
print(f"⚠️ Не удалось прочитать {file_path}: {exc}")
|
||||
continue
|
||||
|
||||
# Разбиваем текст на чанки
|
||||
chunks = splitter.split_text(text)
|
||||
|
||||
# Создаём Document объекты с метаданными
|
||||
for i, chunk in enumerate(chunks):
|
||||
docs_to_add.append(
|
||||
Document(
|
||||
page_content=chunk,
|
||||
metadata={
|
||||
"source": str(file_path),
|
||||
"page": i + 1,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
if not docs_to_add:
|
||||
print("⚠️ В указанной папке не найдено подходящих файлов.")
|
||||
return
|
||||
|
||||
# Добавляем документы в коллекцию
|
||||
vectorstore.add_documents(docs_to_add)
|
||||
|
||||
# Сохраняем изменения (persist)
|
||||
vectorstore.persist()
|
||||
Reference in New Issue
Block a user