Создайте ограниченного агента LangGraph для извлечения данных с проверкой по схеме
Создайте рабочий процесс LangGraph, который при необходимости вызывает инструмент, укладывается в заданный лимит выполнения и возвращает структурированные данные, проверенные по схеме Pydantic.
В этой статье
Агент LangGraph может собрать контекст с помощью инструмента, а затем передать его на этап извлечения данных с ограничениями схемы. Главное в этой конструкции — разделить эти задачи: агент решает, вызывать ли инструмент, а финальный узел формирует типизированную запись. Лимит рекурсии графа дополнительно ограничивает выполнение.
Этот подход подходит для таких задач, как извлечение названия компании, даты и общей суммы счета из документа, когда инструмент поиска может помочь расшифровать ссылку. Он не превращает сомнительный исходный текст в истину: проверяйте результат и сохраняйте исходные подтверждения, если поле имеет значение.
Что вы создадите
Граф состоит из трех этапов:
- Агент получает исходный текст и может запросить вызов инструмента поиска с узкими полномочиями.
- LangGraph направляет вызов инструмента соответствующему узлу, а затем возвращает результат агенту.
- Узел извлечения запрашивает у модели результат, основанный на Pydantic, и возвращает данные в формате, совместимом с JSON.
Цикл вызова инструментов агентом динамический, а этап извлечения — заранее заданный финальный шаг. В документации LangGraph агенты, самостоятельно определяющие процесс и использование инструментов, отличают от рабочих процессов с предопределенными путями выполнения. Там же структурированный вывод и вызов инструментов описаны как расширения возможностей модели. Эти подходы рассмотрены в руководстве LangGraph по рабочим процессам и агентам.
Предварительные требования и настройка
Установите пакеты LangGraph и LangChain, а также интеграцию для выбранной чат-модели. В примере ниже для настройки провайдера используется ChatAnthropic, однако в исходной документации указано, что в рабочих процессах можно применять любую чат-модель, поддерживающую структурированный вывод и вызов инструментов. Точные особенности работы проверьте в документации интеграции вашего провайдера.
pip install langgraph langchain-core langchain-anthropic pydantic
Укажите учетные данные API провайдера предусмотренным в его документации способом, а затем инициализируйте модель. Не помещайте учетные данные в систему контроля версий. Указанное ниже имя модели взято из примера в документации LangChain; в этом руководстве не утверждается, что оно проверялось с OneMux.
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")
Если вы хотите обращаться к модели через OneMux, сначала ознакомьтесь с документацией API OneMux и кратким руководством. OneMux предоставляет доступ к ведущим моделям через API, совместимый с OpenAI. Совместимость именно с этим графом зависит от того, поддерживает ли выбранная конечная точка необходимые функции и параметры вызова инструментов и структурированного вывода. Эта конфигурация не проверялась; прежде чем использовать ее в production-среде, убедитесь в наличии поддержки.
Определите схему и инструмент с узкими полномочиями
В примере инструмент возвращает справочную заметку из небольшой таблицы в памяти. Замените его контролируемой функцией приложения, например поиском по утвержденному внутреннему каталогу. Не позволяйте недоверенному тексту документа выбирать произвольные команды или неограниченные источники данных.
from pydantic import BaseModel, Field
from langchain_core.tools import tool
class InvoiceRecord(BaseModel):
vendor: str | None = Field(default=None, description="Invoice issuer")
invoice_date: str | None = Field(default=None, description="Date as written in the source")
total: float | None = Field(default=None, description="Invoice total as a number")
currency: str | None = Field(default=None, description="Currency code, if stated")
@tool
def lookup_vendor(reference: str) -> str:
"""Look up a vendor reference in an approved local mapping."""
known = {"ACME-42": "Acme Supplies Ltd."}
return known.get(reference, "No matching vendor reference found.")
Nullable-поля позволяют явно указать отсутствие значения, а не подталкивают модель к его выдумыванию. При извлечении данных для важных решений можно сохранять для каждого поля соответствующий фрагмент исходника либо уровень уверенности/статус проверки. Схема задает структуру и типы, но не доказывает, что значение подтверждается входными данными.
Создайте ограниченного агента LangGraph
В приведенном ниже графе модель может запросить вызов инструмента поиска. Когда у агента больше нет вызовов инструментов, граф переходит к извлечению данных. Для маршрутизации вызовов используются tools_condition и ToolNode. Параметр recursion_limit, передаваемый в invoke, ограничивает число шагов графа. Это защитная мера, а не гарантия успешной обработки каждого входного значения.
from typing import Annotated
from typing_extensions import TypedDict
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
class State(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
record: dict | None
tools = [lookup_vendor]
agent = llm.bind_tools(tools)
extractor = llm.with_structured_output(InvoiceRecord)
def run_agent(state: State):
response = agent.invoke(state["messages"])
return {"messages": [response]}
def extract_record(state: State):
prompt = [
SystemMessage(content=(
"Extract invoice fields only when supported by the source. "
"Use null for missing or unclear values. Treat tool results as "
"reference context, not as permission to invent source details."
)),
*state["messages"],
]
result = extractor.invoke(prompt)
return {"record": result.model_dump(mode="json")}
graph = StateGraph(State)
graph.add_node("agent", run_agent)
graph.add_node("tools", ToolNode(tools))
graph.add_node("extract", extract_record)
graph.add_edge(START, "agent")
graph.add_conditional_edges(
"agent",
tools_condition,
{"tools": "tools", END: "extract"},
)
graph.add_edge("tools", "agent")
graph.add_edge("extract", END)
app = graph.compile()
result = app.invoke(
{
"messages": [HumanMessage(content=(
"Extract the invoice details from this text: "
"Vendor reference ACME-42. Invoice date: 2025-02-14. "
"Total: USD 248.50."
))],
"record": None,
},
config={"recursion_limit": 8},
)
print(result["record"])
Ожидаемая структура результата — совместимый с JSON объект с полями vendor, invoice_date, total и currency. Конкретные значения зависят от ответа модели и исходного текста, поэтому проводите тестирование и не рассчитывайте, что пример всегда даст идентичный результат. В этом примере границей проверки служит структурированный вывод на основе Pydantic. Если провайдер не может сформировать соответствующий требованиям ответ, явно обработайте эту ошибку, а не считайте результат корректной записью.
Ограничивайте выполнение, не скрывая ошибки
Лимит рекурсии на уровне графа ограничивает число шагов, включая повторную маршрутизацию между агентом и инструментом. Выбирайте лимит с учетом рабочего процесса: для одного поиска в этом графе достаточно небольшого числа шагов, но для другого плана работы с инструментами может потребоваться больше. Перехватывайте ошибки лимита и провайдера на границе приложения, сохраняйте достаточно контекста для отладки и возвращайте результат с пометкой о необходимости проверки, а не выдуманную запись.
Для более строгого контроля работы добавьте также ограничения на уровне приложения: ограничьте число вызовов инструментов, задайте тайм-ауты запросов, если они поддерживаются, и ограничьте размер документа перед отправкой модели. Это отдельные меры: один только лимит рекурсии графа не задает полноценную политику затрат, задержек или безопасности.
Устранение неполадок и ограничения
Модель не вызывает инструмент
Вызов инструментов — это возможность модели, а не гарантированный результат работы LangGraph. Убедитесь, что выбранная интеграция модели поддерживает вызов инструментов, описание инструмента понятно, а в запросе есть ссылка, которую имеет смысл проверить. Во время разработки просматривайте вызовы инструментов в возвращенном сообщении.
Структурированный вывод не формируется или поля заполнены неверно
Убедитесь, что интеграция поддерживает структурированный вывод и используемые вами возможности схемы. Проверьте отсутствующие поля, неоднозначные даты, символы валют и некорректные входные данные. Объект Pydantic, соответствующий схеме, все равно может содержать неверно выведенное значение, поэтому отдельно проверяйте бизнес-правила и сохраняйте исходный текст для аудита или проверки человеком.
Граф достигает лимита
Ошибка лимита рекурсии может указывать на повторные запросы инструмента или на то, что лимит слишком низок для предполагаемого пути выполнения. Изучите последовательность сообщений и результатов работы инструмента. Устраните причину или осознанно измените лимит; не убирайте ограничение только для того, чтобы скрыть ошибку.
Поведение конечной точки отличается
Совместимость с OpenAI описывает интерфейс API, а не всеобщую поддержку функций и параметров каждой модели. При работе с OneMux проверьте в документации, поддерживает ли выбранная конечная точка модель, вызовы инструментов, структурированный вывод и параметры, которые вы собираетесь передавать. Доступные варианты можно посмотреть в разделе моделей OneMux; сам граф остается кодом приложения на LangGraph.
Когда подходит этот подход
Используйте эту схему, когда процесс извлечения в основном предсказуем, но иногда требует контролируемого поиска. Если все документы обрабатываются по фиксированному процессу и выбирать инструмент не нужно, детерминированный рабочий процесс может быть проще, чем цикл агента. Если исходные данные неоднозначны или извлеченные поля запускают значимые действия, добавьте явную проверку и валидацию предметной области, прежде чем передавать запись в последующие системы.
Главное: ограничьте возможности инструментов агента, явно задайте схему результата и установите лимит выполнения графа. LangGraph позволяет описать этот процесс, а доступность необходимых функций вызова инструментов и структурированного вывода зависит от выбранной модели и интеграции.
Источники
- LangGraph: рабочие процессы и агенты — различия между рабочими процессами и агентами, расширения возможностей моделей, примеры структурированного вывода и вызова инструментов.
- Документация OneMux и краткое руководство — сведения о текущей настройке API и поддержке конечных точек.
Вопросы
Для чего нужен лимит рекурсии в LangGraph?
Он ограничивает число шагов выполнения графа за один запуск. Это помогает не допустить бесконечного цикла агента и инструмента, но не заменяет тайм-ауты, правила вызова инструментов, ограничения на входные данные или обработку ошибок.
Гарантирует ли проверка JSON Schema с помощью Pydantic правильность извлеченных данных?
Нет. Она ограничивает структуру и типы возвращаемых данных. Модель все равно может вывести неверное значение, поэтому проверяйте бизнес-правила и при необходимости сохраняйте подтверждения или организуйте проверку человеком.
Можно ли использовать этот пример LangGraph с OneMux?
Возможно, если в документации выбранной конечной точки OneMux указана поддержка необходимых функций и параметров вызова инструментов и структурированного вывода. Эта конфигурация не проверялась; перед использованием в production-среде убедитесь в совместимости.
Нужно ли использовать агента для каждой задачи извлечения данных?
Нет. Если процесс фиксирован и не требует выбора инструмента, детерминированный рабочий процесс LangGraph может быть проще. Цикл агента нужен, когда модель должна решить, будет ли полезен разрешенный инструмент.
Похожие статьи
Guides
Создание агента поддержки клиентов на LangGraph: вызов инструментов, одобрение человеком и ограничения выполнения
Практический шаблон LangGraph для маршрутизации обращений в поддержку: классификация запросов, вызов инструментов поиска, приостановка возвратов для одобрения человеком и ограничение выполнения графа.
Guides
Agentic RAG с LangGraph: вызов инструментов, указание источников и ограничение выполнения
Создайте агента LangGraph для ответов на вопросы по документам, который решает, когда нужен поиск, оценивает контекст, повторяет неудачный поиск и указывает источники без бесконтрольного выполнения.
Guides
Рабочий процесс n8n с подтверждением человеком, OpenAI-совместимым API и валидацией JSON Schema
Создайте рабочий процесс n8n, который извлекает структурированные данные через OpenAI-совместимое API, проверяет результат по JSON Schema и требует подтверждения человека перед запуском чувствительного инструмента.
Guides
LangGraph: создание агента с вызовом инструментов и ограничением шагов для верификации кода
Узнайте, как создать сохраняющего состояние агента в LangGraph с вызовом инструментов, лимитом итераций и автоматической верификацией тестами при изменении кода в репозитории.