Интеграция 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 — мы подберём архитектуру под ваш проект.







