LangChain ReAct代理执行完成后,如何将生成的DataFrame作为本地变量获取?
LangChain ReAct代理执行完成后,如何将生成的DataFrame作为本地变量获取?
我现在用LangChain的ReAct代理来加载Excel文件、做数据转换,最后把结果存在名为df的DataFrame里。但问题是,最后调用agent_executor.invoke()的时候,它只返回一个描述执行过程的字典,根本拿不到实际的DataFrame。我想在主脚本里把生成的DataFrame作为本地变量直接用,下面是我的代码:
import pandas as pd from langchain.agents import AgentExecutor, create_react_agent, Tool from langchain.tools import tool from langchain_community.tools import ShellTool from langchain_openai import ChatOpenAI from langchain_experimental.utilities import PythonREPL from langchain import hub @tool def load_excel_response(filepath: str): """Load an Excel file and return a transformed DataFrame.""" df = pd.read_excel(filepath, skiprows=2, names=['responses']).reset_index(drop=True) df = df.select_dtypes(include=['object']) return df # df.to_json() llm = ChatOpenAI(model='gpt-4o-mini') python_repl = PythonREPL() shell_tool = ShellTool() repl_tool = Tool( name="python_repl", description="Run Python commands in a REPL environment.", func=python_repl.run, ) tools_list = [load_excel_response, repl_tool, shell_tool] prompt = hub.pull("hwchase17/react") shell_agent = create_react_agent(llm=llm, tools=tools_list, prompt=prompt) agent_executor = AgentExecutor(agent=shell_agent, tools=tools_list, verbose=True) path = 'excel_file.xlsx' user_prompt = f"Load the Excel file located at {path} and assign the result to a variable named df." response = agent_executor.invoke({"input": user_prompt}) print("Agent response:", response)
目前我观察到的情况是:
- 代理确实加载了Excel文件(已经通过
verbose=True的输出确认了) agent_executor.invoke()的最终返回值是一个字典,只总结了代理的执行步骤和最终消息,没有实际的DataFrame数据- 我需要的是执行完成后拿到
df这个变量
我已经试过这些办法,但都没解决:
- 定义一个全局的
df变量,想让代理把结果存到全局变量里 - 在
load_excel_response工具里返回df.to_json()格式的数据
不管怎么试,代理的最终返回还是只有文本总结,拿不到实际数据。
可行的解决思路
ReAct代理的设计本来就是返回自然语言的执行总结,所以要拿到实际的DataFrame,得换个思路——把数据存储在代理可以访问、主脚本也能拿到的共享空间里,或者让工具直接把数据输出到外部可访问的地方。下面是两种比较靠谱的实现方式:
方式一:用类封装状态(推荐,比全局变量更优雅)
我们可以创建一个简单的类来保存DataFrame的状态,让工具方法直接操作这个类的实例,这样主脚本就能从实例里拿到最终的DataFrame。
修改后的代码示例:
import pandas as pd from langchain.agents import AgentExecutor, create_react_agent, Tool from langchain.tools import tool from langchain_community.tools import ShellTool from langchain_openai import ChatOpenAI from langchain_experimental.utilities import PythonREPL from langchain import hub # 定义一个类来存储共享状态 class DataStore: def __init__(self): self.df = None data_store = DataStore() @tool def load_excel_response(filepath: str): """Load an Excel file and store the transformed DataFrame in the shared data store.""" df = pd.read_excel(filepath, skiprows=2, names=['responses']).reset_index(drop=True) df = df.select_dtypes(include=['object']) # 把df存到共享的data_store里 data_store.df = df return "Excel文件加载并转换完成,DataFrame已存储到共享数据区" llm = ChatOpenAI(model='gpt-4o-mini') python_repl = PythonREPL() shell_tool = ShellTool() repl_tool = Tool( name="python_repl", description="Run Python commands in a REPL environment.", func=python_repl.run, ) tools_list = [load_excel_response, repl_tool, shell_tool] prompt = hub.pull("hwchase17/react") shell_agent = create_react_agent(llm=llm, tools=tools_list, prompt=prompt) agent_executor = AgentExecutor(agent=shell_agent, tools=tools_list, verbose=True) path = 'excel_file.xlsx' user_prompt = f"Load the Excel file located at {path} using the load_excel_response tool." response = agent_executor.invoke({"input": user_prompt}) print("Agent response:", response) # 现在主脚本可以直接从data_store里拿到df了 final_df = data_store.df print("最终拿到的DataFrame:", final_df.head())
方式二:让工具返回序列化后的DataFrame,主脚本解析
如果不想用类,也可以让工具返回JSON格式的DataFrame数据,然后在主脚本里把JSON解析回DataFrame。不过要注意修改prompt或者引导代理返回原始的JSON数据,而不是总结文本。
修改工具和主脚本的关键部分:
@tool def load_excel_response(filepath: str): """Load an Excel file and return the transformed DataFrame as JSON string.""" df = pd.read_excel(filepath, skiprows=2, names=['responses']).reset_index(drop=True) df = df.select_dtypes(include=['object']) # 返回JSON格式的字符串 return df.to_json(orient='records') # 调用代理后,解析返回的结果 response = agent_executor.invoke({"input": f"Load the Excel file at {path} and return the raw JSON output from the load_excel_response tool."}) # 注意这里要从response的output里提取JSON字符串,然后解析 import json final_df = pd.DataFrame(json.loads(response['output'])) print("解析后的DataFrame:", final_df.head())
为什么之前的方法没生效?
- 全局变量的问题:代理的工具方法在执行时,可能处于不同的上下文,直接赋值全局变量有时候会因为作用域问题不生效;而且如果是多线程环境,全局变量还会有线程安全问题。
- 返回JSON但没拿到:因为ReAct代理默认会把工具的返回值转换成自然语言总结,所以即使工具返回了JSON,代理也会把它改成文本描述,不会直接返回原始的JSON数据。
备注:内容来源于stack exchange,提问作者Daniel Tobi
相关产品推荐
相关产品推荐

