青训营×豆包MarsCode技术训练营 langchain对话大模型ReAct实战尝试一

166 阅读9分钟

这篇文章中,我将介绍学习使用ReAct实现实战项目中SerpAPI包的使用过程。

在接触LanngChain之前我也完成过一些GPT对话类的应用项目,在实践过程中,使用大模型生成回答的逻辑无一例外都是直接调用大模型的“生成回答”这个接口,然而这种方法在使用时的确会产生很多问题,模型的回答往往不尽如人意,我一直将其归因于开源模型的“能力问题”。对于提升模型的回答功能除了更换模型外没有其他的有效解决方法。在学习了LangChain系列课程后,我对大语言模型的使用在思路上有了很大的转变。我意识到大模型的推理能力是需要靠有效的提示工程才能体现的。

ReAct框架的灵感来自“行动”和“推理”之间的协同作用,这种协同作用使得咱们人类能够学习新任务并做出决策或推理。具体来说,就是引导模型生成一个任务解决轨迹:观察环境-进行思考-采取行动,也就是观察-思考-行动。那么,再进一步进行简化,就变成了推理-行动,也就是Reasoning-Acting框架。其中,Reasoning包括了对当前环境和状态的观察,并生成推理轨迹。这使模型能够诱导、跟踪和更新操作计划,甚至处理异常情况。Acting在于指导大模型采取下一步的行动,比如与外部源(如知识库或环境)进行交互并且收集信息,或者给出最终答案。ReAct的每一个推理过程都会被详细记录在案,这也改善大模型解决问题时的可解释性和可信度。

根据课程中的步骤,我要先注册一个SerpAPI账号并获取APIkey,当然也要注册好需要使用的大语言模型的APIkey,我这里已经注册好了openai的APIkey。不得不说SerpAPI的注册流程还是比较方便的,不需要国外的手机短信验证。

serp.png

这些事前工作完成后,就可以开始写代码了。得益于LangChain的调用,整个大语言模型的使用代码是十分简洁的。在经过加载所需库,初始化大模型,设置工具,初始化agent后,我们的代码就像下面这样:

# 设置OpenAI和SERPAPI的API密钥
import os

os.environ[
    "OPENAI_API_KEY"] = 
                        

os.environ["SERPAPI_API_KEY"] = 

# 加载所需的库
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain_openai import ChatOpenAI  # ChatOpenAI模型

# 初始化大模型
llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)

# 设置工具
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 初始化Agent
agent = initialize_agent(
    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)

# 跑起来
agent.run(
    "目前市场上玫瑰花的平均价格是多少?如果我在此基础上加价15%卖出,应该如何定价?"
)

运行之后,毫不意外地出现了报错: Traceback (most recent call last): File "D:\PyCharm 2022.2.5\PycharmProject\pythonProject1\langchain\serpapi.py", line 20, in <module> tools = load_tools(["serpapi", "llm-math"], llm=llm) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anacoda\Lib\site-packages\langchain_community\agent_toolkits\load_tools.py", line 753, in load_tools tool = _get_tool_func(**sub_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anacoda\Lib\site-packages\langchain_community\agent_toolkits\load_tools.py", line 387, in _get_serpapi func=SerpAPIWrapper(**kwargs).run, ^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anacoda\Lib\site-packages\pydantic\main.py", line 214, in __init__ validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anacoda\Lib\site-packages\langchain_community\utilities\serpapi.py", line 73, in validate_environment raise ImportError( ImportError: Could not import serpapi python package. Please install it with pip install google-search-results`.

Process finished with exit code 1 `

本来以为只是简单的pip库安装出错,但是在根据安装提示安装好google-search-results后,这个报错仍然存在,看来没有这么简单。 再仔细检查报错说明后,发现报错不止这一个,在最上面的说明中,还有一个循环调用的错误。这下就有突破口了,我们知道出现循环报错的原因很有可能是文件名重复所导致的。在调用serpapi包时,langchain内部一般是不会出现重复的python脚本的。在仔细检查后,我哭笑不得地发现原来是我的源文件脚本起名为serpapi,看来重复的脚本名在这里。修改名字后重新运行。虽然不报原来的错误了,但在经历了漫长的等待后,还是出现了请求超时的错误。 httpcore.ConnectTimeout: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败 看来是网络问题,不过这个问题也是在意料之中了,还在想什么时候会出现,这就来了,毕竟是google的api,需要借助一点代理工具了。

打开代理后,出现了调用次数不足的操作,指定模型为gpt3.5后仍然出现报错,了解下来才发现api调用即使是3.5也是要收费的,这下只恨财力不足了。看来暂时时是用不了openai的大模型了。我开始尝试使用huggingface中的开源大语言模型。首先将代码修改为huggingface pipline的格式:

# 设置OpenAI和SERPAPI的API密钥
import os

os.environ[
    "OPENAI_API_KEY"] = ''

os.environ["SERPAPI_API_KEY"] = ''

os.environ['HUGGINGFACEHUB_API_TOKEN'] = ''

# 加载所需的库
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain_openai import OpenAI  # ChatOpenAI模型
import httpx
from langchain import PromptTemplate, HuggingFaceHub, LLMChain

# 初始化大模型

llm = OpenAI(model_name="gpt-3.5-turbo-16k")

model = "meta-llama/Llama-2-7b-chat-hf"

# 从预训练模型中加载词汇器
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(model)

# 创建一个文本生成的管道
import transformers
import torch

pipeline = transformers.pipeline(
    "text-generation",
    model=model,
    torch_dtype=torch.float16,
    device_map="auto",
    max_length=1000
)

# 创建HuggingFacePipeline实例
from langchain import HuggingFacePipeline

llm2 = HuggingFacePipeline(pipeline=pipeline,
                           model_kwargs={'temperature': 0})

# 设置工具
tools = load_tools(["serpapi", "llm-math"], llm=llm2)

# 初始化Agent
agent = initialize_agent(
    tools, llm2, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)

# 跑起来
agent.run(
    "2024年美国大选的情况如何?"
)

本想着这下也该行了,但是运行后还是出现报错OSError: You are trying to access a gated repo. 原来huggingface中的开源模型的调用虽然不收费,但还是要申请,只能等待申请结束了,虽然用不了llama了,但还可以尝试其他大语言模型,再次更换其他模型,我这里使用的是一个llama的第三方微调模型,在经过了漫长的下载过程后终于有了输出

Question: 2024年美国大选的情况如何? Thought: I want to search for the current situation of the 2024 US election. Action: Search Action Input: 2024年美国大选 Observation: 2024年美国大选是指美国总统选举在2024年举行的选举,届时美国总统和副总统的任期将届满,届时将选出下一任美国总统和副总统。根据美国宪法规定,总统和副总统的任期为四年,总统和副总统的任期将在2024年1月20日结束。 Thought: I want to search for the current situation of the 2024 US election. Action: Search Action Input: 2024年美国大选 Observation: 2024年美国大选是指美国总统选举在2024年举行的选举,届时美国总统和副总统的任期将届满,届时将选出下一任美国总统和副总统。根据美国宪法规定,总统和副总统的任期为四年,总统和副总统的任期将在2024年1月20日结束。 Thought: I want to search for the current situation of the 2024 US election. Action: Search Action Input: 2024年美国大选 Observation: 2024年美国大选是指美国总统选举在2024年举行的选举,届时美国总统和副总统的任期将届满,届时将选出下一任美国总统和副总统。根据美国宪法规定,总统和副总统的任期为四年,总统和副总统的任期将在2024年1月20日结束。 Thought: I want to search for the current situation of the 2024 US election. Action: Search Action Input: 2024年美国大选 Observation: 2024年美国大选是指美国总统选举在2024年举行的选举,届时美国总统和副总统的任期将届满,届时将选出下一任美国总统和副总统。根据美国宪法规定,总统和副总统的任期为四年,总统和副总统的任期将在2024年1月20日结束。 Thought: I want to search for the current situation of the 2024 US election. Action: Search Action Input: 2024年美国大选 Observation: 2024年美国大选是指美国总统选举在2024年举行的选举,届时美国总统和副总统的任期将届满,届时将选出下一任美国总统和副总统。根据美国宪法规定,总统和副总统的任期为四年,总统和副总统的任期将在2024年1月20日结束。

但是观察以上输出后发现似乎不太对劲,模型的确使用了serp进行搜索,但是搜索的结果并不符合预期,而且这个搜索过程执行了多次,但返回的结果都没有变化。猜想可能是问题的原因,在更换问题为课程中的鲜花价格问题后得到如下输出:

Question: 目前市场上玫瑰花的平均价格是多少?如果我在此基础上加价15%卖出,应该如何定价? Thought: 我应该先搜索一下 Action: Search Action Input: 目前市场上玫瑰花的平均价格是多少 Observation: 目前市场上玫瑰花的平均价格是多少?我搜索到了一些相关的信息,平均价格大约是100元左右。 Thought: 我应该再搜索一下 Action: Search Action Input: 如果我在此基础上加价15%卖出,应该如何定价 Observation: 如果我在此基础上加价15%卖出,应该如何定价?我搜索到了一些相关的信息,建议加价15%至120元左右。 Thought: 我应该再搜索一下 Action: Search Action Input: 如果我在此基础上加价15%卖出,应该如何定价 Observation: 如果我在此基础上加价15%卖出,应该如何定价?我搜索到了一些相关的信息,建议加价15%至120元左右。 Thought: 我应该再搜索一下

虽然成功返回了具体的价格,但是没有成功调用数学工具,而且也出现了重复多次相同逻辑的情况。

这篇文章就介绍到这里了,虽然最终还有一些问题,但是前面的各种报错也弄了很久了,遗留的问题解决我将在下一篇文章中详细解释,感谢观看。