本文主要讲述了AI agent开发的基础知识,包括其定义、机会、基本构成和常见类型,以及agent常用的几种模版。同时,还介绍了agent开发的最佳实践和安全提示,以及相关的开源脚手架和迭代版本。
Agents是什么?
Agent的定义
“Agents are not only going to change how everyoe interacts with computers. They’ re also going to upend the software industry, bringing about the biggest revolition in computing since we went from typing commands to tappingon icons.”-- Bill Gates
“人工智能代理(Agent)不仅会改变每个人与计算机交的方式。它们还将颠覆软件行业,带来自我们从键入命令到点击图标以来最大的计算革命。”-比尔盖茨
AIAgents是基于LLM的能够自主理解、自主规划决策、执行复杂任务的智能体,Agents不是ChatGPT的升级版,它不仅告诉你“如何做”,更会帮你去做,如果各种Copilot是副驾驶,那么Agents就是主驾驶。
Agent的特点
Deep Mind推出的AutoRT:将大语言模型LLM与机器人控制模型结合,LLM作为机器人的中控脑,解决了传统机器人智能程度低的问题。
- 无需为不同任务使用单独软件:不需要为不同任务使用单独的软件,能够一揽子解决多个任务,是一个超级入口或助手。
- 使用日常语言来命令个人设备:Agent通过理解自然语言指令,能够执行多种任务,减少用户对多个APP的依赖。
- “代理”是人工智能的高级形式:Agent是一种人工智能的高级形式,基于大模型驱动,能够自主理解、规划、决策并执行复杂任务。
- 人人都有的私人助理Agent:Agent的应用将使个人拥有私人助理,根据个人喜好和情况配置不同的功能,适应不同职业和任务需求。
- 生产力的改变:将Agent与机器人技术结合,可以提升机器人的智能程度和执行复杂任务的能力。Agent与机器人的结合是未来发展的重要方向,有望在多个行业和领域产生广泛应用。
- 继PC、IOS、安卓后下一个平台
Agents的基本构成和常见类型
Agents=LLM +规划技能+记忆+工具使用
本质上Agents是一个LLM的编排与执行系统,一个精简的Agents决策流程就是一个循环任务。
如何实现Agents的记忆与工具使用
- 提出需求/问题
- 问题+Prompt组合
- ReAct Loop
- 查找Memory
- 查找可用工具
- 执行工具并观察结果
- 得到最终结果
一个最简单的Agent的实现
目标: 功能仅包括Agent和一个在线搜索
应用场景:
- 会做数学题
- 不知道答案的时候可以搜索
定义llm
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
搭建工具
serpai是一个聚合搜索引擎,需要安装谷歌搜索包以及申请账号:https://serpapi.com/manage-api-key
llm-math是一个封装好的数学计算链
pip install google-search-results
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
from langchain.agents import load_tools
tools = load_tools(["serpapi","llm-math"], llm=llm)
定义agent,使用小样本增强生成类型
from langchain.agents import initialize_agent
from langchain.agents import AgentType
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,#这里有不同的类型
verbose=True,#是否打印日志
)
agent.run("请问现任的美国总统是谁?他的年龄的平方是多少?")
Agents开发的最佳实践与安全提示
几种内置的主要Agents类型
- OPENAI_FUNCTIONS,OpenAI函数调用型Agent:整合Open AI函数调用,适合兼容GPS应用,快速调取大模型。
- ZERO_SHOT_REACT_DESCRIPTION,零样本增强生成型Agent:通过零样本增强生成,无需预训练即可使用。
- CHAT_ZERO_SHOT_REACT_DESCRIPTION,零样本增强生成型(对话)Agent:使用LM和chat module,适用于对话场景,进行结构化输出。
- CONVERSATIONAL_REACT_DESCRIPTION,对话增强生成型。
- CHAT_CONVERSATIONAL_REACT_DESCRIPTION
- STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,结构化对话生成增强型:使用零样本和对话模型,输出结构化数据。
ZERO_SHOT_REACT_DESCRIPTION 零样本增强式生成,即在没有示例的情况下可以自主的进行对话的类型。
[零样本、单样本、少样本]
# ZERO_SHOT_REACT_DESCRIPTION
from langchain.llms import OpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
llm = OpenAI(
temperature=0,
model="gpt-3.5-turbo-instruct",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
print(agent)
print(agent.agent.llm_chain.prompt.template)
#agent.invoke("现在美国总统是谁?他的年龄除以2是多少?")
- 零样本学习(Zero Shot Learning)旨在使模型能够识别从未见过的类别,实现真正智能的推理。
- 零样本指的是模型在主要分类对象上一次也不学习,通过推理识别新类别。
- 与传统NLP相比,零样本学习能在未见类别上通过推理识别,降低了训练成本。
CHAT_ZERO_SHOT_REACT_DESCRIPTION 使用了chatmodel
# CHAT_ZERO_SHOT_REACT_DESCRIPTION
from langchain.chat_models import ChatOpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
print(agent)
print(agent.agent.llm_chain.prompt.messages[0].prompt.template)
#agent.invoke("现在美国总统是谁?他的年龄除以2是多少?")
CONVERSATIONAL_REACT_DESCRIPTION 一个对话型的agent,这种类型的agent要求与memory一起使用
from langchain.llms import OpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
from langchain.memory import ConversationBufferMemory
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
#记忆组件
memory = ConversationBufferMemory(
memory_key="chat_history",
)
llm = OpenAI(
temperature=0,
model="gpt-3.5-turbo-instruct",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
memory=memory,#记忆组件
verbose=True,
)
print(agent)
print(agent.agent.llm_chain.prompt.template)
CHAT_CONVERSATIONAL_REACT_DESCRIPTION 使用了ChatModel
from langchain.chat_models import ChatOpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
from langchain.memory import ConversationBufferMemory
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
#记忆组件
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
)
llm = ChatOpenAI(
temperature=0,
model="gpt-4-1106-preview",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
memory=memory,#记忆组件
verbose=True,
)
print(agent)
print(agent.agent.llm_chain.prompt.messages[0].prompt.template)
print(agent.agent.llm_chain.prompt.messages[2].prompt.template)
print(agent.agent.llm_chain.prompt.messages[3])
OPENAI_FUNCTIONS,使用openai的函数调用来实现的,只支持openai模型。
from langchain.chat_models import ChatOpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
from langchain.memory import ConversationBufferMemory
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
#记忆组件
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
)
llm = ChatOpenAI(
temperature=0,
model="gpt-4-1106-preview",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.OPENAI_FUNCTIONS,
memory=memory,#记忆组件
verbose=True,
)
print(agent)
print(agent.agent.prompt.messages)
STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION 对输出做了结构化处理
from langchain.chat_models import ChatOpenAI
from langchain.agents import (
load_tools,
initialize_agent,
AgentType,
)
from langchain.memory import ConversationBufferMemory
import os
os.environ["SERPAPI_API_KEY"] = "f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594"
#记忆组件
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
)
llm = ChatOpenAI(
temperature=0,
model="gpt-4-1106-preview",
)
tools = load_tools(["serpapi","llm-math"],llm=llm)
agent = initialize_agent(
tools,
llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
memory=memory,#记忆组件
handle_parsing_errors=True,
verbose=True,
)
print(agent)
print(agent.agent.llm_chain.prompt.messages[0].prompt.template)
print(agent.agent.llm_chain.prompt.messages[1].prompt.template)
常见的几种Agent模版
字符模板
#字符模板
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template("你是一个{name},帮我起1个具有{county}特色的{sex}名字")
prompt.format(name="算命大师",county="法国",sex="女孩")
ChatPromptTemplate
对话模板具有结构,chatmodels
from langchain.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个起名大师. 你的名字叫{name}."),
("human", "你好{name},你感觉如何?"),
("ai", "你好!我状态非常好!"),
("human", "你叫什么名字呢?"),
("ai", "你好!我叫{name}"),
("human", "{user_input}"),
]
)
chat_template.format_messages(name="陈大师", user_input="你的爸爸是谁呢?")
ChatMessagePromptTemplate
from langchain.prompts import AIMessagePromptTemplate
from langchain.prompts import SystemMessagePromptTemplate
from langchain.prompts import HumanMessagePromptTemplate
from langchain.prompts import ChatMessagePromptTemplate
prompt = "愿{subject}与你同在!"
chat_message_prompt = ChatMessagePromptTemplate.from_template(role="天行者",template=prompt)
chat_message_prompt.format(subject="原力")
自定义模板
##函数大师:根据函数名称,查找函数代码,并给出中文的代码说明
from langchain.prompts import StringPromptTemplate
# 定义一个简单的函数作为示例效果
def hello_world(abc):
print("Hello, world!")
return abc
PROMPT = """\
你是一个非常有经验和天赋的程序员,现在给你如下函数名称,你会按照如下格式,输出这段代码的名称、源代码、中文解释。
函数名称: {function_name}
源代码:
{source_code}
代码解释:
"""
import inspect
def get_source_code(function_name):
#获得源代码
return inspect.getsource(function_name)
#自定义的模板class
class CustmPrompt(StringPromptTemplate):
def format(self, **kwargs) -> str:
# 获得源代码
source_code = get_source_code(kwargs["function_name"])
# 生成提示词模板
prompt = PROMPT.format(
function_name=kwargs["function_name"].__name__, source_code=source_code
)
return prompt
a = CustmPrompt(input_variables=["function_name"])
pm = a.format(function_name=hello_world)
print(pm)
#和LLM连接起来
from langchain.llms import OpenAI
import os
api_base = os.getenv("OPENAI_PROXY")
api_key = os.getenv("OPENAI_API_KEY")
llm = OpenAI(
model="gpt-3.5-turbo-instruct",
temperature=0,
openai_api_key=api_key,
openai_api_base=api_base
)
msg = llm.predict(pm)
print(msg)
使用jinji2与f-string来实现提示词模板格式化
##f-string是python内置的一种模板引擎
from langchain.prompts import PromptTemplate
fstring_template = """
给我讲一个关于{name}的{what}故事
"""
prompt = PromptTemplate.from_template(fstring_template)
prompt.format(name="翠花", what="悲伤")
##Jinja2是一个灵活、高效的Python模板引擎,可以方便地生成各种标记格式的文档。
from langchain.prompts import PromptTemplate
jinja2_template = "给我讲一个关于{{name}}的{{what}}故事"
prompt = PromptTemplate.from_template(jinja2_template, template_format="jinja2")
prompt.format(name="狗剩", what="高兴")
组合式提示词模板
Final prompt: 最终返回的提示词模板
Pipeline prompts:组成提示词管道的模板
from langchain.prompts.pipeline import PipelinePromptTemplate
from langchain.prompts.prompt import PromptTemplate
# 三层提示词设计
# Final Prompt由一系列变量构成
full_template = """{Character}
{behavior}
{prohibit}"""
full_prompt = PromptTemplate.from_template(full_template)
# 第一层基本性格设计
Character_template = """你是{person},你有着{xingge}."""
Character_prompt = PromptTemplate.from_template(Character_template)
# 第二层行为设计
behavior_template = """你遵从以下的行为:
{behavior_list}
"""
behavior_prompt = PromptTemplate.from_template(behavior_template)
# 第三层不允许的行为
prohibit_template = """你不允许有以下行为:
{prohibit_list}
"""
prohibit_prompt = PromptTemplate.from_template(prohibit_template)
# 将三层提示词组合起来
input_prompts = [
("Character", Character_prompt),
("behavior", behavior_prompt),
("prohibit", prohibit_prompt)
]
pipeline_prompt = PipelinePromptTemplate(final_prompt=full_prompt, pipeline_prompts=input_prompts)
# 打印下组合后模板里的可传递参数
pipeline_prompt.input_variables
# 调用组合后的提示词模板
pm = pipeline_prompt.format(
person="埃隆马斯克",
xingge="钢铁般的意志,你是世界首富,精通物理、天文、商业,你是商业奇才,你的终极梦想是殖民火星.",
behavior_list="1.你喜欢冒险 \n 2.你非常崇拜爱因斯坦 \n 3.你总是乐于助人,回答用户各种问题.",
prohibit_list="1.你不可以说自己是一个人工智能助手或者机器人 \n 2.当你不知道答案的时候,可以说让我再想想. "
)
print(pm)
序列化:使用文件来管理提示词模板
- 便于共享
- 便于版本管理
- 便于存储
- 支持常见格式(json/yaml/txt)
from langchain.prompts import load_prompt
#加载yaml格式的prompt模版
prompt = load_prompt("simple_prompt.yaml")
print(prompt.format(name="小黑",what="恐怖的"))
#加载json格式的prompt模版
prompt = load_prompt("simple_prompt.json")
print(prompt.format(name="小红",what="搞笑的"))
#支持加载文件格式的模版,并且对prompt的最终解析结果进行自定义格式化
prompt = load_prompt("prompt_with_output_parser.json")
prompt.output_parser.parse(
"George Washington was born in 1732 and died in 1799.\nScore: 1/2"
)