通过让LLM能够与各种工具、数据源和功能等进行互动,运行代码或从网上获取信息,来提高LLM的能力。
Trimbakeshwar Nashik
喂,你好… 测试… 好了,我回来了。
所以今天我们将会介绍如何在LLM的应用场景中实现工具和代理的功能。我们先来了解一下工具和代理是什么。
工具:就是允许代理、链或LLM与世界交互的界面。简单来说,就是用户定义的函数,LLM可以使用这些函数来完成特定的任务。例如,我们可以创建一个计算器函数来完成数学任务,然后我们可以让LLM使用这个函数来处理数学问题。想象一下更大的图景,比如网络抓取、加载新数据、执行函数、解析代码或从万维网上获取信息。
代理: LLM代理程序能够推理,将复杂的任务分解为更容易管理的部分,并为每个部分制定具体计划。代理系统使用LLM作为其推理引擎来决定采取哪些行动以及传递哪些输入。它使用例如搜索和计算器这样的工具来生成需要顺序处理的复杂文本。
定义 2:智能代理,被设计来增强LLM的能力,能够与各种工具和数据源交互,做出决策、执行操作并动态检索信息。
现在让我们来看看代码。在本文中的例子中,我们将使用Hugging Face模型的API调用,这些调用相比OpenAI API提供了更好的token限制功能。
首先,登录到Hugging Face网站并生成API密钥。
Hugging Face访问令牌(access token)
# 加载库和模型,并使用HuggingFaceEndPoint 方法
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
##################################################
# 调用模型的API
repo_id = "mistralai/Mistral-7B-Instruct-v0.2"
llm = HuggingFaceEndpoint(
repo_id=repo_id,
#max_length=1288,
temperature=0.5,
huggingfacehub_api_token= "hf_youkey")
我们将使用Serpapi:https://serpapi.com 这个网站是SERPAPI,挺实用的。进行网络爬虫抓取。请注册生成并复制API密钥。
我们来做个工具
从 langchain.agents 导入 load_tools,
从 langchain.agents 导入 initialize_agent,
从 langchain.agents 导入 Tool, tool
serpapi_api_key="your_key"
# 手动创建工具
# 从 langchain.utilities 导入 SerpAPIWrapper
# search = SerpAPIWrapper(serpapi_api_key="7eb979c55d8a5ab2d07ab0461c969a8fe1f2b4c4b4484560d4436bacd84612aa")
# tools = [
# Tool(name = "Current Search",
# func=search.run,
# description="当需要回答有关当前事件或世界当前状态的问题时非常有用"),
# ]
导入 os;
os.environ["SERPAPI_API_KEY"] = serpapi_api_key
# 加载现有的工具
tools = load_tools(["serpapi", "llm-math",], llm=llm)
查看工具详情
# 这样的工具是什么
tools[1].name, tools[1].description
('计算器', '非常适合回答数学问题时使用。')
Tools saved as object list
初始化一个代理程序
agent = initialize_agent(tools,
llm,
agent="zero-shot-react-description", #Deprecated instead use create_react_agent()
#zero-shot-react-description:无需先前的上下文或训练即可完成任务,
verbose=True,handle_parsing_errors=True)
#查看默认模板
agent.agent.llm_chain.prompt.template
#'请使用以下格式:\n\n问题:你需要回答的输入问题\n思考:思考下一步应该采取什么行动\n行动:要采取的动作,应为[Search, Calculator]之一\n行动输入:动作的输入\n观察:动作的结果\n...(此思考/行动/行动输入/观察可以重复N次)\n思考:我现在知道了最终答案\n最终答案:问题的答案\n\n开始!\n\n问题:{问题}\n思考:{思考内容}'
运行一个查询来看看不同之处
## 标准LLM查询
agent.run("嗨,今天怎么样?")
agent.run("DeepMind是什么?")
agent.run("嗨,今天怎么样?")
agent.run('什么是DeepMind?')
我们将更进一步地推进,通过添加我们自定义的函数。为此,我们只需在函数前声明@tool。
#添加新工具------------------
@tool
def get_word_length(word: str) -> int:
"""返回单词的长度"""
return len(word)
get_word_length.invoke("abc")
#输出为3
tools1 = [get_word_length]
tools_new = [get_word_length]
tools_new.append(tools[1])#添加上面定义的工具1
tools_new[0].name, tools_new[0].description
#('get_word_length', '返回单词的长度')
tools_new[1].name, tools_new[1].description
#('计算器', '在需要回答数学问题时非常有用')
#所以我们有了两个工具:get_word_length 和计算器
为LLM添加记忆功能,记录聊天记录,这样我们就可以查询之前的聊天记录中的主题了。
几种记忆类型。
1. 会话缓冲内存:适用于需要完整历史背景且内存限制不是主要问题的情况
2. 缓冲窗口内存: 当历史背景不太重要且需要限制内存大小时很有用。
3. 对话Token缓存: 当Token数量控制对模型处理至关重要的时候适用。这适用于需要严格控制Token数量以确保模型处理效果最佳的情况。
4. 对话摘要功能: 当 token 数量需要高效管理时,不优先考虑详细上下文时特别有用。
5.对话中的实体记忆: 当我们需要提取并保存特定实体或数据点特别有用。
6. 向量存储检索器内存: 当快速准确地检索上下文信息至关重要时,这种内存类型非常适用。
7. ConversationKGMemory: 这种记忆类型利用知识图谱来再现记忆。
# 添加记忆 -----------------------------
from langchain.memory import ConversationBufferWindowMemory
memory = ConversationBufferWindowMemory(memory_key="chat_history",
k=3, # k 是历史记录的数量
return_messages = True)
启动一下代理
#初始化-------------------------
from langchain.agents import AgentType
agent = initialize_agent(tools_new,
llm, max_iterations = 3,
agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,#已废弃,建议使用create_react_agent()
#"零样本反应描述::一个在行动前进行推理步骤的Agent",
verbose=True,#early_stopping= "generate",# 不需要填写
memory=memory
,handle_parsing_errors=True)
#查看提示
agent.agent.llm_chain.prompt.template
运行查询,然后看看有什么不同。
agent.run("2加2等于多少?")
agent.run("告诉我关于埃洛拉的详情")
results = agent.invoke("它位于哪里?")
agent.run('2加2等于多少')
agent.run(「告诉我关于埃洛拉的资料」)
结果值 = agent.invoke("它的位置在哪里")
将最终结果保存为字典‘results’。我们可以清楚地观察到,这是因为我们并没有提到名称‘Ellora’这一特定地名,而是仅仅提到了‘它在哪里’。
让我们试试用AgentExecutor做一些复杂的例子,我们将代理(相当于大脑)与AgentExecutor中的工具结合在一起,这样它会反复调用代理并执行工具。
#加载库
from langchain.agents import AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template(
"""请回答以下问题,回答得越准确越好。你可以使用以下工具:
{tools}
{chat_history}
请使用以下格式:
问题:需要回答的问题
思考:你应该思考下一步该怎么做
动作:应该采取的动作,应该是 [{tool_names}] 中的一种
动作输入:(此处填写具体输入)
观察:动作的结果
...(思考/动作/动作输入/观察可以重复N次)
思考:我现在可以给出最终答案了
最终答案:对原始问题的最终答案
开始!
问题:{input}
思考:{agent_scratchpad}
"""
)
#注意,`agent_scratchpad` 是一个函数,用于将代理的动作和观察的中间步骤格式化为字符串。
添加内存,然后启动智能体。
# 添加记忆 -----------------------------
from langchain.memory import ConversationBufferWindowMemory
memory2 = ConversationBufferWindowMemory(memory_key="chat_history",
k=3,return_messages = True)
agent = create_react_agent(llm, tools_new, prompt)
# create_react_agent 使用的是 ReAct 提示策略。
# 该论文基于“ReAct: 语言模型中的推理与行动的协同”(https://arxiv.org/abs/2210.03629)。
# 工具信息
tools_new[0].name, tools_new[0].description
# 请注意,工具列表 tools_new 中仅包含 get_word_length 和计算器。
agent_executor = AgentExecutor(
agent=agent, # 这里的 agent 定义使用的是 create_react_act(),而不是 AgentType.CONVERSATIONAL_REACT_DESCRIPTION
tools=tools,
verbose=True,
max_iterations=5,
memory = memory2,
#max_execution_time=max_execution_time,
#early_stopping_method=early_stopping_method,
handle_parsing_errors=True)
现在我们来查询并观察不同之处
results3 = agent_executor.invoke({"input":"跟我说说更多关于埃洛拉的详情"})
results3 = agent_executor.invoke({"input":"多告诉我一些关于埃洛拉的信息"})
咱们可以观察到,AgentExecutor 尝试使用咱们的工具 “get_word_length&Calculator” 来运行这个查询,当然,这些工具并不能正确地找到答案。
首先,它会依次使用工具查找答案,如果找不到,还会从内部查找来找到答案。
就这样。恭喜我们可以创建“代理” 和 “工具”,扩展了我们LLM的功能。
接下来,我们将学习LLM对话记忆的类型以及提示类型,此外还有PEFT(周边高效精调)来调优模型及程序辅助语言模型 (PAL)
随时都可以联系我。感谢你抽空阅读,如果你喜欢这篇短文并感兴趣的话,我还有很多关于高级分析、数据科学和机器学习的主题在我的Medium账号里。[https://medium.com/@bobrupakroy](https://medium.com/@bobrupakroy)_
我的一些在线平台或账户比如Facebook,Instagram,Udemy,Blogger,Issuu,Slideshare,Scribd等等。
也可在Quora上找到 @ https://www.quora.com/profile/Rupak-Bob-Roy
有需要的话告诉我,我们很快再聊。
一定要去纳希克
Sula Life: Nashik
共同学习,写下你的评论
评论加载中...
作者其他优质文章