
本文详解如何解决 llama 2 与 langchain 自定义工具(如计算器)集成时常见的“could not parse llm output”错误,核心在于适配 llama 2 的非结构化文本输出——通过定制 outputparser 实现 json 格式指令解析,并推荐更兼容的 agent 类型。
Llama 2(尤其是 llama-2-70b-chat 等开源大模型)默认以自由文本形式生成响应,而 LangChain 的 STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION Agent 严格依赖结构化 JSON 输出(如 {"action": "Calculator", "action_input": "2 + 3"})来识别并调用工具。当 Llama 2 返回自然语言描述(例如:“我将使用计算器计算 2 加 3”)时,Agent 内置的 ReActJsonOutputParser 无法解析,从而抛出 Could not parse LLM output 错误。
✅ 正确做法是:绕过默认 parser,改用支持自由文本推理的 Agent + 自定义 OutputParser。推荐以下组合:
选用 OpenAIFunctionsAgent 或 ToolCallingAgent(LangChain v0.1+)
这些 Agent 原生支持函数调用协议(即使后端非 OpenAI),可配合 Llama 2 的函数调用微调版本(如 llama-2-70b-chat-function-calling)或通过 prompt engineering 模拟函数调用格式。若使用基础 Llama 2(无函数调用微调),必须自定义 OutputParser
示例代码(基于 llama-cpp-python 或 transformers 加载模型):
from langchain_core.output_parsers import BaseOutputParser
from langchain_core.agents import AgentAction, AgentFinish
import re
import json
class Llama2ReActOutputParser(BaseOutputParser):
def parse(self, text: str) -> AgentAction | AgentFinish:
# 匹配 Llama 2 常见的 ReAct 风格输出(支持中文/英文混合)
if "Final Answer:" in text:
return AgentFinish(return_values={"output": text.split("Final Answer:")[-1].strip()}, log=text)
# 尝试提取 action 和 action_input(兼容多种格式)
action_match = re.search(r"Action:\s*(\w+)", text)
input_match = re.search(r"Action Input:\s*(.*)", text, re.DOTALL)
if action_match and input_match:
action = action_match.group(1).strip()
action_input = input_match.group(1).strip().strip('"\'')
try:
# 尝试 JSON 解析 action_input(如为 JSON 字符串)
parsed_input = json.loads(action_input)
return AgentAction(tool=action, tool_input=parsed_input, log=text)
except (json.JSONDecodeError, ValueError):
return AgentAction(tool=action, tool_input=action_input, log=text)
raise ValueError(f"Could not parse LLM output: {text}")
# 使用示例
from langchain_community.llms import LlamaCpp
from langchain.agents import AgentExecutor, create_structured_chat_agent
llm = LlamaCpp(
model_path="./models/llama-2-70b-chat.Q4_K_M.gguf",
temperature=0.1,
max_tokens=512,
top_p=1,
verbose=False,
)
# 自定义工具(如 Calculator)
from langchain.tools import StructuredTool
def calculate(expression: str) -> str:
try:
return str(eval(expression))
except:
return "Invalid expression"
calculator = StructuredTool.from_function(
func=calculate,
name="Calculator",
description="Useful for performing arithmetic calculations. Input must be a valid Python expression (e.g., '2 + 3 * 4')."
)
prompt = hub.pull("hwchase17/structured-chat-agent")
agent = create_structured_chat_agent(
llm=llm,
tools=[calculator],
prompt=prompt,
output_parser=Llama2ReActOutputParser() # 关键:注入自定义 parser
)
agent_executor = AgentExecutor(agent=agent, tools=[calculator], verbose=True)⚠️ 注意事项:
- Prompt 工程至关重要:确保使用的 Prompt 模板(如 hwchase17/structured-chat-agent)明确要求 Llama 2 以 Action: / Action Input: / Final Answer: 格式输出,避免自由发挥。
- 避免 STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION 直接搭配原生 Llama 2:该 Agent 对输出格式容错性极低,建议优先尝试 create_openai_functions_agent(配合 llm.bind_tools())或升级至 LangChain 0.1.20+ 的 create_tool_calling_agent。
- 多输入工具支持:StructuredTool 天然支持 Pydantic 模型定义多参数(如 def search(query: str, site: str, timeout: int = 5)),无需额外配置;Agent 会自动解析结构化输入。
总结:Llama 2 与 LangChain 工具链集成失败,本质是“LLM 输出格式”与“Agent 解析协议”不匹配。解决方案不是更换模型,而是精准定制 OutputParser + 选择语义兼容的 Agent 类型 + 强化 Prompt 约束。参考 Pinecone 官方 Llama 2 Agent 示例 可快速验证完整流程。










