Обработка исключений LangGraph ToolException в REPLPython

Программы на Python
Ответить
Anonymous
 Обработка исключений LangGraph ToolException в REPL

Сообщение Anonymous »

У меня есть агент LangGraph, который должен взаимодействовать с пользователем в многоэтапных диалогах и вносить изменения в среду Kubernetes. Я использую внешний сервер протокола контекста модели для предоставления инструментов для взаимодействия с конфигурацией k8s, и на данный момент моя конструкция агента представляет собой просто функцию LangChain create_agent.

Теперь агент может использовать инструменты неправильно (например, пытаясь удалить несуществующий модуль k8s), и инструмент вызовет исключение ToolException, описание которого может помочь модели в уточнении ее подхода. Поскольку для состояния агента требуется ToolMessage, соответствующий каждому AIMessage, который соответствует вызову инструмента, я хочу перехватить исключение и добавить его описание в качестве ответа ToolMessage в состоянии агента. Однако я получаю сообщение об ошибке, которую сложно отладить, что говорит о том, что я делаю это неправильно.
Вот код моего агента:

Код: Выделить всё

from langchain.agents import create_agent
from langchain_core.messages import BaseMessage
from langchain.messages import ToolMessage, AIMessage
from langgraph.graph import MessagesState
from langgraph.checkpoint.memory import InMemorySaver
from langchain.tools import ToolException

class MyAgent:
def __init__(self):
model = ...
tools = []

self.config = {...}

self.agent = create_agent(
model,
tools=tools,
state_schema=MessagesState,
checkpointer=InMemorySaver()
)

def run(self,cmd:dict) ->  BaseMessage:
try:
result = self.agent.invoke(cmd,self.config)
return result["messages"][-1]
except ToolException as expt:

# ERROR HANDLING
# get state snapshot to find out tool call id
snapshot = self.agent.get_state(self.config)
last_tool_call = snapshot.values["messages"][-1].tool_calls[0]
# compose toolmessage to signal the error
error_tool_message = ToolMessage(
content=f"Couldn't execute tool because of: {expt}",
tool_call_id=last_tool_call["id"]
)

# ERROR COMES FROM HERE
# update the state
self.agent.update_state(
self.config,
{"messages":[error_tool_message]}
)

# return error notification to the user
return AIMessage(
f"Couldn't execute because of tool error: {expt}"
)
Когда я пытаюсь запустить агент с сообщением, в котором его просят удалить несуществующий модуль, я получаю следующее сообщение об ошибке:

Код: Выделить всё

Traceback (most recent call last):
File "/home/ubuntu/dev/elster/src/elster/agent.py", line 144, in run
result = self.event_loop.run_until_complete(
self.agent.ainvoke(cmd,config=self.config)
)
File "/home/ubuntu/.local/share/uv/python/cpython-3.13.9-linux-x86_64-gnu/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/main.py", line 3182, in ainvoke
async for chunk in self.astream(
......
chunks.append(chunk)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/main.py", line 3000, in astream
async for _ in runner.atick(
......
yield o
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/_runner.py", line 304, in atick
await arun_with_retry(
......
)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/_retry.py", line 137, in arun_with_retry
return await task.proc.ainvoke(task.input, config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/_internal/_runnable.py", line 705, in ainvoke
input = await asyncio.create_task(
^^^^^^^^^^^^^^^^^^^^^^^^^^
step.ainvoke(input, config, **kwargs), context=context
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/_internal/_runnable.py", line 473, in ainvoke
ret = await self.afunc(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 733, in _afunc
outputs = await asyncio.gather(*coros)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 1066, in _arun_one
return await self._execute_tool_async(tool_request, input_type, config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 1015, in _execute_tool_async
content = _handle_tool_error(e, flag=self._handle_tool_errors)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 389, in _handle_tool_error
content = flag(e)  # type:  ignore [assignment, call-arg]
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 352, in _default_handle_tool_errors
raise e
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain/tools/tool_node.py", line 970, in _execute_tool_async
response = await tool.ainvoke(call_args, config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/tools/structured.py", line 63, in ainvoke
return await super().ainvoke(input, config, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/tools/base.py", line 601, in ainvoke
return await self.arun(tool_input, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/tools/base.py", line 969, in arun
raise error_to_raise
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/tools/base.py", line 938, in arun
response = await coro_with_context(coro, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/tools/structured.py", line 117, in _arun
return await self.coroutine(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_mcp_adapters/tools.py", line 292, in call_tool
return _convert_call_tool_result(call_tool_result)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_mcp_adapters/tools.py", line 80, in _convert_call_tool_result
raise ToolException(tool_content)
langchain_core.tools.base.ToolException: failed to delete pod aaa in namespace : pods "aaa"  not found
During task with name 'tools' and id '8fb89a71-87c5-ea74-9154-9fbc2b3b2503'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ubuntu/.local/share/uv/python/cpython-3.13.9-linux-x86_64-gnu/lib/python3.13/runpy.py", line 198, in _run_module_as_main
return _run_code(code, main_globals, None,
"__main__", mod_spec)
File "/home/ubuntu/.local/share/uv/python/cpython-3.13.9-linux-x86_64-gnu/lib/python3.13/runpy.py", line 88, in _run_code
exec(code, run_globals)
~~~~^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 71, in 
cli.main()
~~~~~~~~^^
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 508, in main
run()
~~~^^
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 358, in run_file
runpy.run_path(target, run_name="__main__")
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 310, in run_path
return _run_module_code(code, init_globals, run_name, pkg_name=pkg_name, script_name=fname)
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 127, in _run_module_code
_run_code(code, mod_globals, init_globals, mod_name, mod_spec, pkg_name, script_name)
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/.vscode-server/extensions/ms-python.debugpy-2025.14.1-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 118, in _run_code
exec(code, run_globals)
~~~~^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/src/elster/main.py", line 104, in 
main()
~~~~^^
File "/home/ubuntu/dev/elster/src/elster/main.py", line 97, in main
msg = agent.run(cmd)["messages"][-1]
~~~~~~~~~^^^^^
File "/home/ubuntu/dev/elster/src/elster/agent.py", line 155, in run
self.agent.update_state(self.config,{"messages":[error_tool_message]})
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/main.py", line 2359, in update_state
return self.bulk_update_state(config, [[StateUpdate(values, as_node, task_id)]])
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/main.py", line 1883, in bulk_update_state
current_config = perform_superstep(current_config, superstep)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/pregel/main.py", line 1818, in perform_superstep
run.invoke(
~~~~~~~~~~^
values,
^^^^^^^
......
),
^^
)
^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langchain_core/runnables/base.py", line 3090, in invoke
input_ = context.run(step.invoke, input_, config)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/_internal/_runnable.py", line 400, in invoke
ret = self.func(*args, **kwargs)
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/graph/_branch.py", line 167, in _route
return self._finish(writer, input, result, config)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/dev/elster/.venv/lib/python3.13/site-packages/langgraph/graph/_branch.py", line 203, in _finish
r if isinstance(r, Send) else self.ends[r] for r in result
~~~~~~~~~^^^
KeyError: 'model'
Что я здесь делаю неправильно?


Подробнее здесь: https://stackoverflow.com/questions/798 ... -in-a-repl
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»