Агент с RAG‑памятью: tools.py

This commit is contained in:
2026-05-26 09:21:08 +00:00
parent 8f7d7648b7
commit 7314622085
@@ -0,0 +1,89 @@
# tools.py
"""
Модуль с инструментами для агента.
В файле определены два инструмента:
1. search_knowledge_base семантический поиск в Qdrant.
2. add_to_knowledge_base – добавление документа (с чанками) в базу.
Инструменты реализованы через декоратор @tool из langchain.tools,
что позволяет автоматически использовать их в агентах LangChain.
"""
from pathlib import Path
from typing import List, Tuple
# ──────────────────────── Зависимости ────────────────────────
from langchain.embeddings.ollama import OllamaEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores.qdrant import QdrantVectorStore
from langchain.tools import tool
# ──────────────────────── Конфигурация ────────────────────────
# Путь к локальной базе Qdrant (предполагается, что она уже запущена)
QDRANT_URL = "http://localhost:6333"
COLLECTION_NAME = "knowledge_base"
# Создаём один экземпляр векторного хранилища и эмбеддеров,
# чтобы не создавать их каждый раз при вызове инструментов.
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = QdrantVectorStore(
client_kwargs={"url": QDRANT_URL},
collection_name=COLLECTION_NAME,
embedding_function=embeddings.embed_query, # функция для получения эмбеддингов
)
# ──────────────────────── Инструмент: поиск ────────────────────────
@tool("search_knowledge_base",
description="Семантический поиск в базе знаний. "
"Возвращает список строк с найденными документами и их релевантностью.")
def search_knowledge_base(query: str, max_results: int = 5) -> List[Tuple[str, float]]:
"""
Выполняет семантический поиск по запросу.
Args:
query (str): поисковый запрос.
max_results (int): максимальное количество результатов.
Returns:
List[Tuple[str, float]]: список кортежей (текст документа, релевантность).
"""
# similarity_search_with_score возвращает [(Document, score), ...]
results = vectorstore.similarity_search_with_score(query, k=max_results)
return [(doc.page_content, score) for doc, score in results]
# ──────────────────────── Инструмент: добавление ────────────────────────
@tool("add_to_knowledge_base",
description="Добавляет новый документ в базу знаний. "
"Документ разбивается на чанки и сохраняется с метаданными.")
def add_to_knowledge_base(content: str, title: str) -> str:
"""
Добавляет текстовый контент в Qdrant.
Args:
content (str): полный текст документа.
title (str): заголовок/имя документа.
Returns:
str: сообщение об успешном добавлении и количестве чанков.
"""
# Разбиваем документ на чанки
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", " ", ""],
)
chunks = splitter.split_text(content)
# Создаём объекты Document с метаданными
from langchain.schema import Document
documents: List[Document] = [
Document(page_content=chunk, metadata={"title": title})
for chunk in chunks
]
# Добавляем векторные представления в Qdrant
vectorstore.add_documents(documents)
return f"Документ '{title}' добавлен. Количество чанков: {len(chunks)}"