category
人工智能助手大脑结构的一阶原理
大家好,这篇文章是我两周前在神经元实验室进行的一次教程的书面形式。如果你喜欢叙事演练,你可以在这里找到YouTube视频:
和往常一样,你可以在GitHub上找到代码,这里有单独的Colab笔记本:
- 计划和推理
- 不同类型的记忆
- 各种类型的工具
- 构建完整代理
代理商介绍
作者插图。LLM通常通过RAG架构使用外部存储器进行扩充。代理将这一概念扩展到记忆、推理、工具、答案和动作
让我们从探究LLM代理的各种示例开始上课。虽然这个话题被广泛讨论,但很少有人积极利用代理人;通常,我们所感知的代理只是大型语言模型。让我们考虑一个简单的任务,比如搜索足球比赛结果并将其保存为CSV文件。我们可以比较几种可用的工具:
- 带搜索和插件的GPT-4:正如你在这里的聊天历史记录中所发现的,由于代码错误,GPT-4未能完成任务
- AutoGPT通过https://evo.ninja/至少可以生成某种CSV(但并不理想):
- AgentGPT通过https://agentgpt.reworkd.ai/:决定将此任务视为合成数据生成器,这不是我们所要求的,请查看此处的聊天历史记录
由于可用的工具并不好,让我们学习如何从头开始构建代理的第一个原则。我正在使用令人惊叹的Lilian的博客文章作为结构参考,但我自己添加了更多的例子。
步骤1:计划
简单的“输入-输出”LLM使用与思想链、具有自洽性的思想链、思想树等技术之间的视觉差异
您可能会遇到各种旨在提高大型语言模型性能的技术,例如提供提示,甚至开玩笑地威胁它们。一种流行的技术被称为“思维链”,要求模型一步一步地思考,从而实现自我纠正。这种方法已经发展成更高级的版本,如“具有自洽性的思想链”和广义的“思想树”,在其中创建、重新评估和合并多个思想以提供输出。
在本教程中,我将大量使用Langsmith,这是一个用于LLM应用程序产品化的平台。例如,在构建思想树提示时,我将子提示保存在提示存储库中并加载它们:
from langchain import hub
from langchain.chains import SequentialChain
cot_step1 = hub.pull("rachnogstyle/nlw_jan24_cot_step1")
cot_step2 = hub.pull("rachnogstyle/nlw_jan24_cot_step2")
cot_step3 = hub.pull("rachnogstyle/nlw_jan24_cot_step3")
cot_step4 = hub.pull("rachnogstyle/nlw_jan24_cot_step4")
model = "gpt-3.5-turbo"
chain1 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step1,
output_key="solutions"
)
chain2 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step2,
output_key="review"
)
chain3 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step3,
output_key="deepen_thought_process"
)
chain4 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step4,
output_key="ranked_solutions"
)
overall_chain = SequentialChain(
chains=[chain1, chain2, chain3, chain4],
input_variables=["input", "perfect_factors"],
output_variables=["ranked_solutions"],
verbose=True
)
你可以在这个笔记本上看到这种推理的结果,我想在这里指出的是,在Langsmith这样的LLMOps系统中定义推理步骤并对其进行版本控制的正确过程。此外,您还可以在公共存储库中看到其他流行推理技术的示例,如ReAct或Self ask with search:
prompt = hub.pull("hwchase17/react")
prompt = hub.pull("hwchase17/self-ask-with-search")
其他值得注意的方法有:
- Reflexion (Shinn & Labash 2023)是一个为智能体配备动态记忆和自我反思能力以提高推理技能的框架。
- Chain of Hindsight (CoH; Liu et al. 2023) 后见之链(CoH;Liu等人2023)鼓励模型通过明确地向其提供一系列过去的输出来改进其自身的输出,每个输出都附有反馈。
第二步:记忆
我们可以将大脑中不同类型的记忆映射到LLM代理结构的组成部分
- 感官记忆:记忆的这一组成部分捕捉即时的感官输入,比如我们看到、听到或感觉到的东西。在提示工程和人工智能模型的背景下,提示充当瞬时输入,类似于瞬时触摸或感觉。它是触发模型处理的初始刺激。
- 短期记忆:短期记忆暂时保存信息,通常与正在进行的任务或对话有关。在即时工程中,这相当于保留了最近的聊天历史。这种记忆使代理人能够在整个互动过程中保持上下文和连贯性,确保回应与当前对话保持一致。在代码中,通常将其添加为会话历史记录:
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor
from langchain.agents import create_openai_functions_agent
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
tools = [retriever_tool]
agent = create_openai_functions_agent(
llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
message_history = ChatMessageHistory()
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: message_history,
input_messages_key="input",
history_messages_key="chat_history",
)
- 长期记忆:长期记忆存储事实知识和程序指令。在人工智能模型中,这是由用于训练和微调的数据表示的。此外,长期记忆支持RAG框架的操作,允许代理访问学习信息并将其集成到响应中。这就像是一个全面的知识库,代理可以利用它来生成知情和相关的输出。在代码中,通常将其添加为矢量化数据库:
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
loader = WebBaseLoader("https://neurons-lab.com/")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200
).split_documents(docs)
vector = FAISS.from_documents(documents, OpenAIEmbeddings())
retriever = vector.as_retriever()
步骤3:工具
在实践中,您希望使用单独的推理行(可以是另一种LLM,即特定于域或另一种用于图像分类的ML模型)或更基于规则或API的模型来增强代理
ChatGPT插件和OpenAI API函数调用是LLM在实践中增强工具使用功能的好例子。
-
内置Langchain工具:Langchain有一系列内置工具,从互联网搜索和Arxiv工具包到Zapier和雅虎金融。对于这个简单的教程,我们将尝试Tavily提供的互联网搜索:
从langchain.utilities.tavily_search导入TavilySearchAPIWrapper
从langchain.tools.tavily_search导入TavilySearchResults
from langchain.utilities.tavily_search import TavilySearchAPIWrapper
from langchain.tools.tavily_search import TavilySearchResults
search = TavilySearchAPIWrapper()
tavily_tool = TavilySearchResults(api_wrapper=search)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
agent_chain = initialize_agent(
[retriever_tool, tavily_tool],
llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
自定义工具:定义自己的工具也很容易。让我们来剖析一个计算字符串长度的工具的简单例子。你需要使用@tooldecorator让Langchain知道它。然后,不要忘记输入和输出的类型。但最重要的部分将是“”“”之间的函数注释——这是您的代理了解此工具的功能并将此描述与其他工具的描述进行比较的方式:
from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import BaseTool, StructuredTool, tool
@tool
def calculate_length_tool(a: str) -> int:
"""The function calculates the length of the input string."""
return len(a)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
agent_chain = initialize_agent(
[retriever_tool, tavily_tool, calculate_length_tool],
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
你可以在这个脚本中找到它如何工作的例子,但你也可以看到一个错误——它没有提取神经元实验室公司的正确描述,尽管调用了正确的长度计算自定义函数,但最终结果是错误的。让我们试着把它修好!
4.一起
我提供了一个干净的版本,可以在这个脚本中将所有的体系结构组合在一起。请注意,我们如何轻松地分别分解和定义:
- 各种工具(搜索、自定义工具等)
- 各种记忆(作为提示的感官记忆,作为可运行的消息历史记录的短期记忆,作为提示中的画板记忆,以及作为矢量数据库检索的长期记忆)
- 任何类型的规划策略(作为从LLMOps系统中提取的提示的一部分)
代理的最终定义看起来很简单,如下所示:
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: message_history,
input_messages_key="input",
history_messages_key="chat_history",
)
正如您在脚本的输出中所看到的(或者您可以自己运行它),它解决了前一部分中与工具相关的问题。发生了什么变化?我们定义了一个完整的体系结构,其中短期记忆起着至关重要的作用。我们的代理获得了消息历史记录和一个草稿板,作为推理结构的一部分,使其能够提取正确的网站描述并计算其长度。
Outro
我希望通过LLM代理体系结构的核心元素进行的演练将帮助您为旨在自动化的认知任务设计功能机器人。最后,我想再次强调代理的所有要素到位的重要性。正如我们所看到的,即使是对于摘要生成及其长度计算等非常简单的任务,缺少短期记忆或对工具的描述不完整也会扰乱代理的推理,并提供错误的答案。祝你的人工智能项目好运,如果你的公司需要帮助,请毫不犹豫地联系!
- 登录 发表评论
- 36 次浏览
最新内容
- 7 hours ago
- 9 hours ago
- 9 hours ago
- 3 days ago
- 3 days 8 hours ago
- 3 days 8 hours ago
- 3 days 9 hours ago
- 3 days 9 hours ago
- 1 week ago
- 1 week ago