通八洲科技

如何在 LangChain 中将自定义工具与 Llama 2 模型无缝集成

日期:2025-12-27 00:00 / 作者:碧海醫心

本文详解如何解决 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。推荐以下组合:

  1. 选用 OpenAIFunctionsAgent 或 ToolCallingAgent(LangChain v0.1+)
    这些 Agent 原生支持函数调用协议(即使后端非 OpenAI),可配合 Llama 2 的函数调用微调版本(如 llama-2-70b-chat-function-calling)或通过 prompt engineering 模拟函数调用格式。

  2. 若使用基础 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)

⚠️ 注意事项:

总结:Llama 2 与 LangChain 工具链集成失败,本质是“LLM 输出格式”与“Agent 解析协议”不匹配。解决方案不是更换模型,而是精准定制 OutputParser + 选择语义兼容的 Agent 类型 + 强化 Prompt 约束。参考 Pinecone 官方 Llama 2 Agent 示例 可快速验证完整流程。