LCEL и pipe-синтаксис: цепочки через |
Урок знакомит с LCEL — способом собирать цепочки оператором конвейера.
LCEL (LangChain Expression Language) — декларативный способ соединять компоненты в конвейер оператором
|, где выход одного звена становится входом следующего.
Идея конвейера
Знакомый из shell оператор | передаёт вывод одной команды на вход другой. LCEL делает то же с компонентами LangChain: prompt | model | parser читается как «заполни шаблон, отправь в модель, разбери ответ». Каждый элемент — это Runnable, и составленная цепочка тоже Runnable.
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_template("Дай определение термина: {term}")
model = ChatOpenAI(model="gpt-4o-mini")
parser = StrOutputParser()
chain = prompt | model | parser
print(chain.invoke({"term": "идемпотентность"}))Единый интерфейс Runnable
Любая LCEL-цепочка умеет одинаковый набор методов:
| Метод | Что делает |
invoke(x) | один вход → один выход |
batch([x1, x2]) | пакет входов параллельно |
stream(x) | стримит ответ по частям |
ainvoke(x) | асинхронный вариант |
Принцип «функция-композиция» легко смоделировать на чистом Python:
def compose(*funcs):
def run(x):
for f in funcs:
x = f(x)
return x
return run
pipeline = compose(str.strip, str.upper, lambda s: f"[{s}]")
print(pipeline(" langchain "))Вывод:
[LANGCHAIN]
Как работает под капотом
Оператор | у Runnable перегружен: он создаёт объект RunnableSequence, который хранит список звеньев. При invoke() он прогоняет вход через звенья по очереди, прокидывая выход предыдущего на вход следующего. Поскольку у всей последовательности тот же интерфейс Runnable, к ней автоматически применимы batch, stream и асинхронные методы — их не нужно реализовывать вручную для каждой цепочки.
Частые ошибки
- Несовпадение типов между звеньями. Выход одного звена должен подходить на вход следующего (например, парсер ждёт
AIMessage, а не строку). - Забыть парсер. Без
StrOutputParserна выходе останетсяAIMessage, а не чистая строка. - Ожидать, что цепочка «сама поймёт» порядок. Порядок задаёте вы, слева направо.
Итог
- LCEL соединяет компоненты оператором
|в конвейер. - Каждое звено и вся цепочка — это
Runnableс методамиinvoke/batch/stream/ainvoke. - Порядок звеньев — слева направо, типы между ними должны совпадать.