Гайд · TNWS AI
Как показывать ход работы LangChain-агента через stream updates и messages
Различия stream_mode updates и messages, потоковая выдача токенов и контроль конца ответа без показа сырого tool JSON.
Задача и применимость
Русскоязычный запрос: «как показывать прогресс LangChain stream updates messages». Проверка официальной документации LangChain — 19 сентября 2026 года. Python LangChain 1.x; create_agent возвращает граф, поддерживающий stream/astream. Конкретная модель должна поддерживать streaming для посимвольной выдачи.
stream_mode="updates" выдаёт обновления состояния после шагов агента: модель, инструмент и следующий ответ. stream_mode="messages" выдаёт пары token/metadata при генерации. Можно выбрать несколько режимов и version="v2", тогда события помечаются type/data. Инкрементальные куски tool call JSON не являются готовым пользовательским ответом.
Порядок действий
- Сначала сделайте обычный invoke и запишите конечный текст для контрольного вопроса.
- Включите stream_mode="updates" и наблюдайте узлы model и tools; проверьте, что инструмент действительно запущен.
- Для токенов используйте messages и version="v2"; отображайте только текстовые куски AIMessageChunk.
- Разделите события внутренних аргументов tool и финального текста, чтобы не раскрыть структуру служебных вызовов.
- Обработайте разрыв соединения: UI должен явно показывать неполный ответ и возможность безопасного повтора.
Пример ниже предназначен для демонстрационного окружения: установите соответствующий пакет интеграции, настройте ключ через секреты сервера и убедитесь, что модель доступна вашему аккаунту. Если доступ к указанному model ID отсутствует, выберите поддерживаемую модель со сходными возможностями и заново проверьте работу именно на ней. Ни один пример не содержит действующего API-ключа и не разрешает обход ограничений провайдера.
Готовый шаблон на Python
from langchain.agents import create_agent
from langchain.messages import AIMessageChunk
agent = create_agent(model="openai:gpt-5.5", tools=[])
for event in agent.stream(
{"messages": [{"role": "user", "content":
"Объясни в двух предложениях, что такое embedding."}]},
stream_mode=["messages", "updates"], version="v2"):
if event["type"] == "messages":
chunk, metadata = event["data"]
if isinstance(chunk, AIMessageChunk) and chunk.text:
print(chunk.text, end="", flush=True)
elif event["type"] == "updates":
# Состояние шага храните в служебном журнале, а не в ответе UI.
pass
Конкретные входные и ожидаемые данные
Вход: просьба объяснить embedding в двух предложениях. Ожидается несколько фрагментов текста по ходу генерации и итог, содержащий корректное объяснение числового представления. Событие updates с завершением узла не равно отдельному предложению ответа. Если сеть обрывается после первых пяти слов, UI не должен обозначить текст как завершённый.
Оценивать стоит не красоту формулировки, а проверяемое выполнение задачи. Сохраните исходный текст, ID пользователя или теста и ожидаемое значение отдельно от ответа модели. Если пример выдаёт неверный факт, разберите данные на входе и состояние инструмента до изменения промпта: иначе можно замаскировать ошибку инфраструктуры удачной перефразировкой.
Диагностика и границы решения
Потоковая выдача решает UX, но усложняет корректность состояния. При инструментальном агенте messages может содержать незаконченные аргументы вызова инструмента, а updates — завершённый ToolMessage. Не направляйте всякий кусок messages прямо пользователю: проверяйте тип содержимого и узел, не показывайте служебные сведения. Если приложение строит HTTP SSE, добавьте отдельное событие completion после окончательного завершения итератора; иначе браузер не отличит нормальный конец от закрытого сокета. Внутренний stream и транспортный SSE — разные слои: поддержка одного не доказывает готовности другого. Пользователь может отменить запрос; приложение должно прекратить вычисление, если API поддерживает отмену, и не выполнять повторно инструмент с побочным эффектом без idempotency key. Удобно сохранять конечный invoke для эталона и сравнивать по смыслу, но точное совпадение текста между двумя генерациями не гарантируется. Для UI добавляйте fallback, когда модель отдаёт только полный ответ без последовательности текстовых chunks. Измеряйте время до первого отображаемого символа и время до подтверждённого завершения отдельно.
Контрольный эксперимент
Отладочный пример с tools=[] не показывает многошаговый прогресс, поэтому после smoke test подключайте безопасный read-only tool и проверяйте порядок model → tools → model через updates. В журнале должны быть идентификатор запроса и тип каждого события; содержимое персональных аргументов маскируйте. Если приложение перезапускает stream после сетевого сбоя, повтор агентного вызова может породить второй tool call, поэтому правило повторов должно зависеть от фактического статуса, а не только от кнопки «попробовать снова». Потребителю потока не следует парсить частичный JSON tool аргументов как завершённый объект. Для клиентов, которым нужен только готовый ответ, обычный invoke проще и надёжнее. Выбирайте streaming по измеренному улучшению пользовательского ожидания, сохраняя возможность проверить финальную фактическую цитату.
Дополнительный проверочный сценарий
Для потокового интерфейса заранее определите, какие события пользователь вправе видеть. Можно показывать «ищем источник» как человеческую метку шага, но нельзя выводить сырой текст промпта, tool arguments и приватный результат БД. Проведите тест со значением инструмента, содержащим персональный адрес: адрес не должен появляться в UI до проверки разрешения на вывод. Если модель начала писать ответ, а затем нашла противоречие, не считайте ранние токены окончательной истиной. Для важных решений удерживайте финальную формулировку до завершения проверки источников либо снабжайте частичный текст явным признаком черновика. Обработчик завершения должен работать при обычном окончании, ошибке инструмента, отмене и закрытии браузера.
Критерии результата
- Обновления содержат конечный шаг работы агента.
- UI не показывает служебные аргументы tool.
- Разрыв сети помечен как незавершённый ответ.
- По завершении есть отдельное подтверждение итогового состояния.
При провале критерия помечайте задачу незавершённой. Корректный HTTP-ответ от провайдера не доказывает истинность результата, а удачный результат локального теста не гарантирует ту же доступность модели или сервисов в вашем рабочем окружении.
Типичные ошибки и что не делать
- Путать updates с токенами.
- Показывать частичный JSON инструмента как готовый ответ.
- Считать закрытие сокета успешным завершением.
- Повторно выполнять побочные эффекты при переподключении.
Не отправляйте персональные сведения и секреты в инструмент трассировки или тестовый аккаунт без оценки права доступа и политики хранения. Сначала добейтесь правильного ответа на небольшом наборе положительных и отрицательных примеров, затем подключайте полноценный контент или базу данных.
FAQ
Какой режим даёт токены?
messages.
Какой режим показывает шаги агента?
updates.
Можно ли включить оба?
Да, передайте список режимов и разбирайте type/data.
Официальные источники
Частые вопросы
Какой режим даёт токены?
messages.
Какой режим показывает шаги агента?
updates.
Можно ли включить оба?
Да, передайте список режимов и разбирайте type/data.
Читайте также
Как добавить безопасный tool в LangChain-агента для проверки статуса заказа
Декоратор @tool, схема аргументов, серверная проверка заказа и отрицательные тесты на чужой ID.
Как обработать несколько независимых запросов через LangChain model.batch
Параллельная обработка независимых промптов, max_concurrency, порядок batch и отличие от batch API провайдера.
Как ограничить число вызовов модели в LangChain-агенте
ModelCallLimitMiddleware: run_limit, thread_limit, checkpointer и тест runaway-цикла без обещания фиксированных затрат.
Комментарии
Пока тихо. Скажите первое слово