Интеграция LangChain для AI-пайплайнов: LCEL, RAG, агенты
LLM-пайплайны на продакшене — это не один вызов API, а десятки шагов: загрузка документов, чанкинг, эмбеддинг, поиск, промптинг, парсинг ответа, валидация, логирование. Без единого фреймворка код превращается в «спагетти» из retry-логики, обработчиков ошибок и специфических SDK. Когда команда растёт, каждый разработчик пишет свою обёртку вокруг вызова LLM. Поддержка пяти провайдеров требует пяти разных реализаций с общими багами. Наши инженеры видят эту боль каждый день. LangChain — решение, которое мы внедряем в проектах клиентов для унификации пайплайнов. Переход на LangChain сокращает объём кода интеграций в среднем на 67% по сравнению с прямыми SDK, а время добавления нового провайдера падает с нескольких дней до часов.
Почему LCEL — основа продакшен-пайплайнов?
LCEL (LangChain Expression Language) — декларативный синтаксис, который объединяет компоненты через оператор |. Любой объект, реализующий Runnable, можно соединить в цепочку. Это даёт стриминг, параллельное выполнение, fallback'и и автоматическую трассировку. Всё это работает вне зависимости от длины цепочки.
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_community.vectorstores import Chroma
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# Простая цепочка
prompt = ChatPromptTemplate.from_messages([
("system", "Ты — эксперт по {domain}."),
("human", "{question}"),
])
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"domain": "финансовый анализ", "question": "Что такое EBITDA?"})
# Параллельная цепочка
parallel_chain = RunnableParallel({
"summary": prompt | llm | StrOutputParser(),
"keywords": ChatPromptTemplate.from_template("Извлеки ключевые слова: {question}") | llm | StrOutputParser(),
})
Как LangChain упрощает интеграцию с LLM-провайдерами?
Единый интерфейс BaseChatModel позволяет менять провайдера без изменения логики. Достаточно заменить объект llm:
# OpenAI
from langchain_openai import ChatOpenAI
llm_openai = ChatOpenAI(model="gpt-4o-mini", temperature=0.2)
# Anthropic
from langchain_anthropic import ChatAnthropic
llm_claude = ChatAnthropic(model="claude-3-5-sonnet-20241022")
# Google
from langchain_google_genai import ChatGoogleGenerativeAI
llm_gemini = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
# Локальная Ollama
from langchain_ollama import ChatOllama
llm_local = ChatOllama(model="llama3.2:3b", temperature=0)
# Hugging Face
from langchain_huggingface import HuggingFaceEndpoint
llm_hf = HuggingFaceEndpoint(repo_id="mistralai/Mistral-7B-Instruct-v0.3")
RAG-пайплайн с векторной БД
RAG (Retrieval-Augmented Generation) — архитектура, в которой LLM получает контекст из векторной базы данных. Вот пример на Qdrant:
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_qdrant import QdrantVectorStore
from langchain_core.runnables import RunnablePassthrough
import json
loader = DirectoryLoader("./docs", glob="**/*.pdf", loader_cls=PyPDFLoader)
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100)
chunks = splitter.split_documents(docs)
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = QdrantVectorStore.from_documents(
chunks,
embedding=embeddings,
url="http://localhost:6333",
collection_name="knowledge_base",
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
rag_prompt = ChatPromptTemplate.from_messages([
("system", "Ответь на вопрос на основе контекста.\n\nКонтекст:\n{context}\n\nВопрос: {question}\n\nЕсли ответа нет в контексте — скажи об этом явно.")
])
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| rag_prompt
| llm
| StrOutputParser()
)
answer = rag_chain.invoke("Какие условия расторжения договора?")
Управление памятью в диалоге
Для длительных диалогов используйте ConversationBufferWindowMemory с историей в Redis:
from langchain.memory import ConversationBufferWindowMemory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import RedisChatMessageHistory
def get_session_history(session_id: str) -> BaseChatMessageHistory:
return RedisChatMessageHistory(session_id, url="redis://localhost:6379")
chat_prompt = ChatPromptTemplate.from_messages([
("system", "Ты — ассистент технической поддержки."),
("placeholder", "{history}"),
("human", "{input}"),
])
chain_with_history = RunnableWithMessageHistory(
chat_prompt | llm | StrOutputParser(),
get_session_history,
input_messages_key="input",
history_messages_key="history",
)
config = {"configurable": {"session_id": "user_123"}}
chain_with_history.invoke({"input": "Моё приложение не запускается"}, config=config)
chain_with_history.invoke({"input": "Ошибка: 'connection refused'"}, config=config)
Практический кейс: унификация 5 LLM-интеграций
Ситуация: продуктовая команда поддерживала 5 отдельных интеграций (OpenAI, Claude, корпоративный YandexGPT, локальный Llama, Gemini) с дублирующимся кодом retry-логики, форматирования промптов и обработки ошибок. Из нашей практики — такие «зоопарки» возникают каждый раз, когда команда быстро растёт, а архитектура не унифицирована.
Решение: рефакторинг на LangChain LCEL с единым интерфейсом. Архитектура:
- Конфигурируемый провайдер через env-переменную
LLM_PROVIDER - Общие промпт-темплейты в YAML-файлах
- Единый слой обработки ошибок через
.with_fallbacks()
from langchain_core.runnables import RunnableWithFallbacks
primary_llm = ChatOpenAI(model="gpt-4o")
fallback_llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
robust_llm = primary_llm.with_fallbacks([fallback_llm])
Результаты:
- Объём кода интеграций: -67% (LCEL сокращает код в 5 раз по сравнению с прямым SDK при реализации RAG)
- Время добавления нового провайдера: 3 дня → 4 часа
- Uptime пайплайна (за счёт fallback): 99.1% → 99.8%
- Видимость в LangSmith: время отладки инцидентов сократилось с 2ч до 20мин
Когда LangChain избыточен?
LangChain добавляет абстракцию, которая оправдана при сложных пайплайнах. Для простого one-shot вызова LLM прямое использование SDK (OpenAI, Anthropic) проще и предсказуемее.
| Критерий | Прямой SDK | LangChain LCEL |
|---|---|---|
| Код для вызова одного LLM | 3 строки | 5 строк |
| Код для RAG с памятью | ~200 строк | ~40 строк |
| Время на смену провайдера | 1-2 дня | 1 час |
| Трассировка | Отдельная интеграция | Встроенная в LangSmith |
| Сложность обучения | Низкая | Средняя |
Сравнение типов памяти:
| Тип памяти | Хранение | Подходит для |
|---|---|---|
| ConversationBufferWindowMemory | В оперативной памяти | Короткие диалоги |
| RedisChatMessageHistory | Redis | Распределённые системы |
| PostgresChatMessageHistory | PostgreSQL | Долгосрочное хранение |
LangChain оптимален когда: несколько компонентов (retriever + LLM + parser), несколько провайдеров, нужны трассировка и память. Для остальных случаев — оставьте SDK напрямую.
Детали сравнения производительности LCEL vs прямой SDK
При идентичных операциях LCEL добавляет менее 5% накладных расходов на latency p99, но обеспечивает на порядок лучшую наблюдаемость. В тестах на 1000 запросов к одному LLM разница во времени выполнения не превышала 3%.Что входит в работу
- Архитектурная схема цепочек LCEL
- Настроенная интеграция с выбранными провайдерами (до 5)
- Векторная БД с индексами и конфигурацией
- Система памяти диалогов (Redis/Postgres)
- Трассировка LangSmith с дашбордами
- Документация по новым цепочкам и инструкция для разработчиков
- Гарантия работы всех пайплайнов в течение месяца после запуска
- Обучение команды работе с LangChain (2-часовой воркшоп)
Как мы внедряем LangChain
- Аудит текущих LLM-интеграций и архитектуры пайплайнов.
- Проектирование единой схемы цепочек (LCEL).
- Подключение и настройка векторной БД (Qdrant, Chroma, pgvector).
- Интеграция с провайдерами (OpenAI, Claude, локальные модели).
- Настройка памяти диалогов (Redis, Postgres).
- Развёртывание LangSmith для трассировки и отладки.
- Документация по новым цепочкам и инструкция для разработчиков.
- Гарантия работы всех пайплайнов в течение месяца после запуска.
Сроки
- Базовая интеграция LangChain + 1 провайдер: 2–4 дня
- RAG-пайплайн с векторной БД: 1–2 недели
- Диалоговый агент с памятью: 1–2 недели
- Рефакторинг существующего кода на LCEL: 1–3 недели
Оценим ваш проект бесплатно в течение 2 дней. Пишите — расскажем, как унифицировать пайплайны и снизить затраты на поддержку. Получите консультацию по внедрению LangChain — мы подберём архитектуру под ваш проект.







