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 (легковесная, подходит для начинающих)

Инициализация модели эмбеддингов

Пример

from dotenv import load_dotenv
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"

Код после настройки:

Пример

import os
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_openai import OpenAIEmbeddings
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
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]}...")
Другие расширения