如何让Langchain Structured_Chat_Zero_Shot_Description Agent调用自定义工具?
- 结构化输出格式不匹配:Structured_Chat_Zero_Shot_Description Agent要求模型输出严格的JSON格式工具调用指令,若prompt未明确指定格式要求,或工具参数schema定义模糊,模型可能仅输出自然语言描述的调用指令,而非可被Agent解析执行的结构化内容。
- Agent配置缺失:未正确设置stop序列或prompt模板,导致模型输出内容无法被Agent正确截断和解析;未启用verbose模式,无法排查中间步骤的格式错误。
- 工具定义不规范:若工具未使用
StructuredTool定义清晰的参数schema,模型无法准确识别工具所需参数,生成的调用指令不符合Agent执行要求。
1. 规范工具定义(使用StructuredTool)
通过StructuredTool结合Pydantic模型明确定义工具参数schema,确保模型能准确识别参数要求:
from langchain.tools import StructuredTool from pydantic import BaseModel, Field import json # 写票工具参数定义 class WriteTicketArgs(BaseModel): summary: str = Field(description="工单摘要,需简洁明了描述问题") description: str = Field(description="工单详细内容,包含问题背景、影响范围、临时措施等") def generate_jira_ticket(summary: str, description: str) -> str: # 生成合规Jira工单JSON的逻辑 ticket_json = { "fields": { "summary": summary, "description": description, "project": {"key": "PROJ"}, "issuetype": {"name": "Bug"} } } return json.dumps(ticket_json) CustomJiraTicketWriting = StructuredTool.from_function( func=generate_jira_ticket, args_schema=WriteTicketArgs, name="CustomJiraTicketWriting", description="生成符合Jira API格式的工单JSON字符串,必须传入summary和description参数" ) # 提交工具参数定义 class PostTicketArgs(BaseModel): ticket_json: str = Field(description="已生成的Jira工单JSON字符串") def post_jira_ticket(ticket_json: str) -> str: # 提交工单到Jira的逻辑 # 示例:调用Jira API提交 # response = requests.post(JIRA_API_URL, json=json.loads(ticket_json), headers=JIRA_HEADERS) return "工单提交成功,工单ID: PROJ-123" CustomJiraTicketPOST = StructuredTool.from_function( func=post_jira_ticket, args_schema=PostTicketArgs, name="CustomJiraTicketPOST", description="将生成的Jira工单JSON提交到Jira系统,必须传入ticket_json参数" )
2. 配置正确的Agent Prompt与Stop序列
使用StructuredChatPromptTemplate明确指定工具调用的JSON格式,同时设置正确的stop序列确保模型输出被正确截断:
from langchain.agents import StructuredChatZeroShotAgent, AgentExecutor from langchain.memory import ConversationBufferMemory from langchain.prompts import StructuredChatPromptTemplate, MessagesPlaceholder from langchain.chat_models import ChatOpenAI # 初始化大模型(需支持结构化输出,如gpt-3.5-turbo-1106/gpt-4) llm = ChatOpenAI(model_name="gpt-3.5-turbo-1106", temperature=0) # 定义系统提示词,明确执行步骤和格式要求 system_prompt = """你需要按照以下流程处理Jira工单请求: 1. 首先调用CustomJiraTicketWriting工具生成合规的工单JSON 2. 然后将生成的JSON作为参数,调用CustomJiraTicketPOST工具提交工单 可用工具列表: {tools} 工具调用必须严格遵循以下JSON格式,不要输出任何额外内容: ```json {{"action": "<工具名称>", "action_input": {{<参数键值对>}}}}
开始处理用户请求:"""
prompt = StructuredChatPromptTemplate.from_messages(
[
("system", system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
agent = StructuredChatZeroShotAgent(
llm=llm,
tools=[CustomJiraTicketWriting, CustomJiraTicketPOST],
prompt=prompt,
stop=["\nObservation:"] # 关键:设置stop序列,截断模型多余输出
)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
agent_executor = AgentExecutor.from_agent_and_tools(
agent=agent,
tools=[CustomJiraTicketWriting, CustomJiraTicketPOST],
memory=memory,
verbose=True # 启用verbose模式,便于排查中间步骤
)
result = agent_executor.run("帮我创建一个Jira工单:摘要为'登录页加载缓慢',描述为'用户反馈登录页加载时长超过5秒,影响新用户注册转化率'")
print(result)
## 3. 关键检查点 - **大模型兼容性**:确保使用的大模型支持结构化输出(如OpenAI的gpt-3.5-turbo-1106及以上版本),旧版本模型可能无法稳定生成合规JSON。 - **Verbose日志排查**:启用`verbose=True`后,查看Agent的中间输出,确认模型是否生成了正确的JSON格式调用指令。若输出为自然语言描述,需进一步优化prompt中的格式示例,增强约束性。 - **工具返回值格式**:工具的返回值需为字符串类型,便于Agent识别并传递给下一个工具。 内容的提问来源于stack exchange,提问作者Joffrey Lemery

