agent 是什么?
打开市面上流行的AIGC应用,agent 几乎是必备的功能。 agent到底是什么呢?
我们先从字面意思理解,看看各家公司做的产品是如何定义 agent 的。
智谱清言 (chatglm.cn) 将 agent 定义为 “智能体”
通义千问 (tongyi.aliyun.com/)将 agent 定义为 “智能体”
Kimi (kimi.moonshot.cn/)将 agent 定义为 “私人助理”
扣子(www.coze.cn/) 将 agent 定义为 “智能体”
文心一言 (yiyan.baidu.com/) 将 agent 定义为 “智能体” (无图,拿来凑数)
agent 从英文直译过来是 “代理”,但从国内各AIGIC的产品定义来看,绝大多数公司将 agent 定义为了 “智能体”
好,我们再进一步,那什么是智能体呢?
从 “智能体” 使用者的角度看,“智能体” 就像专门完成某一类任务的机器人。智能体的设计目的其实就是为了实现特定的目标或完成特定的任务。
它像是一个专家一样,专门解决某一类的问题,用医生做比喻,agent就像一个专科大夫,比如骨科大夫,只能看骨科相关的病,而大模型LLM 像是一个全科大夫,什么病都能看。
从设计上不一样,使用上自然就要有所区别,比如你要处理和计算复杂的数学公式,那么向专门为解决这类问题而设计的 “智能体” 提问就比直接向LLM 提问得到的答案要准确。
agent 的创建和使用
我们以 智谱清言 举例,下图是在创建 “智能体” 时的设置页面内容,可以看到有不少的配置。这里面,我要说两个重要的配置。
第一个重要的配置是:“配置信息”
看上图你是否觉得很熟悉,是的,如果你看过我之前的文章,就会注意到,这不就是 "prompt" 吗? 准确地来说是 system prompt 和 role prompt
所以,在我最初的认识里,agent 或者叫 “智能体” 简直就是一个 "prompt engineering" 的产物,只需要把 “提示词” 写好,就能创建好一个 agent 了。后来,我了解到,提示词工程确实很重要,但 agent 并不是只包括设置提示词 。
除了上图所示的 “联网能力”、“代码能力” 这些显而易见的功能外。另一个重要的配置就是 “知识库” 。 加上知识库后,实际上这就是一个 RAG 应用了。这会让 agent 本身外挂一个我们自己上传的知识库,让它学习了我们上传的“知识” 后,再接受提问,就可以更准备地做出回答。
LlamaIndex
demo
用 LlamaIndex 实现一个简单的 agent demo 比较容易,看一下具体的代码实现:
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool
from llamaindex_demo.custom.custom_llm_glm import GLM4LLM
def multiply(a: float, b: float) -> float:
"""Multiply two numbers and returns the product"""
return a * b
def add(a: float, b: float) -> float:
"""Add two numbers and returns the sum"""
return a + b
def main():
multiply_tool = FunctionTool.from_defaults(fn=multiply)
add_tool = FunctionTool.from_defaults(fn=add)
# 使用GLM-4 Plus模型
llm = GLM4LLM()
# 创建ReActAgent实例
agent = ReActAgent.from_tools([multiply_tool, add_tool], llm=llm, verbose=True)
response = agent.chat("20+(2*4)等于多少?使用工具计算每一步")
print(response)
if __name__ == "__main__":
main()
LLM 上,我们继续使用之前文章中使用过的 GLM。
我们看一下它的输出
可以看出,它将提问中的计算步骤分别利用了我们自定义的函数 add
和 multiply
,而不是走大模型。挺有意思的吧,我们可以自定义 agent 中的某些处理流程。除了使用 prompt 外,我们的控制权更大了。
Rag demo
这个 demo 我们来看一下如何把rag 集成到 agent中。也很简单,我们直接上代码:
import os
import sys
import re
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.core.tools import QueryEngineTool
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llamaindex_demo import logger
from llamaindex_demo.custom.custom_llm_glm import GLM4LLM
from llamaindex_demo.custom.custom_embedding_zhipu import ZhipuEmbeddings
from llama_parse import LlamaParse
# 设置环境变量,禁用tokenizers的并行处理
os.environ["TOKENIZERS_PARALLELISM"] = "false"
def toHtml(text: str) -> str:
"""遇到英文单词就用html标签包裹"""
return re.sub(r"(\b[a-zA-Z]+\b)", r'<span style="color:red;">\1</span>', text)
def run_glm4_query_with_embeddings(query: str):
# 从指定目录加载文档数据
documents = SimpleDirectoryReader(input_files=["./data/sample.txt"]).load_data()
# 设置LLM和嵌入模型
Settings.llm = GLM4LLM()
Settings.embed_model = ZhipuEmbeddings()
# 创建索引和查询引擎 show_progress=True 显示 embedding 进度
index = VectorStoreIndex.from_documents(documents, show_progress=True)
query_engine = index.as_query_engine(streaming=True)
yc_tool = QueryEngineTool.from_defaults(
query_engine,
#name="YC 创始人的个人经理",
#description="关于YC创始人Paul Graham的RAG引擎",
)
to_html_tool = FunctionTool.from_defaults(fn=toHtml)
agent = ReActAgent.from_tools(
[to_html_tool,yc_tool],
verbose=True,
)
# 执行查询
logger.info("agent 查询结果:")
response = agent.chat(query)
print(response)
logger.info("\n查询完成")
def main():
run_glm4_query_with_embeddings("请描述一下作者的求学经历,并将英文用html高亮显示")
if __name__ == "__main__":
main()
可以看到,yc_tool
是我们通过加载本地文件自定义的一个RAG 应用,然后我们把它加入到 agent的 from tools中。
以下是加入 RAG 以后的 agent 的输出
INFO:llamaindex_demo.config:agent 查询结果:
> Running step 28bfc6bb-5e8a-4d5b-8273-36791b222a90. Step input: 请描述一下作者的求学经历,并将英文用html高亮显示
INFO:httpx:HTTP Request: POST https://open.bigmodel.cn/api/paas/v4/chat/completions "HTTP/1.1 200 OK"
Thought: The current language of the user is: Chinese. I need to use a tool to help me answer the question.
Action: query_engine_tool
Action Input: {'input': '请描述一下作者的求学经历'}
INFO:httpx:HTTP Request: POST https://open.bigmodel.cn/api/paas/v4/embeddings "HTTP/1.1 200 OK"
INFO:httpx:HTTP Request: POST https://open.bigmodel.cn/api/paas/v4/chat/completions "HTTP/1.1 200 OK"
Observation: 作者的求学经历可以概括如下:
1. **研究生阶段**:
- 作者最初在研究生院学习,但似乎对所选主题(连续性应用程序)并不满意,认为应该选择更有探索空间的宏和嵌入式语言。
- 作者的主要目标是尽快完成学业,摆脱研究生院。
2. **申请艺术学校**:
- 在研究生期间,作者同时申请了美国的罗德岛设计学院(RISD)和意大利佛罗伦萨的Accademia di Belli Arti。
- RISD录取了作者,而Accademia di Belli Arti的回复因邮寄错误延迟。
3. **在RISD的学习**:
- 作者被RISD视为转学二年级生,需要在夏季完成基础课程,包括绘画、色彩和设计等。
- 尽管如此,作者在基础课程中表现不错。
......
总体来说,作者的求学经历充满了探索和转变,从研究生院的学术研究到艺术学校的实践学习,再到通过个人项目和工作的经济独立,展现了其对知识和职业发展的不断追求和反思。
> Running step c8f8eee2-ab9b-45c9-a05e-6136f688cae3. Step input: None
INFO:httpx:HTTP Request: POST https://open.bigmodel.cn/api/paas/v4/chat/completions "HTTP/1.1 200 OK"
Thought: The current language of the user is: Chinese. I need to use a tool to help me highlight the English words in the provided text.
Action: toHtml
Action Input: {'text': '作者的求学经历可以概括如下:\n\n1. **研究生阶段**:\n - 作者最初在研究生院学习,但似乎对所选主题(连续性应用程序)并不满意,认为应该选择更有探索空间的宏和嵌入式语言。\n - 作者的主要目标是尽快完成学业,摆脱研究生院。\n\n2. **申请艺术学校**:\n - 在研究生期间,作者同时申请了美国的罗德岛设计学院(RISD)和意大利佛罗伦萨的Accademia di Belli Arti。\n - RISD录取了作者,而Accademia di Belli Arti的回复因邮寄错误延迟。\n\n3. **在RISD的学习**:\n - 作者被RISD视为转学二年级生,需要在夏季完成基础课程,包括绘画、色彩和设计等。\n - 尽管如此,作者在基础课程中表现不错。\n\n4. **意外的Accademia邀请**:\n - 夏末时,作者意外收到Accademia的入学考试邀请,决定前往佛罗伦萨。\n - 作者通过节俭生活和之前的咨询工作积蓄,勉强支付了生活和学习的费用。\n\n5. **在Accademia的学习**:\n - 作者发现Accademia的绘画系存在一种默契,即学生和教职员工互不干涉,维持着19世纪工作室的传统。\n - 这种教育模式让作者感到失望。\n\n6. **秘密项目与经济独立**:\n - 在Accademia期间,作者秘密从事《论Lisp》的工作,并获得了出版合同和一笔可观的收入。\n - 这笔收入帮助作者还清了大学贷款,并积攒了回RISD的费用。\n\n7. **在Interleaf的工作经历**:\n - 作者在Interleaf公司学到了许多关于科技公司的管理和技术开发的见解。\n - 最重要的是,作者领悟到“低端吞噬高端”的市场策略。\n\n8. **回到RISD**:\n - 作者在秋季回到RISD继续学习,发现真正的艺术学校与Accademia没有太大不同。\n - 作者观察到绘画系的教育相对松散,而其他系如纺织、插画和建筑则更为严格。\n\n总体来说,作者的求学经历充满了探索和转变,从研究生院的学术研究到艺术学校的实践学习,再到通过个人项目和工作的经济独立,展现了其对知识和职业发展的不断追求和反思。'}
Observation: 作者的求学经历可以概括如下:
1. **研究生阶段**:
- 作者最初在研究生院学习,但似乎对所选主题(连续性应用程序)并不满意,认为应该选择更有探索空间的宏和嵌入式语言。
- 作者的主要目标是尽快完成学业,摆脱研究生院。
2. **申请艺术学校**:
- 在研究生期间,作者同时申请了美国的罗德岛设计学院(<span style="color:red;">RISD</span>)和意大利佛罗伦萨的Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> <span style="color:red;">Arti</span>。
- RISD录取了作者,而Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> Arti的回复因邮寄错误延迟。
3. **在RISD的学习**:
- 作者被RISD视为转学二年级生,需要在夏季完成基础课程,包括绘画、色彩和设计等。
- 尽管如此,作者在基础课程中表现不错。
......
总体来说,作者的求学经历充满了探索和转变,从研究生院的学术研究到艺术学校的实践学习,再到通过个人项目和工作的经济独立,展现了其对知识和职业发展的不断追求和反思。
> Running step 649456af-f363-47c9-bd06-3c36d1ff48c6. Step input: None
INFO:httpx:HTTP Request: POST https://open.bigmodel.cn/api/paas/v4/chat/completions "HTTP/1.1 200 OK"
Thought: I can answer without using any more tools. I'll use the user's language to answer.
Answer: 作者的求学经历可以概括如下:
1. **研究生阶段**:
- 作者最初在研究生院学习,但似乎对所选主题(连续性应用程序)并不满意,认为应该选择更有探索空间的宏和嵌入式语言。
- 作者的主要目标是尽快完成学业,摆脱研究生院。
2. **申请艺术学校**:
- 在研究生期间,作者同时申请了美国的罗德岛设计学院(<span style="color:red;">RISD</span>)和意大利佛罗伦萨的Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> <span style="color:red;">Arti</span>。
- RISD录取了作者,而Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> Arti的回复因邮寄错误延迟。
3. **在RISD的学习**:
- 作者被RISD视为转学二年级生,需要在夏季完成基础课程,包括绘画、色彩和设计等。
- 尽管如此,作者在基础课程中表现不错。
......
总体来说,作者的求学经历充满了探索和转变,从研究生院的学术研究到艺术学校的实践学习,再到通过个人项目和工作的经济独立,展现了其对知识和职业发展的不断追求和反思。
作者的求学经历可以概括如下:
1. **研究生阶段**:
- 作者最初在研究生院学习,但似乎对所选主题(连续性应用程序)并不满意,认为应该选择更有探索空间的宏和嵌入式语言。
- 作者的主要目标是尽快完成学业,摆脱研究生院。
2. **申请艺术学校**:
- 在研究生期间,作者同时申请了美国的罗德岛设计学院(<span style="color:red;">RISD</span>)和意大利佛罗伦萨的Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> <span style="color:red;">Arti</span>。
- RISD录取了作者,而Accademia <span style="color:red;">di</span> <span style="color:red;">Belli</span> Arti的回复因邮寄错误延迟。
3. **在RISD的学习**:
- 作者被RISD视为转学二年级生,需要在夏季完成基础课程,包括绘画、色彩和设计等。
- 尽管如此,作者在基础课程中表现不错。
......
总体来说,作者的求学经历充满了探索和转变,从研究生院的学术研究到艺术学校的实践学习,再到通过个人项目和工作的经济独立,展现了其对知识和职业发展的不断追求和反思。
INFO:llamaindex_demo.config:
查询完成
可以看出,在它的思考过程中,应用了我们的 toHtml
方法,将英文单词就用html标签包裹。
agent 记忆
agent 还有记忆的功能,也就是说之前问过的问题,它会记得,比如我们在一个流程中发起了多次提问
agent 不会把每次的提问当做一个独立提问,它是知道上下文的,这就是它的记忆功能。