LangChain RAG
RAG (Retrieval-Augmented Generation) позволяет ИИ отвечать на вопросы на основе ваших приватных документов без дообучения модели. Вам нужно только векторизовать и сохранить документы, и Агент сможет извлекать релевантный контент для ответа.
Что такое RAG
Обычные большие модели могут давать ответы только на основе содержимого, которое присутствует в их обучающих данных. Если ваши документы приватны (внутренние документы компании, личные заметки), модель "не знает" о них. RAG решает эту проблему:
- Офлайн-этап: Разделите документы на небольшие фрагменты → Используйте модель Embedding, чтобы преобразовать их в векторы → Сохраните их в векторной базе данных
- Онлайн-этап: Пользователь задаёт вопрос → Преобразовать вопрос в вектор → Найти наиболее похожий контент в векторной базе данных → Отправить извлечённый контент модели в качестве контекста → Модель отвечает на основе извлечённого контента
Рабочий процесс RAG
┌──────────────────────────────────────────────────────┐ │ 离线阶段(索引) │ │ │ │ 文档 → DocumentLoader → TextSplitter → Embedding │ │ ↓ │ │ VectorStore │ └──────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────┐ │ 在线阶段(检索) │ │ │ │ 用户提问 → Embedding → 相似度搜索 → 检索结果 │ │ ↓ │ │ 检索结果 + 用户问题 → 模型 → 回答 │ └──────────────────────────────────────────────────────┘

Подготовка окружения
Установите зависимости, связанные с RAG:
$ pip install langchain-deepseek langchain-chroma chromadb
| Пакет | Назначение |
|---|---|
| langchain-deepseek | Предоставляет модель OpenAI Embedding |
| langchain-chroma | Интеграция LangChain с векторной базой данных Chroma |
| chromadb | Векторная база данных Chroma (легковесная, подходит для начинающих) |
Инициализация модели эмбеддингов
Пример
load_dotenv()
from langchain_openai import OpenAIEmbeddings
# Модель текстовых эмбеддингов OpenAI
# Преобразовать текст в вектор (набор чисел с плавающей запятой)
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Тест: преобразовать фрагмент текста в вектор
text = "EXAMPLE — это платформа для изучения программирования"
vector = embeddings.embed_query(text)
print(f"Текст: {text}")
print(f"Размерность вектора: {len(vector)}") # text-embedding-3-small имеет 1536 измерений
print(f"Первые 5 значений вектора: {vector[:5]}")
Результат выполнения:
Text: Example 是一个编程学习平台 Vector dimension: 1536 First 5 vector values: [0.0123, -0.0045, 0.0234, -0.0012, 0.0089]
В качестве альтернативы, если у вас нет ключа OpenAI, вы можете использовать сервис Embedding от Alibaba Bailian..envВам нужно добавить ключ Alibaba Bailian в файл конфигурации:
DASHSCOPE_API_KEY="sk-xxx"
Код после настройки:
Пример
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import OpenAIEmbeddings
# Модель текстовых эмбеддингов OpenAI
# Преобразовать текст в вектор (набор чисел с плавающей запятой)
# Использовать сервис Qwen Embedding от Alibaba Cloud Bailian (DashScope)
# Embedding API от Bailian совместим со спецификацией OpenAI API, поэтому напрямую используйте langchain-openai
# OpenAIEmbeddings, просто укажите base_url на совместимый эндпоинт Bailian,
# не нужно устанавливать langchain-community / dashscope (этот пакет больше не поддерживается).
# text-embedding-v4 в настоящее время является рекомендуемой универсальной векторной моделью, по умолчанию выдающей 1024-мерные векторы.
#
# Два ключевых параметра обязательны:
# - check_embedding_ctx_length=False: OpenAIEmbeddings по умолчанию использует tiktoken
# предварительно кодировать текст в массивы идентификаторов токенов перед отправкой (это формат, распознаваемый официальным API OpenAI),
# но совместимый интерфейс Bailian принимает только необработанные строки. Если не отключить эту опцию, он будет сообщать
# ошибка "contents is neither str nor list of str".
# - chunk_size=10: интерфейс Embedding от Bailian принимает не более 10 фрагментов текста за запрос.
# OpenAIEmbeddings по умолчанию упаковывает 1000 фрагментов за раз. Если база знаний немного больше, будет превышен лимит и выдаст ошибку.
embeddings = OpenAIEmbeddings(
model="text-embedding-v4",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
check_embedding_ctx_length=False,
chunk_size=10,
)
# Тест: преобразовать фрагмент текста в вектор
text = "EXAMPLE — это платформа для изучения программирования"
vector = embeddings.embed_query(text)
print(f"Текст: {text}")
print(f"Размерность вектора: {len(vector)}") # text-embedding-3-small имеет 1536 измерений
print(f"Первые 5 значений вектора: {vector[:5]}")
Создать векторное хранилище
Пример
from langchain_chroma import Chroma
# Инициализировать модель Embedding
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Создать векторное хранилище Chroma (данные сохраняются в локальном каталоге)
vector_store = Chroma(
collection_name="example_docs",
embedding_function=embeddings,
persist_directory="./chroma_db", # Каталог сохранения
)
# Добавить документы (простейшая форма: список текстов)
texts = [
"EXAMPLE — это бесплатный сайт для изучения программирования, который предоставляет руководства по HTML, CSS, JavaScript, Python и т. д.",
"Базовый учебник по Python3 состоит из 30 глав, подходит для начинающих с нуля и охватывает настройку окружения, базовый синтаксис, объектно-ориентированное программирование и многое другое.",
"Базовое руководство по HTML содержит 25 глав, охватывающих базовые знания, такие как теги HTML, формы и мультимедиа.",
]
# add_texts автоматически преобразует текст в векторы и сохраняет их
vector_store.add_texts(texts)
print(f"Добавлено {len(texts)} документов в векторное хранилище")
Семантический поиск
Пример
results = vector_store.similarity_search(
"Я хочу изучать Python. Какие руководства вы порекомендуете?",
k=2, # Вернуть 2 наиболее похожих результата
)
print("Результаты поиска:")
for i, doc in enumerate(results):
print(f"\n"Результат {i+1}:")
print(f" Содержимое: {doc.page_content}")
print(f" Метаданные: {doc.metadata}")
Результат выполнения:
搜索结果:
Result 1:
Content: Python3 基础教程共 30 章,适合零基础入门...
Metadata: {}
Result 2:
Content: Example是一个免费的编程学习网站...
Metadata: {}
Обратите внимание, что первый результат поиска более релевантен, чем второй — хотя первый содержит ключевое слово "Python", он ранжируется посемантическому сходству, а не по совпадению ключевых слов. В этом преимущество векторного поиска.
Создание Retriever
Retriever — стандартизированный интерфейс для Vector Store:
Пример
retriever = vector_store.as_retriever(
search_type="similarity", # Поиск по сходству
search_kwargs={"k": 3}, # Вернуть топ-3 результата
)
# Использовать retriever
docs = retriever.invoke("Путь изучения Python")
for doc in docs:
print(f"- {doc.page_content[:60]}...")