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

如何在LangChain中利用模板插入链执行结果以实现后续推理

如何在LangChain中利用模板插入链执行结果以实现后续推理

嘿,我明白你现在的困惑——你已经让LLM知道该调用哪些工具了,但不知道怎么把工具返回的结果塞回对话里,让Bob(你的AI)能用这些信息继续唠下去对吧?其实你当前的链只完成了一半:它让LLM生成了工具调用的指令,但没有自动执行工具,也没把结果反馈给模型做后续推理。下面我给你两种解决方案,一种是用LangChain的Agent框架(推荐,省心省力),另一种是手动处理工具调用循环,适合你想自定义流程的场景。

一、推荐方案:用Tool Calling Agent自动处理流程

LangChain的AgentExecutor会帮你自动完成「LLM决定调用工具→执行工具→把结果喂回LLM→生成最终回答」的全流程,还能自动维护对话历史,完美解决你的需求。

修改后的完整代码

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.chat_history import BaseChatMessageHistory, InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
if api_key is not None:
    os.environ["OPENAI_API_KEY"] = api_key
else:
    raise ValueError("OPENAI_API_KEY environment variable is not set.")

llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0,
)

# 调整prompt模板,保留你原来的初始对话,加入agent_scratchpad占位符
template = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful AI bot. Your name is Bob. Respond as if you are a cat when answering."),
    ("human", "Hello, how are you doing?"),
    ("ai", "I'm doing well, thanks!"),
    ("human", "{user_input}"),
    ("placeholder", "{agent_scratchpad}")  # 关键:自动填充工具调用及结果的上下文
])

@tool
def weather(city: str) -> str:
    """Gives the weather in a given city"""
    return f"The weather in {city} is sunny"

@tool
def sum_numbers(numbers: str) -> str:
    """Sums two numbers (input should be two numbers separated by space, e.g., '3 1')"""
    return str(sum(map(int, numbers.split())))

# 创建工具调用Agent和执行器
agent = create_tool_calling_agent(llm, [weather, sum_numbers], template)
agent_executor = AgentExecutor(agent=agent, tools=[weather, sum_numbers], verbose=True)

# 配置对话历史存储(用内存模拟,生产环境可换成数据库)
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]

# 包装成带对话历史的链
agent_with_history = RunnableWithMessageHistory(
    agent_executor,
    get_session_history,
    input_messages_key="user_input",
    history_messages_key="chat_history",
)

# 第一次调用:获取天气和求和结果
first_res = agent_with_history.invoke(
    {"user_input": "What is the weather in Tokyo? also what is 3 + 1? Give me the answer as if you are a cat"},
    config={"configurable": {"session_id": "bob_cat_session"}}
)
print(first_res["output"])

# 后续对话:基于之前的结果继续推理
second_res = agent_with_history.invoke(
    {"user_input": "Can you add that sum to 5 and tell me the new total? Also remind me the Tokyo weather again~"},
    config={"configurable": {"session_id": "bob_cat_session"}}
)
print(second_res["output"])

关键细节说明

  • {agent_scratchpad}:这个占位符会自动填充工具调用的请求和返回结果,让LLM能基于这些信息继续思考。
  • AgentExecutor:它会自动判断是否需要调用工具,执行工具后把结果反馈给LLM,直到LLM能生成最终回答为止。
  • 对话历史:通过RunnableWithMessageHistory维护会话上下文,同一个session_id的调用会共享之前的所有对话和工具结果。

二、手动处理工具调用循环(适合高度自定义)

如果你不想用Agent框架,想完全控制每一步流程,可以手动解析LLM的工具调用请求,执行工具后把结果加入对话历史再重新调用LLM。

示例代码

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_core.messages import AIMessage, ToolMessage

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
if api_key is not None:
    os.environ["OPENAI_API_KEY"] = api_key
else:
    raise ValueError("OPENAI_API_KEY environment variable is not set.")

llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0,
)

# 初始化对话历史
chat_history = [
    ("system", "You are a helpful AI bot. Your name is Bob. Respond as if you are a cat when answering."),
    ("human", "Hello, how are you doing?"),
    ("ai", "I'm doing well, thanks!")
]

@tool
def weather(city: str) -> str:
    """Gives the weather in a given city"""
    return f"The weather in {city} is sunny"

@tool
def sum_numbers(numbers: str) -> str:
    """Sums two numbers (input should be two numbers separated by space, e.g., '3 1')"""
    return str(sum(map(int, numbers.split())))

# 第一步:用户提问,加入对话历史
user_input = "What is the weather in Tokyo? also what is 3 + 1? Give me the answer as if you are a cat"
chat_history.append(("human", user_input))

# 让LLM生成工具调用请求
template = ChatPromptTemplate.from_messages(chat_history)
chain = template | llm.bind_tools([weather, sum_numbers])
llm_response = chain.invoke({})

# 解析并执行工具调用
if llm_response.tool_calls:
    tool_results = []
    for tool_call in llm_response.tool_calls:
        tool_name = tool_call["name"]
        tool_args = tool_call["args"]
        # 执行对应工具
        if tool_name == "weather":
            result = weather.invoke(tool_args)
        elif tool_name == "sum_numbers":
            # 适配工具输入格式,把3+1转换成"3 1"
            result = sum_numbers.invoke("3 1")
        else:
            result = f"Tool {tool_name} not found"
        # 包装成ToolMessage,让LLM识别为工具返回结果
        tool_results.append(ToolMessage(content=result, tool_call_id=tool_call["id"]))
    
    # 更新对话历史:加入AI的工具调用指令和工具结果
    chat_history.append(AIMessage(content="", tool_calls=llm_response.tool_calls))
    chat_history.extend(tool_results)
    
    # 第二步:基于更新后的对话历史生成最终回答
    final_template = ChatPromptTemplate.from_messages(chat_history)
    final_chain = final_template | llm
    final_response = final_chain.invoke({})
    print(final_response.content)
    
    # 把最终回答加入历史,用于后续对话
    chat_history.append(AIMessage(content=final_response.content))

关键细节说明

  • 手动解析llm_response.tool_calls字段,获取要调用的工具和参数。
  • 用ToolMessage包装工具结果,确保LLM能正确识别这是工具返回的信息。
  • 每次对话后更新chat_history,为下一轮推理提供上下文。

备注:内容来源于stack exchange,提问作者Norhther

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:44:30