RAG по своим документам: поиск по базе знаний и ответы с цитатами через TokenMaster
RAG (Retrieval-Augmented Generation) — это способ заставить языковую модель отвечать по вашим документам, а не по общей памяти. Система сначала ищет нужные фрагменты в вашей базе знаний, а затем передаёт их модели, которая строит ответ с опорой на эти куски. Так модель отвечает по актуальным данным и может ссылаться на конкретный документ, а не выдумывать факты.
Что понадобится
- API-ключ TokenMaster — создаётся в разделе «Ключи» после регистрации на tokenmaster.ru.
- Python 3.8+ и библиотеки
openai,chromadbиsentence-transformers. - Тексты ваших документов: регламенты, договоры, инструкции, статьи базы знаний.
Библиотеки устанавливаются одной командой:
pip install openai chromadb sentence-transformers
Пошаговая сборка RAG
Схема работы простая: разбиваем документы на чанки, переводим их в векторы (embeddings), сохраняем в векторную базу, а на запрос находим похожие чанки и подставляем их в промпт модели.
1. Разбиваем документы на чанки
Модель не может держать в контексте целую библиотеку, поэтому текст режут на небольшие пересекающиеся фрагменты:
def split_text(text, chunk_size=500, overlap=50):
words = text.split()
chunks = []
for i in range(0, len(words), chunk_size - overlap):
chunks.append(" ".join(words[i:i + chunk_size]))
return chunks
with open("docs.txt", encoding="utf-8") as f:
chunks = split_text(f.read())
Перекрытие (overlap) нужно, чтобы фрагмент не обрывался на середине мысли.
2. Получаем embeddings и сохраняем в векторную БД
Embedding — это числовой вектор, отражающий смысл текста: похожие по смыслу фрагменты оказываются рядом в векторном пространстве. Для эмбеддингов берём локальную модель, а сохраняем всё в Chroma:
from sentence_transformers import SentenceTransformer
import chromadb
model = SentenceTransformer("intfloat/multilingual-e5-small")
embeddings = model.encode(chunks)
client = chromadb.Client()
collection = client.get_or_create_collection("my_docs")
collection.add(
ids=[str(i) for i in range(len(chunks))],
documents=chunks,
embeddings=embeddings.tolist(),
)
3. На запрос ищем похожие чанки
Запрос переводим в тот же векторный вид и ищем ближайшие по смыслу фрагменты:
query = "Как расторгнуть договор аренды?"
query_embedding = model.encode([query])[0]
results = collection.query(
query_embeddings=[query_embedding.tolist()],
n_results=3,
)
context = "\n\n".join(results["documents"][0])
4. Отдаём контекст в LLM
Найденные чанки подставляем в промпт и просим модель отвечать только по ним:
from openai import OpenAI
client = OpenAI(
base_url="https://tokenmaster.ru/v1",
api_key="sk-...", # ваш ключ TokenMaster
)
prompt = (
"Ответь на вопрос, используя только приведённый контекст. "
"Если ответа в контексте нет, так и скажи.\n\n"
f"Контекст:\n{context}\n\n"
f"Вопрос: {query}"
)
answer = client.chat.completions.create(
model="deepseek-flash", # или glm-4.5, qwen
messages=[{"role": "user", "content": prompt}],
)
print(answer.choices[0].message.content)
Добавив в промпт номера фрагментов и требование указывать их в ответе, вы получите ответы с цитатами на конкретные куски документа.
Подключение TokenMaster
TokenMaster — это AI-шлюз с OpenAI-совместимым API, поэтому модель вызывается стандартной библиотекой openai без изменений. Подключение сводится к двум параметрам:
- Base URL:
https://tokenmaster.ru/v1 - API Key: ваш ключ вида
sk-…
Почему TokenMaster? Один ключ и один баланс для моделей DeepSeek, GLM (Zhipu) и Qwen, оплата из России. Base URL единый —
https://tokenmaster.ru/v1.
Модель выбирается под задачу: deepseek-flash подойдёт для быстрых ответов по базе знаний, а более мощные модели — для сложных вопросов по длинным документам. Актуальный каталог и цены — на tokenmaster.ru/pricing, документация по API — на tokenmaster.ru/docs.
Проверка работы
Запустите скрипт и задайте вопрос, ответ на который есть в ваших документах. Если модель отвечает по тексту и не выдумывает лишнего — RAG работает. Типичные ошибки:
- 401 / invalid api key — ключ неверный или скопирован не целиком; он должен начинаться с
sk-. - connection error — проверьте Base URL: ровно
https://tokenmaster.ru/v1, без лишнего/chat/completionsв конце. - insufficient quota — на балансе недостаточно средств; пополните его в личном кабинете.
- ответ не по документам — увеличьте
n_resultsили перепроверьте разбивку на чанки: слишком большие или слишком мелкие фрагменты ухудшают поиск.
Частые вопросы
Чем RAG лучше простого «загрузить файл в чат»? Загруженный файл упирается в лимит контекста модели. RAG хранит всю базу в векторном виде и подставляет в промпт только релевантные фрагменты, поэтому работает с большими объёмами документов.
Где брать embeddings?
Для эмбеддингов не нужен платный API: локальная модель sentence-transformers даёт качественные векторы бесплатно. Для продакшена с большими объёмами можно взять Chroma с постоянным хранилищем, FAISS или специализированные векторные базы.
Можно ли получать ответы с цитатами? Да. Пронумеруйте чанки при сохранении и попросите модель в промпте указывать номера фрагментов, на которые она ссылается, — тогда ответ будет легко проверить по исходному документу.
Итог
RAG по своим документам — это короткий конвейер на Python: разбили текст на чанки, получили embeddings, сохранили в векторную базу, а на запрос нашли похожие фрагменты и передали их в промпт модели. Подключите OpenAI-совместимый API TokenMaster по Base URL https://tokenmaster.ru/v1 с ключом sk-… — и получите чат, который отвечает по вашей базе знаний с опорой на конкретные документы.
TokenMaster