内容目录

前言

电影《钢铁侠》中的智能助手J.A.R.V.I.S.是一位得力的助手,它不但有强大的理解能力,而且还具备执行行动的能力。随着技术的不断进步,类似于贾维斯的Agent正在逐步从银幕走进现实。本文将探讨Agent的产生背景,并结合一些代码示例理解Agent。

Agent的产生背景

一个例子

# 引入Qwen大模型
from utils import get_qwen_models

llm , chat, _ = get_qwen_models()

chat.invoke("现在几点了?")

运行结果:

AIMessage(content='我是一个AI模型,无法实时获取当前时间。请您查看您的设备或询问周围的人来获取准确的时间。', 
response_metadata={'model_name': 'qwen-max', 
'finish_reason': 'stop', 
'request_id': 'cc11822c-605c-9b94-b443-85d30c9b6c0f', 
'token_usage': {'input_tokens': 12, 'output_tokens': 24, 'total_tokens': 36}}, 
id='run-bb389bae-6801-4e53-a67c-5d41a53aba8c-0')

通过与大模型的交流,我们会发现大模型无法回答实时类的问题,例如:

  • 今天是几月几号?
  • 北京现在的天气是多少?
  • ……

大模型可以接受输入,可以分析&推理、可以输出文字\代码\媒体。然而,它无法像人类一样,拥有规划思考能力、运用各种工具与物理世界互动,以及拥有人类的记忆能力。

如何给大模型配备上与物理世界互动的能力,那么会怎样呢?

Agent的实例

定义工具函数

第一步:实现一个获取当前时间的函数:

# 定义一个获取当前时间的函数
def get_datetime() -> str:
    """
        跟时期或时间查询相关的问题,请调用此方法
        注意:
            - 此方法没有入参
            - 返参是字符串形式的日期
    """
# 调用该函数
get_datetime()

运行结果:

'2024-08-29 20:39:34'

定义Prompt模板

第二步:定义使用工具的Prompt模板

from langchain.prompts import PromptTemplate

prompt = PromptTemplate.from_template("""
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought:{agent_scratchpad}
""")

创建Agent并调用

第三步:创建Agent并调用Agent

from langgraph.prebuilt import create_react_agent
from langchain_core.messages import HumanMessage

agent = create_react_agent(model=chat, tools=[get_datetime])

# 调用代理
try:
    response = agent.invoke({"messages": [HumanMessage(content="现在几点了?")]})
    print(response)
except KeyError as e:
    print(f"KeyError: {e}")
except Exception as e:
    print(f"发生错误: {e}")

运行结果:

{'messages': 
  [
    HumanMessage(content='现在几点了?', id='1e807299-fb54-4fd9-ba16-71b2c45dab98'), 
    AIMessage(content='', additional_kwargs={
      'tool_calls': [{
        'function': {
          'name': 'get_datetime', 
          'arguments': '{}'}, 
          'index': 0, 
          'id': 'call_d21bf57fd5df4314941b9e', 
          'type': 'function'
        }]}, 
        response_metadata={
          'model_name': 'qwen-max', 
          'finish_reason': 'tool_calls', 
          'request_id': '95c8bf84-3105-91c7-988f-430ef4f3bb84', 
          'token_usage': {'input_tokens': 180, 'output_tokens': 12, 'total_tokens': 192}}, id='run-9b8c496f-4e2a-4698-bb6d-9fec655c3e37-0', 
          tool_calls=[{
            'name': 'get_datetime', 
            'args': {}, 
            'id': 'call_d21bf57fd5df4314941b9e', 
            'type': 'tool_call'}]), 
    ToolMessage(content='2024-08-30 14:52:29', 
      name='get_datetime', 
      id='ce53e86f-252a-4c6d-b33b-1589732ebbbb', 
      tool_call_id='call_d21bf57fd5df4314941b9e'), 
    AIMessage(content='现在的时间是14点52分29秒。', 
      response_metadata={
        'model_name': 'qwen-max', 
        'finish_reason': 'stop', 
        'request_id': 'adb16577-6a8e-937d-8c13-0d6ba44e5082', 
        'token_usage': {'input_tokens': 220, 'output_tokens': 17, 'total_tokens': 237}}, 
        id='run-fd7835ae-b7f2-41d2-b7f9-4a33a51cd67b-0')
  ]
}

通过上述代码,可以看到大模型通过Agent被赋予了调用 get_datetime() 的能力,从而可以回答实时类问题:现在几点了?

完整代码如下:


import datetime
from langchain.prompts import PromptTemplate
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import HumanMessage
from utils import get_qwen_models

# 连接大模型
llm , chat, _ = get_qwen_models()

# 定义调用函数
def get_datetime() -> str:
    """
    获取当前时间
    """
    now = datetime.datetime.now()
    formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")

    return formatted_date

# 给大模型绑定工具
bined_chat = chat.bind_tools(tools=[get_datetime])

# 创建使用工具的prompt
prompt = PromptTemplate.from_template("""
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought:{agent_scratchpad}
""")

# 创建Agent
agent = create_react_agent(model=chat, tools=[get_datetime])

# 调用Agent
try:
    response = agent.invoke({"messages": [HumanMessage(content="现在几点了?")]})
    print(response)
except KeyError as e:
    print(f"KeyError: {e}")
except Exception as e:
    print(f"发生错误: {e}")

Agent的简介

概念

LLM Agent 是一种能产出不单是简单文本的 AI 系统,它作为一种人工智能体,具备环境感知能力、自主理解、决策制定及执行行动能力的智能实体。简而言之,它是构建于大模型之上的计算机程序,能够模拟独立思考过程,灵活调用各类工具,逐步达成预设目标的智能存在。

构成

如图所示,在基于 LLM 的智能体中,LLM 的充当着智能体的“大脑”的角色,同时还有 3 个关键部分:

  • 规划(Planning): 智能体会把大型任务分解为子任务,并规划执行任务的流程;智能体会对任务执行的过程进行思考和反思,从而决定是继续执行任务,或判断任务完结并终止运行。
  • 记忆(Memory): 短期记忆,是指在执行任务的过程中的上下文,会在子任务的执行过程产生和暂存,在任务完结后被清空。长期记忆是长时间保留的信息,一般是指外部知识库,通常用向量数据库来存储和检索。
  • 工具使用(Tool use): 为智能体配备工具 API,比如:计算器、搜索工具、代码执行器、数据库查询工具等。有了这些工具 API,智能体就可以是物理世界交互,解决实际的问题。

Agent的一些示例

示例1:数据库查询工具

第一步:使用已封装好的 utils 连接大模型

# 连接大模型
from utils import get_qwen_models

llm, chat, embed = get_qwen_models()

第二步:连接数据库


# 连接数据库
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///博金杯比赛数据.db")

数据库可以从魔塔社区上拉取到。

第三步:初始化SQL工具包

from langchain_community.agent_toolkits import SQLDatabaseToolkit

# 初始化数据库工具包,传入数据库连接对象 db 和语言模型 llm
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# 从工具包中获取可用的工具,并将其存储在 tools 变量中
tools = toolkit.get_tools() 

第四步:构建Prompt

from langchain_core.messages import SystemMessage

SQL_PREFIX = """You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 results.
You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

To start you should ALWAYS look at the tables in the database to see what you can query.
Do NOT skip this step.
Then you should query the schema of the most relevant tables."""

system_message = SystemMessage(content=SQL_PREFIX)

以上Prompt可以从https://smith.langchain.com/hub 查询 langchain-ai/sql-agent-system-prompt 得到。

第五步:创建Agent

from langgraph.prebuilt import create_react_agent

# 创建Agent,传入 chat、工具 tools 和 第四步的 prompt
agent_executor = create_react_agent(chat, tools, messages_modifier=system_message)

第六步:调用Agent并打印执行过程


# 查询
example_query = "请帮我查询出20210415日,建筑材料一级行业涨幅超过5%(不包含)的股票数量"

# 流式处理事件
events = agent_executor.stream(
    {"messages": [("user", example_query)]},
    stream_mode="values",
)

# 打印流式事件的消息
for event in events:
    event["messages"][-1].pretty_print()

执行结果:

================================ Human Message =================================

请帮我查询出20210415日,建筑材料一级行业涨幅超过5%(不包含)的股票数量
================================== Ai Message ==================================
Tool Calls:
  sql_db_list_tables (call_c14a5fc51d324381926311)
 Call ID: call_c14a5fc51d324381926311
  Args:
    tool_input:
================================= Tool Message =================================
Name: sql_db_list_tables

A股公司行业划分表, A股票日行情表, 基金份额持有人结构, 基金债券持仓明细, 基金可转债持仓明细, 基金基本信息, 基金日行情表, 基金股票持仓明细, 基金规模变动表, 港股票日行情表
================================== Ai Message ==================================
Tool Calls:
  sql_db_schema (call_f9acd6019db64e93a74987)
 Call ID: call_f9acd6019db64e93a74987
  Args:
    table_names: A股公司行业划分表, A股票日行情表
================================= Tool Message =================================
Name: sql_db_schema

CREATE TABLE "A股公司行业划分表" (
    "股票代码" TEXT, 
...
[(74,)]
================================== Ai Message ==================================

在2021年04月15日,建筑材料一级行业涨幅超过5%(不包含)的股票数量为74只。

最终,大模型借助SQL工具,查到了结果:2021年04月15日,建筑材料一级行业涨幅超过5%(不包含)的股票数量为74只。

完整代码:

from langchain_community.utilities import SQLDatabase
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
from utils import get_qwen_models

# 连接大模型
llm, chat, embed = get_qwen_models()

# 连接数据库
db = SQLDatabase.from_uri("sqlite:///博金杯比赛数据.db")

# 初始化SQL工具包
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
tools = toolkit.get_tools() 

# 构建Prompt
SQL_PREFIX = """You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 results.
You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

To start you should ALWAYS look at the tables in the database to see what you can query.
Do NOT skip this step.
Then you should query the schema of the most relevant tables."""

system_message = SystemMessage(content=SQL_PREFIX)

# 创建Agent
agent_executor = create_react_agent(chat, tools, messages_modifier=system_message)

# 查询
example_query = "请帮我查询出20210415日,建筑材料一级行业涨幅超过5%(不包含)的股票数量"

events = agent_executor.stream(
    {"messages": [("user", example_query)]},
    stream_mode="values",
)

# 查看工具调用过程
for event in events:
    event["messages"][-1].pretty_print()

示例2:维基百科搜索工具

通过对 示例1 的分析,我们可以在Langchain官网上找到不少tools工具,接下来我们实现一个维基百科搜索工具。

第一步:安装依赖包

pip install wikipedia

第二步:执行代码


from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
from utils import get_qwen_models

# 连接大模型
llm, chat, embed = get_qwen_models()

wikipedia = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
tools = [wikipedia]

# 构建Prompt
wiki_PREFIX = """你是一个搜索专家,可以根据用户提出的问题,为用户搜索相应的内容.
你可以使用维基百科工具来搜索相关的内容。

如果搜索不到对应的内容,你可以对问题进行相关性引申3个问题,来丰富查询过程。
搜索后的结果,请使用markdown的方式返回。
"""

system_message = SystemMessage(content=wiki_PREFIX)

# 创建Agent
agent_executor = create_react_agent(chat, tools, messages_modifier=system_message)

# 查询
example_query = "请帮我查询出美国林肯号航母的相关信息"

events = agent_executor.stream(
    {"messages": [("user", example_query)]},
    stream_mode="values",
)

# 查看工具调用过程
for event in events:
    event["messages"][-1].pretty_print()

运行结果:


请帮我查询出美国林肯号航母的相关信息
================================== Ai Message ==================================
Tool Calls:
  wikipedia (call_78e651d21ea44eafa47741)
 Call ID: call_78e651d21ea44eafa47741
  Args:
    query: USS Abraham Lincoln (CVN-72)
================================= Tool Message =================================
Name: wikipedia

Page: USS Abraham Lincoln (CVN-72)
Summary: USS Abraham Lincoln (CVN-72) is the fifth Nimitz-class aircraft carrier in the United States Navy. She is the third Navy ship to have been named after the former President Abraham Lincoln. Her home port is NAS North Island, San Diego, California; she is a member of the United States Pacific Fleet. She is administratively responsible to Commander, Naval Air Forces Pacific, and operationally serves as the flagship of Carrier Strike Group 3 and host to Carrier Air Wing Nine. She was returned to the fleet on 12 May 2017, marking the successful completion of her Refueling and Complex Overhaul (RCOH) carried out at Newport News Shipyard. As of August 10, 2024, USS Abraham Lincoln and her strike group are being deployed to the Middle East as part of the U.S. response to the escalation of tensions between Iran and Israel.

Page: USS Abraham Lincoln
Summary: Two ships have borne the name Abraham Lincoln, in honor of the 16th President of the United States.

USS Abraham Lincoln (SSBN-602), a ballistic missile submarine in service from 1961 to 1981
USS Abraham Lincoln (CVN-72), an aircraft carrier commissioned in 1989 and currently in service

Page: Carrier Strike Group 9
Summary: Carrier Strike Group 9 (CSG-9 or CARSTRKGRU 9) is a U.S. Navy carrier strike group. Commander Carrier Strike Group 9 (COMCARSTRKGRU 9 or CCSG 9) is responsible for unit-level training, integrated training, and material readiness for the ships and aviation squadrons assigned to the group. The group reports to Commander, U.S. Third Fleet, which also supervises its pre-deployment training and certification that includes Composite Unit Training Exercises.
It is currently assigned to the U.S. Pacific Fleet. The Nimitz-class aircraft carrier USS Theodore Roosevelt (CVN-71) is the group's current flagship. Other group units include Carrier Air Wing 11, the Ticonderoga-class cruiser USS Lake Erie (CG-70), and the Arleigh Burke-class destroyer's USS John S. McCain (DDG-56)USS Halsey (DDG-97), and the USS Daniel Inouye (DDG-118).
The strike group traces its history to Cruiser-Destroyer Group 3, created on 30 June 1973, by the re-designation of Cruiser Destroyer Flotilla 11. From 2004, the strike group has made multiple Middle East deployments providing air forces over Afghanistan and Iraq, as well as conducting Maritime Security Operations.  The strike group received the Humanitarian Service Medal in recognition of its disaster relief efforts in Indonesia during Operation Unified Assistance in 2004–05.
================================== Ai Message ==================================

USS亚伯拉罕·林肯号(USS Abraham Lincoln,舷号CVN-72)是美国海军第五艘尼米兹级核动力航空母舰,也是第三艘以美国第16任总统亚伯拉罕·林肯命名的军舰。她的母港位于加利福尼亚州圣迭戈的北岛海军航空站,隶属于太平洋舰队。作为航母打击群3(CSG-3)的旗舰,她搭载了第9舰载机联队(Carrier Air Wing Nine)。林肯号在完成于纽波特纽斯船厂的燃料补给及复杂大修(RCOH)后,于2017年5月12日重新归队。截至2024年8月10日,亚伯拉罕·林肯号及其打击群被部署至中东地区,作为美国对伊朗和以色列之间紧张局势升级应对的一部分。

另外,还有两艘以前总统亚伯拉罕·林肯命名的舰艇:
- USS亚伯拉罕·林肯号(SSBN-602),一艘1961年至1981年间在役的弹道导弹潜艇;
- USS亚伯拉罕·林肯号(CVN-72),即目前仍在服役的航空母舰。

而航母打击群9(CSG-9)曾是亚伯拉罕·林肯号所属的打击群,但目前该打击群的旗舰为另一艘尼米兹级航母USS西奥多·罗斯福号(USS Theodore Roosevelt,CVN-71)。

内容小结

  • 大模型可以接受输入,可以分析&推理、可以输出文字\代码\媒体,但是对于实时类的问题,没有能力处理。
  • LLM Agent 是一种能产出不单是简单文本的 AI 系统,它作为一种人工智能体,具备环境感知能力、自主理解、决策制定及执行行动能力的智能实体。
  • 创建Agent的大体步骤是:
    • 连接大模型
    • 定义工具函数
    • 给大模型绑定工具
    • 构建工具的prompt
    • 创建Agent
    • 调用Agent

参考资料

一文带你了解大模型——智能体(Agent)

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

分类文章

personal_logo
Dongming
自由职业者

推荐活动

推荐文章

【项目实战】基于Agent的金融问答系统:RAG的检索增强之上下文重排和压缩
【项目实战】基于Agent的金融问答系统:RAG的检索增强之ElasticSearch
【项目实战】基于Agent的金融问答系统:前后端流程打通
【项目实战】基于Agent的金融问答系统:代码重构
【项目实战】基于Agent的金融问答系统:Agent框架的构建
【项目实战】基于Agent的金融问答系统:RAG检索模块初建成
【项目实战】基于Agent的金融问答系统:项目简介
【课程总结】day29:大模型之深入了解Retrievers解析器
【课程总结】day28:大模型之深入探索RAG流程
【课程总结】day30:大模型之Agent的初步了解
内容目录
滚动至顶部