
Ai 代理解密:只需 5 个简单步骤,就能构建你的第一个自主代理!
这还有比这更简单的吗?
AI agent — image created with Leonardo.ai
介绍
让它简单,他们说。
这正是我即将做的事情。
如今,我们听到和阅读了很多关于代理人工智能的内容。“到处都是代理,代理!”,“今年将是代理的年”,…。
当然,但真正的代理是什么?(至少,这种形式的代理)
在这个故事中,我将尝试给出一个AI代理的最简单解释,以及在Python中实现一个的最简单方法(需要一些关于文档索引、嵌入和向量存储的基本知识)。
什么是代理人工智能?
代理人工智能是指能够独立行动以实现目标的人工智能系统。
这意味着,代理人工智能不仅仅是响应输入(就像 ChatGPT 回答你的问题),而是规划、做出决策并根据环境采取行动。
再一次:计划 ➡ 决策 ➡ 行动。
简单例子:
想象一个机器人:
- 知道你在早上8点喜欢喝咖啡(例如,我最喜欢的 Nespresso Arpeggio)
- 注意到家里没有咖啡了
- 在你没有要求的情况下 从 Nespresso 的在线商店订购咖啡
- 为你制作咖啡(我在开玩笑!! 还没有,不过无论如何..)
这是代理行为,因为人工智能:
- 观察一个情况。
- 规划一个解决方案。
- 自主采取行动。
Agents的关键特征是什么?
Agents因以下关键特征而“出名”:
-
自主性: 它在无需人类干预的情况下做出决策。相反,它主动采取行动,例如,从PDF文件中读取或执行Python命令。
-
目标导向: 它通过将复杂目标分解为更小的步骤并按正确顺序执行来朝着特定结果努力。
-
推理: 它在行动之前评估不同的选项。
-
适应性: 如果情况发生变化,它可以调整计划并动态优化其方法。
编码示例
现在让我们来看一个工作示例。
我们将创建一些机器在制造工厂中的生产的人工数据。
我们还将创建一个包含这些机器信息的人工PDF文件,并将其交给代理以执行RAG(检索增强生成),并提供有关机器的信息。
现在让我们创建一个能够通过OpenAI兼容的大语言模型(在此案例中为gpt-4)区分我们请求的AI代理,并执行相应的操作。我们可以请求计算数据中的某些内容,或者从PDF文件中获取有关机器的信息。我们将尽可能简单。
我们将利用LangChain框架(0.1.16版),该框架有助于创建AI代理。
我们还需要在加载后拆分文档,创建其嵌入并将其存储在向量存储中以便进行相似性访问。
让我们导入必要的模块并显示示例数据:
import pandas as pd
import openai
import os
from langchain.document_loaders import PyPDFLoader
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
import warnings
warnings.filterwarnings("ignore")
openai_api_key = "...."
openai.api_key = openai_api_key
因此,我们有一个示例数据集,包含时间戳、机器、每分钟由机器生产的瓶子数量、操作状态以及机器当时是否出现故障的信息,以及故障类型。
非常简单的数据,仅用于展示代理在这里是如何工作的。
所以,首先要做的是:代理必须能够分析我们的提问,并决定是否需要计算数据中的某些内容或咨询PDF文件。
这意味着它必须表现出“自主性”,并决定问题是关于“数据分析”还是“信息检索”。
如何做到这一点:
def classify_intent(question):
prompt = f"将以下问题的意图分类为'data_analysis'或'info_retrieval':{question},并仅回复意图"
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "system", "content": "您是一个分类问题的AI。"},
{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
然后提供PDF文件,以便代理进行检索:
def load_pdf_for_rag(pdf_path):
loader = PyPDFLoader(pdf_path)
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
split_docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings(api_key=openai_api_key)
vectorstore = Chroma.from_documents(split_docs, embeddings)
return vectorstore
pdf_path = "sample_machines.pdf"
if os.path.exists(pdf_path):
vectorstore = load_pdf_for_rag(pdf_path)
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
else:
retriever = None
现在“重要的内容”:如何让代理“思考”并做出决定?
def process_query(question):
intent = classify_intent(question)
if intent == "info_retrieval":
if retriever:
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(api_key=openai_api_key),
retriever=retriever)
response = qa.run(question)
return response
else:
return "机器信息不可用。"
else:
prompt = f"将以下问题转换为Python pandas命令:{question}。在您的回复中仅返回python代码,不提及其他内容,以纯文本形式。"
response = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "您是一个将问题转换为Python pandas命令的AI助手。您将被问及一个包含有关制造工厂中机器信息的数据框的问题。该数据框包含:时间戳、机器、生产的瓶子数量、操作状态、故障、故障类型。请记住,您必须仅返回python代码。"},
{"role": "user", "content": prompt}
]
)
code_snippet = response.choices[0].message.content
try:
result = eval(code_snippet, {"df": df, "pd": pd})
return result
except Exception as e:
return f"执行代码时出错:{e}"
所以代理在做什么:
- 代理收到一个问题。
- 它分析问题是关于“数据分析”还是“信息检索”。
- 如果是关于“信息检索”,它执行RAG,从向量存储中检索PDF文件,并回复机器的信息。
- 如果是关于“数据分析”,它将问题转换为Python代码并在数据集上执行该命令。
- 在任何情况下,它都使用OpenAI的API来回答问题。
还要注意系统内容和用户内容:我们需要明确告知代理如何回复(“仅代码”以便稍后执行)以及提供一些细节以使其更易于理解。
现在让我们用4个简单的问题进行测试:
queries = [
"机器A总共生产了多少瓶?",
"数据集中有哪些机器出现了故障?",
"告诉我更多关于机器B的信息。",
"机器D在做什么?我看到很多故障。"
]
问题: 机器A总共生产了多少瓶?
回答: 335
问题: 数据集中有哪些机器出现了故障?
回答: [‘D’]
问题: 告诉我更多关于机器B的信息。
回答: 机器B是一台标签机,在瓶子沿着输送带移动时贴标签。它的生产速度为每分钟450瓶,操作状态包括运行、空闲和调整。机器B的典型故障包括标签对齐不当和粘合剂故障。
问题: 机器D在做什么?我看到很多故障。
回答: 机器D,质量控制扫描仪,使用基于AI的视觉系统检查瓶子是否存在缺陷。它识别出标签不正确、密封不当和空瓶等问题。机器D提到的故障包括传感器故障和错误分类。
代理正确识别出前两个问题与计算有关,因此它创建了相应的代码并成功执行。它的回答非常简单,仅包含答案,但如果我们想,可以进行更多配置。
另外两个问题与机器信息有关,因此它检索了PDF文件并相应地回答。
代理正确遵循了规则:计划 ➡ 决策 ➡ 行动。
结论
在这个故事中,我非常简单地解释了代理人工智能的概念:可以自主决策和独立执行的系统。
为此,它们需要多种元素协同工作,例如大语言模型、检索器、向量索引和向量存储。
我还向你展示了如何用LangChain实现一个非常简单的代理,这是这种解决方案中最著名的框架之一,只需几行代码。你也可以利用其他框架,或者改进这个框架以更详细地阐述其答案。
感谢你的阅读!
感谢您成为社区的一部分
在您离开之前:
- 确保点赞和关注作者
- 欲获取更多内容,请访问 plainenglish.io + stackademic.com