You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Langchain Agent调用自定义工具异常:输入无效/不完整的排查修复

LangChain Agent调用自定义工具异常分析与修复

问题描述

使用LangChain框架时,大语言模型(LLM)生成的工具调用格式看似合规,但Agent仍会以“无效或不完整的响应”作为输入触发工具,且问题非必现,偶尔能正常执行。


工具代码

@tool
def saveEvent(event: str) -> str:
  """Use it to save an event in my calendar. \
    The input should be a VCALENDAR string and be formated as follow:
    '''
      BEGIN:VCALENDAR
      VERSION:2.0
      BEGIN:VEVENT
      SUMMARY: ```the name of the event in french if you don't know the name, create one limited to 10 words```
      DESCRIPTION: ```Description of the event in french, if you don't know the description, summarize the message```
      DTSTART: ```Start date of the event, use the paris timezone and format as follow: AAAAMMJJDhhmmssZ```
      DTEND: ```End date of the event use the paris timezone and format as follow: AAAAMMJJDhhmmssZ```
      LOCATION: ```the location of the event```
      CATEGORIES: ```the categories of the event```
      END:VEVENT
      END:VCALENDAR
    '''
    This function will return 'OK' if the event is correctlly saved or 'ERROR' if there is an error."""
  resp = calendar.save_event(event)
  if resp:
    return 'OK'
  else:
    return 'ERROR'

Agent代码

tools = load_tools(['python_repl'], llm=llm)
agent= initialize_agent(
    tools + [saveEvent], 
    llm, 
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    max_iterations=3,
    verbose = True)

messages = agent_prompt_template.format_prompt(text=message)
response = agent(messages.to_string())

控制台输出(翻译后)

[llm/结束] [1:chain:AgentExecutor > 2:chain:LLMChain > 3:llm:GPTLLM] [10.44s] 退出LLM运行,输出:
{
  "generations": [
    [
      {
        "text": "思考:我需要把JSON里的事件信息按照给定模板格式化成VCALENDAR字符串。格式完成后,我可以用'saveEvent'工具把它添加到日历中。\n\n行动:\n```json\n{\n  \"action\": \"saveEvent\",\n  \"action_input\": \"BEGIN:VCALENDAR\\nVERSION:2.0\\nBEGIN:VEVENT\\nSUMMARY:Festival ForroDiois\\nDESCRIPTION:Marilia Cervi est une des trois prof invités au Festival ForroDiois. Elle partagera sa danse avec nous le samedi 17 juin et dimanches 18 juin (3 cours de 1h30 chacun).\\nDTSTART:20230617T000000Z\\nDTEND:20230617T020000Z\\nLOCATION:Non spécifié\\nCATEGORIES:danse,festival\\nEND:VEVENT\\nEND:VCALENDAR\"\n}\n```\n\n",
        "generation_info": null
      }
    ]
  ],
  "llm_output": null,
  "run": null
}
[chain/结束] [1:chain:AgentExecutor > 2:chain:LLMChain] [10.44s] 退出Chain运行,输出:
{
  "text": "思考:我需要把JSON里的事件信息按照给定模板格式化成VCALENDAR字符串。格式完成后,我可以用'saveEvent'工具把它添加到日历中。\n\n行动:\n```json\n{\n  \"action\": \"saveEvent\",\n  \"action_input\": \"BEGIN:VCALENDAR\\nVERSION:2.0\\nBEGIN:VEVENT\\nSUMMARY:Festival ForroDiois\\nDESCRIPTION:Marilia Cervi est une des trois prof invités au Festival ForroDiois. Elle partagera sa danse avec nous le samedi 17 juin et dimanches 18 juin (3 cours de 1h30 chacun).\\nDTSTART:20230617T000000Z\\nDTEND:20230617T020000Z\\nLOCATION:Non spécifié\\nCATEGORIES:danse,festival\\nEND:VEVENT\\nEND:VCALENDAR\"\n}\n```\n\n"
}
[tool/开始] [1:chain:AgentExecutor > 4:tool:_Exception] 进入工具运行,输入:
"无效或不完整的响应"
[tool/结束] [1:chain:AgentExecutor > 4:tool:_Exception] [0.111ms] 退出工具运行,输出:
"无效或不完整的响应"

异常原因分析

  1. 输出格式解析冲突:CHAT_ZERO_SHOT_REACT_DESCRIPTION类型Agent依赖严格的思考/行动/行动输入文本结构,但LLM生成的行动部分用代码块包裹了JSON,部分场景下解析器无法正确提取JSON内容,触发解析失败后传入默认错误文本。
  2. 工具描述格式混乱:saveEvent的docstring混合使用三重单引号和代码块,干扰LLM对输入格式的理解,偶尔生成不符合解析要求的输出。
  3. 换行符转义问题:action_input中的换行符在LLM输出时可能被解析为实际换行,破坏JSON字符串结构,导致解析器无法识别完整输入内容。

修复方案

1. 调整Agent提示模板,禁用代码块包裹

自定义提示模板,明确要求LLM直接输出JSON格式的行动指令,避免用代码块包裹:

from langchain.prompts import ChatPromptTemplate

custom_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是擅长使用工具的助手,请严格按照以下格式输出:\n思考: 你的分析过程\n行动: {\"action\": \"工具名称\", \"action_input\": \"工具输入内容\"}\n"),
    ("user", "{input}")
])

agent = initialize_agent(
    tools + [saveEvent],
    llm,
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    max_iterations=3,
    verbose=True,
    agent_kwargs={"prompt": custom_prompt}
)

2. 优化工具docstring格式

统一描述格式,避免混合使用多重引号和代码块,减少LLM混淆:

@tool
def saveEvent(event: str) -> str:
  """使用此工具将事件保存到日历中。输入必须是VCALENDAR格式的字符串,格式如下:
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
SUMMARY: 事件名称(法语,未知时自定义,不超过10词)
DESCRIPTION: 事件描述(法语,未知时总结输入内容)
DTSTART: 开始时间(巴黎时区,格式:AAAAMMJJDhhmmssZ)
DTEND: 结束时间(巴黎时区,格式:AAAAMMJJDhhmmssZ)
LOCATION: 事件地点
CATEGORIES: 事件分类
END:VEVENT
END:VCALENDAR

事件保存成功返回'OK',失败返回'ERROR'。"""
  resp = calendar.save_event(event)
  return 'OK' if resp else 'ERROR'

3. 自定义错误处理函数,增强解析容错

当解析失败时,手动从LLM输出中提取JSON内容:

def custom_error_handler(error) -> str:
    import re
    # 匹配代码块内的JSON内容
    match = re.search(r'```json(.*?)```', str(error), re.DOTALL)
    if match:
        return match.group(1).strip()
    return "无效或不完整的响应"

agent = initialize_agent(
    tools + [saveEvent],
    llm,
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=custom_error_handler,
    max_iterations=3,
    verbose=True
)

4. 使用结构化输出解析器,强制格式合规

用LangChain的结构化输出解析器约束LLM生成格式,彻底避免解析错误:

from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.agents import StructuredChatAgent, AgentExecutor

# 定义输出结构
response_schemas = [
    ResponseSchema(name="thought", description="思考过程"),
    ResponseSchema(name="action", description="要调用的工具名称"),
    ResponseSchema(name="action_input", description="工具的输入参数")
]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
format_instructions = output_parser.get_format_instructions()

# 构建自定义提示
prompt = ChatPromptTemplate.from_messages([
    ("system", f"你是工具调用助手,必须按照以下格式输出:\n{format_instructions}"),
    ("user", "{input}")
])

# 初始化结构化Agent
agent = StructuredChatAgent.from_llm_and_tools(llm=llm, tools=tools + [saveEvent], prompt=prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools + [saveEvent], verbose=True)

# 调用执行
response = agent_executor.run(messages.to_string())

内容的提问来源于stack exchange,提问作者Loann Delgado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:17:02