Практичні поради: Стрімування відповідей у LangGraph: 3 практичні патерни, які кожен
Покрокове пояснення до практичних порад: стрімінг відповідей у LangGraph: 3 практичні шаблони, контракти, перевірки та готові блоки коду для команд, які використовують цей шаблон.
У цьому посібнику детально описано шлях від сировини до функціональної системи для: Стрімування відповідей у LangGraph: 3 практичні патерни, які має знати кожен розробник агентів. Основна увага приділяється конкретним крокам виконання, чітким перевіркам та коду, який можна просто додати до репозиторію, не намагаючись здогадатися про мету. На етапі огляду необхідно визначити вхідні дані, виконавця кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись зрозуміти прихований стан. Необхідно одночасно задокументувати шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
Чому стрімування має більше значення, ніж думають люди
Під час роботи над етапом «Чому стрімінг має більше значення» спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Робіть перевірки після дорогих кроків. Система відновлення не повинна знову оплачувати один і той самий виклик LLM, коли оператор намагається виконати пізнішу операцію.
Приклад, над яким ми працюємо
Під час роботи над етапом «Приклад, який ми створюємо», спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Дайте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання. Робіть перевірки після дорогих кроків. Система відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається знову виконати пізнішу операцію.
import asyncio
import operator
from typing import Annotated, TypedDict
from dotenv import load_dotenv
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph
load_dotenv()
# --- 1. STATE & GRAPH ---
class State(TypedDict):
messages: Annotated[list[BaseMessage], operator.add]
llm = ChatOpenAI(model="gpt-4o-mini", streaming=True)
def chatbot_node(state: State) -> dict:
return {"messages": [llm.invoke(state["messages"])]}
def dummy_node(state: State) -> State:
return state
builder = StateGraph(State)
builder.add_node("chatbot", chatbot_node)
builder.add_node("dummy", dummy_node)
builder.add_edge(START, "chatbot")
builder.add_edge("chatbot", "dummy")
builder.add_edge("dummy", END)
graph = builder.compile()
# --- 2A. stream_mode="updates" — one event per node ---
print("=== Method 1: stream_mode='updates' ===")
for event in graph.stream(
{
"messages": [HumanMessage("List 3 benefits of LangGraph in one line each")],
},
stream_mode="updates",
):
for node_name, output in event.items():
print(f" [{node_name}] {output['messages']}")
# --- 2B. stream_mode="values" — full state after each node ---
print("\n=== Method 2: stream_mode='values' ===")
for snapshot in graph.stream(
{
"messages": [HumanMessage("Say hello in 3 languages")],
},
stream_mode="values",
):
print(f" State has {len(snapshot['messages'])} message(s) now")
print(snapshot["messages"])
# --- 2C. astream_events — token-by-token (async) ---
async def token_stream():
print("\n=== Method 3: Token-by-token streaming ===")
print("🤖 Bot: ", end="", flush=True)
async for event in graph.astream_events(
{
"messages": [HumanMessage("Count from 1 to 5 slowly, one per line")],
},
version="v2",
):
if event["event"] == "on_chat_model_stream":
chunk = event["data"]["chunk"].content
if chunk:
print(chunk, end="", flush=True)
print()
asyncio.run(token_stream())
Крок 1: Спочатку зрозумійте проектування стану
Під час виконання кроку 1 «Розуміння етапу» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із результатами функціонування. Відображення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ. Робіть контрольні пункти після дорогих кроків. Система повторного запуску не повинна знову стягувати плату за один і той самий виклик ШІ, якщо оператор намагається знову виконати пізніший етап. Під час виконання кроку 1 «Розуміння етапу» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Одночасно задокументуйте оптимальний та альтернативний шляхи виконання. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
class State(TypedDict):
messages: Annotated[list[BaseMessage], operator.add]
{"messages": [some_new_message]}
Чому це важливо для стрімінгу
Підхід «Чому це важливо для стрімінгу» працює найкраще, коли його розглядають як вимірювану структуру. Збережіть один ідеальний зразок транскрипції, один випадок невдачі та примітки щодо скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну послідовність дій. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
Крок 2: Сам граф спеціально розроблений простим
Етап 2 «Граф» працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад роботи, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
chatbot_node
Етап chatbotnode працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис розмови, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-версії до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють відновлення після перерв. Етап chatbotnode працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис розмови, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний шляхи роботи. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
def chatbot_node(state: State) -> dict:
return {"messages": [llm.invoke(state["messages"])]}
dummy_node
На етапі dummynode необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру процесу. Встановлюйте людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функціоналу.
def dummy_node(state: State) -> State:
return state
START → chatbot → dummy → END
Метод 1: stream_mode="updates"
На етапі оновлень у режимі потоку Методу 1 необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементів, визначте критерії успіху та не допускайте беззвучного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повності бізнес-процесу.
for event in graph.stream(..., stream_mode="updates"):
Що він робить
На етапі „Що воно робить“ необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Встановлюйте людське схвалення для кроків, які спричиняють витрати чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повності функціоналу продукту. На етапі „Що воно робить“ необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Документуйте як оптимальний, так і альтернативний шлях виконання. Повторні спроби, людське схвалення та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
{
"chatbot": {
"messages": [...]
}
}
{
"dummy": {
"messages": [...]
}
}
Чому цей режим корисний
Під час роботи над етапом «Чому цей режим корисний» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну послідовність операцій. Робіть перевірки після дорогих кроків. Функція відновлення не повинна знову оплачувати один і той самий виклик LLM, коли оператор намагається виконати пізнішу операцію.
Найкращі сценарії використання
Під час роботи над етапом «Найкращі сценарії використання» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового виконання завдань. Робіть перевірки після дорогих кроків. Система повернення до виконання не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається виконати наступний етап.
Приклад з реального життя
Під час роботи над етапом прикладу з реального світу спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних середовищ. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізніший етап. Під час роботи над етапом прикладу з реального світу спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Перезапуски, людські перевірки та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
Метод 2: stream_mode="values"
Значення режиму потоку Method 2 у режимі stage найкраще функціонують, якщо їх розглядати як вимірювану поверхню. Збережіть один ідеальний зразок результату, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.
for snapshot in graph.stream(..., stream_mode="values"):
Що він робить
Етап «Що він робить» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад роботи, один випадок збою та примітку про скасування змін перед розширенням обсягу завдань. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
print(f" State has {len(snapshot['messages'])} message(s) now")
print(snapshot["messages"])
Чому це важливо
Етап «Чому це важливо» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат на ранньому етапі запобігає несподіваним рахункам під час переходу від демо-версії до спільних середовищ. Зберігайте стан графа у простому та типованому вигляді. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв. Етап «Чому це важливо» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний шляхи роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
Найкращі сценарії використання
На етапі найкращих сценаріїв використання необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру процесу. Необхідно встановити людське схвалення для кроків, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення елементів під час компіляції не є гарантією повноти бізнес-функціоналу.
Приклад з реального життя
На етапі прикладу з реального світу необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви для кожного елемента, визначте критерії успіху та не допускайте мовчазного часткового завершення. Необхідно забезпечити людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Компіляційне підключення елементів не є гарантією повноти виконання завдань у бізнес-сенсі.
Метод 3: astream_events() для потокової обробки токенів по одному
Для astreamevents методу 3 для етапу необхідно визначити вхідні дані, власника кроку та критерії завершення ще до зміни коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища. У разі, коли наступним кроком є код або виклик інструменту, краще використовувати структуровані результати з перевіркою схеми, ніж вільний текст. Для astreamevents методу 3 для етапу необхідно визначити вхідні дані, власника кроку та критерії завершення ще до зміни коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Документуйте як успішний, так і відновлювальний сценарії роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
async for event in graph.astream_events(..., version="v2"):
if event["event"] == "on_chat_model_stream":
chunk = event["data"]["chunk"].content
Що воно робить
Під час роботи над етапом «Що воно робить» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну послідовність операцій. Робіть перевірки після дорогих кроків. Система повторного запуску не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається знову виконати пізніший етап.
Чому це важливо
Під час роботи над етапом «Чому це важливо», спочатку запишіть умови договору: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як договір між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового виконання. Робіть перевірки після дорогих кроків. Система повернення до виконання не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор намагається виконати наступний етап.
Чому astream_events() є асинхронним
Під час роботи над етапом «Чому astreamevents є асинхронним» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени чи запити поруч із функціональними результатами. Відображення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізніший етап. Під час роботи над етапом «Чому astreamevents є асинхронним» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Перезапуски, людські перевірки та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
asyncio.run(token_stream())
Розуміння фільтра подій
Етап розуміння фільтра подій працює найкраще, якщо його розглядати як вимірювану структуру. Спочатку збережіть один ідеальний запис, один випадок збою та примітки щодо скасування змін, перш ніж розширювати обсяг роботи. Віддавайте перевагу невеликим, тестованим одиницям коду замість об’ємних скриптів. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну послідовність операцій. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
if event["event"] == "on_chat_model_stream":
chunk = event["data"]["chunk"].content
3 режими стрімування простою мовою
Етап 3 режимів стрімінгу працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад виконання, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Зберігайте стан графа у простій та типованій формі. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що ускладнює продовження роботи після перерв.
updates
Етап оновлень працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Зберігайте стан графа у випрямленому та типованому форматі. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, і ускладнюють продовження роботи після перерв. Етап оновлень працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний шляхи роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
values
На етапі визначення значень необхідно спочатку визначити вхідні дані, відповідальну особу за крок та критерії завершення, перш ніж змінювати код. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру процесу. Необхідно включати людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення елементів під час компіляції не є гарантією повноти бізнес-функціоналу.
astream_events
Для етапу astreamevents необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви результатів роботи, визначте критерії успіху та не допускайте мовчазного часткового завершення. Вимагайте людського схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повності виконання завдань у бізнес-сенсі.
Який режим стрімінгу вам слід використовувати?
Для визначення режиму стрімінгу, який слід використовувати, необхідно перед зміною коду визначити вхідні дані, власника кроку та критерії завершення. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища. Встановлюйте людське схвалення для кроків, які спричиняють витрати чи змінюють дані у продакшені. Підключення під час компіляції не є гарантією повноти функціоналу продукту. Для визначення режиму стрімінгу, який слід використовувати, необхідно перед зміною коду визначити вхідні дані, власника кроку та критерії завершення. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Документуйте як оптимальний, так і альтернативний шляхи виконання. Повторні спроби, людське схвалення та обробка некоректних повідомлень є частиною продукту, а не етапами подальшої оптимізації.
.Використовуйте updates, коли:
Під час роботи над етапом «Використовуйте оновлення», спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову оплачувати один і той самий виклик LLM, коли оператор намагається виконати наступний етап.
Використовуйте values, коли:
Під час роботи над розділом «Використання значень на етапі» спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте безпроблемного часткового завершення. Робіть перевірки після дорогих кроків. Система відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор намагається знову виконати пізніший етап.
Використовуйте astream_events, коли:
Під час роботи над етапом «Use astreamevents when stage» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із результатами функціоналу. Відображення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізніший етап. Під час роботи над етапом «Use astreamevents when stage» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Перезапуски, людські перевірки та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.
Kраща ментальна модель: стрімінг для користувачів проти стрімінгу для розробників
Етап «Краща ментальна модель» працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи.
Стрімінг для користувачів
Стрімінг для розробників
Шаблон для продакшну, який вам, ймовірно, знадобиться
Поширені помилки під час стрімінгу відповідей LangGraph
1. Використання стрімінгу токенів, коли насправді потрібні оновлення вузлів
2. Очікування того, що values будуть поводитися як стрімінг токенів
3. Забування про те, що astream_events() є асинхронним
4. Відсутність фільтрації типів подій
5. Створення графів, які стрімлять дані, але не відображають значущий стан
Продвинутий порада: стрімінг стає набагато потужнішим у багатокрокових графах агентів
updates
values
astream_events
for event in graph.stream(
{
"messages": [HumanMessage("List 3 benefits of LangGraph in one line each")],
},
stream_mode="updates",
):
for node_name, output in event.items():
print(f"\nNode: {node_name}")
for message in output["messages"]:
print(message)
- Практичні нотатки: створення системи перегляду коду для багатьох агентів за допомогою LangGraph — Детальний посібник з практичних нотаток щодо створення такої системи: контракти, перевірки та готові блоки коду для команд, які використовують цю модель.
for event in graph.stream(
{
"messages": [HumanMessage("List 3 benefits of LangGraph in one line each")],
},
stream_mode="updates",
):
for node_name, output in event.items():
print(f"\nNode: {node_name}")
for message in output["messages"]:
print(message)