基于A2A/MCP的AI Agent架构(二)

115 阅读12分钟

基于MCP主机、客户端和服务器的AI智能体

本节将探讨Anthropic的模型上下文协议(Model Context Protocol,MCP)所定义的MCP主机(MCP Host)、MCP客户端(MCP Client)和MCP服务器(MCP Server)组件。该协议的一大优势是,任何遵循此协议的AI智能体都能够利用任何MCP服务器实现的所有专业功能来完成任务。当AI智能体这样做时,它也就成为了我们所说的MCP主机。

要实现这一点,首先必须向AI智能体注册一个或多个MCP服务器;具体注册方式因AI智能体而异,但未来或许也会出现相关标准。在运行时,MCP主机会为每个MCP服务器实例化一个MCP客户端。有些MCP服务器被实现为可执行进程,与AI智能体运行在同一台本地计算机上,并通过标准输入/输出进行通信。其他MCP服务器则被实现为HTTP服务;MCP客户端通过向该服务的URL发送HTTP请求与之进行远程通信。

每个MCP服务器都向AI智能体及其协调器提供工具(函数)、资源和提示词。

MCP服务器工具

实例化MCP客户端/服务器后,AI智能体会向每个服务器请求其可用工具列表。每个工具都有名称、描述以及指定调用该工具所需的精确JSON输入的模式(schema)。以下是一个示例:

工具1:
   名称:calculate_sum
   描述:将两个数字相加
   输入模式(InputSchema):
        {
           type: "object",
           properties: {
              a: { type: "number" },
              b: { type: "number" }
           },
           required: ["a", "b"]
        }

工具2:
   名称:execute_command
   描述:运行shell命令
   输入模式(InputSchema):
        {
           type: "object",
           properties: {
              command: { type: "string" },
              args: { type: "array", items: { type: "string" } }
           }
        }

然后,AI智能体的协调器会收集上述所有工具信息,并将其添加到最新的对话用户消息中。之后,对话会被发送给AI模型,模型可能会输出协调器应调用的工具的精确名称。AI模型会根据工具的文本描述选择最合适的工具。此外,AI模型还会输出一个精确的JSON对象,其值与输入模式匹配;这些值由AI模型根据属性名称进行初始化。

AI模型可能会让协调器调用多个工具。例如,对于“巴黎的天气和当前时间是什么?”这样的提示,需要调用一个获取巴黎天气的工具,以及另一个获取巴黎当前时间的工具。协调器可以并行执行这两个调用以提高性能。

调用工具后,工具的字符串输出会被放入一条新消息中,并附加到对话中。

以下是可视化上述工作流程的图表:

使用工具时,有几个注意事项需要了解:

  • 由于AI模型可能存在缺陷,它可能不会选择最佳工具,还可能生成损坏或不合适的JSON对象。协调器无法检测到这一点,因此强烈建议AI智能体在调用工具前提示人类请求许可。这样做还能让人类在将JSON对象发送到某个任意工具之前,检查其中是否包含敏感数据。

  • 协调器向AI模型提供的工具越多,选中最佳工具的可能性就越低。协调器可能会采用描述关键词匹配、语义相似性或预定义映射等技术,从大量潜在工具中筛选出少数相关的工具。

  • 即使AI模型选择了最佳工具并准备了完美的JSON对象,工具的代码也可能执行任何操作,这可能会带来严重后果(比如删除数据)。这也是许多协调器在调用工具前请求人类许可的另一个原因。

MCP服务器资源

AI智能体可能支持读取资源/文件,并将其数据包含在传递给AI模型的对话用户消息(提示词)中,以便AI模型对这些数据进行推理。

实例化MCP服务器后,AI智能体会向每个MCP服务器请求其可用资源列表。每个资源必须有名称和URI,还可以选择性地包含MIME类型和描述。以下是示例:

资源1:
   名称:应用程序日志(Application Logs)
   URI:file:///logs/app.log
   MIME类型:text/plain
   描述:应用程序的日志文件。

资源2:
   名称:年度报告(Annual Report)
   URI:https://contoso.com/annual-report.pdf
   MIME类型:application/pdf
   描述:Contoso公司的年度报告。

资源3:
   名称:温度(Temperature)
   URI:http://temperature/{deviceName}{?units}
   MIME类型:text/plain
   描述:设备温度。

资源4:
   名称:股票信息(Stock Info)
   URI:http://stock/{ticker}
   MIME类型:application/json
   描述:股票详情。

上面的资源3和资源4是使用资源模板URI的示例。这些URI包含遵循RFC 6570语法的变量。要从URI模板资源读取数据,需要填充变量;填充操作可由人类、了解模板变量并知道如何设置它们的AI智能体,或AI模型执行。

选择要读取的资源URI取决于AI智能体的具体情况。如果AI智能体提供用户界面,那么它可以允许人类从可用资源列表中进行选择。或者,AI智能体可以创建包含某些资源属性(描述、URI等)的非精确提示消息,并让AI模型精确输出资源URL;以下是此类提示词的示例:

根据以下URL,获取office-23恒温器的摄氏温度:

应用程序的日志文件:file:///logs/app.log
Contoso公司的年度报告:https://contoso.com/annual-report.pdf
设备温度:http://temperature/{deviceName}{?units}
股票详情:http://stock-info/{ticker}

仅返回URL

当我将这个非精确输入提示词发送给AI模型时,得到了以下填充好变量的精确输出:

http://temperature/office-23?units=celsius

一旦选定资源URI,AI智能体会请求所属的MCP服务器读取该URI的数据。这些数据通常会嵌入到下一条消息提示词中,附加到对话历史中,然后发送给AI模型进行处理。

MCP服务器提示词

AI智能体可能支持从MCP服务器获取提示词建议的功能。通常,这些提示词建议由人类通过斜杠命令、快捷操作、上下文菜单项、命令面板条目等方式选择。当然,这需要AI智能体具备用户界面,比如应用程序或网站;请参见本文后面的UI AI智能体部分。

实例化MCP服务器后,UI AI智能体会向每个MCP服务器请求其有用的提示词列表。每个提示词必须有名称、描述和一组参数。以下是一个示例:

提示词1:
   名称:analyze-code
   描述:分析代码以寻找潜在改进点
   参数1:
      名称:language
      描述:编程语言
      必填:是
提示词2:
   名称:analyze-project
   描述:分析项目日志和代码
   参数1:
      名称:time-frame
      描述:要分析日志的时间段
      必填:是
   参数2:
      名称:fileUri
      描述:要审查的代码文件的URI
      必填:是

如前所述,通常由人类选择提示词,但协调器也可以通过描述关键词匹配、语义相似性或预定义映射来选择提示词。一旦选定提示词,参数值必须由人类或AI模型提供。

然后,协调器将名称/参数发送给MCP服务器,服务器会返回一条或多条包含参数值的专用消息给协调器。这些消息中还可能包含一些MCP服务器的资源数据。例如,当MCP服务器接到处理analyze-project提示词的请求,且参数为time-frame=1h、fileUri=file:///path/to/code.py时,可能返回以下消息:

用户消息(AI模型提示指令):
   文本:分析这些系统日志和代码文件,查找任何问题:

用户消息(从资源URI附加到AI模型提示):
   URI:logs://recent?timeframe=1h
   MIME类型:text/plain
   文本:[2024–03–14 15:32:11] 错误:network.py:127中连接超时
         [2024–03–14 15:32:15] 警告:正在重试连接(第2次/共3次)
         [2024–03–14 15:32:20] 错误:已超过最大重试次数

用户消息(从另一个资源URI附加到AI模型提示):
   URI:file:///path/to/code.py
   MIME类型:text/x-python
   文本:def connect_to_service(timeout=30):
            retries = 3
            for attempt in range(retries):
               try:
                  return establish_connection(timeout)
               except TimeoutError:
                  if attempt == retries - 1:
                     raise
                  time.sleep(5)

         def establish_connection(timeout):
            # 连接实现代码
            pass

协调器将这3条用户消息附加到对话中,并将更新后的对话传递给其AI模型进行处理。AI模型的输出由协调器按常规方式处理:调用工具或将智能体消息附加到对话中。之后,协调器会循环继续对话,直至任务完成。

MCP服务器采样

MCP服务器可能希望在其部分内部工作中使用AI模型。MCP协议通过一项名为“采样(sampling)”的功能来满足这一需求。借助采样功能,MCP服务器会向AI智能体发送一条sampling/createMessage消息,请求其使用自身的某个AI模型来完成这项工作。这种方式的好处是,MCP服务器自身无需配置、付费或管理用于访问AI模型的API密钥/机密。虽然对于需要此功能的MCP服务器来说这听起来很不错,但实际上,支持采样功能的主流MCP客户端寥寥无几。

MCP服务器根目录

AI智能体可能希望将其MCP服务器的注意力集中在特定的资源子集上。典型示例是,集成开发环境(IDE,如VS Code)会将当前项目代码文件的根目录发送给所有MCP服务器,以便它们只关注项目的源代码文件(资源),而非用户电脑上的所有文件。AI智能体会向其MCP服务器发送根目录(一组URI)。这些URI通常是文件系统路径(file:),但也可以是其他类型的路径。以下是MCP服务器可能接收到的根目录示例:

{
  "roots": [
    {
      "uri": "file:///home/user/projects/frontend",
      "name": "Frontend Repository"
    },
    {
      "uri": "https://api.example.com/v1",
      "name": "API Endpoint"
    }
  ]
}

在AI智能体的生命周期内,它可能会向其MCP服务器发送新的根目录URI列表。例如,当IDE用户打开另一个项目时。与采样功能类似,支持根目录功能的主流MCP主机也寥寥无几。

用户界面(UI)AI智能体

在前面的讨论中,我们将AI智能体定位为远程HTTP服务。然而,客户端应用程序或网站本身也可以作为独立的AI智能体,拥有自己的协调器、AI模型、知识库(RAG)、AI智能体列表以及MCP客户端/服务器。但这些AI智能体具备用户界面(UI),而非监听HTTP请求。微软将任何“基于AI构建用户界面”的应用程序或网站称为“Copilot(辅助程序)”。当然,人类通过用户界面与这类AI智能体(辅助程序)进行交互。以下是前面展示过的图表的更新版本,其中包含了用户界面AI智能体。

由于我们已经讨论过AI智能体,关于用户界面AI智能体,除了它具备用户界面外,没有太多额外内容需要说明。用户界面AI智能体通常采用类聊天界面:人类输入用户消息,协调器进行处理,最终的智能体消息会在界面中显示出来。

不过,与普通AI智能体不同,用户界面AI智能体可以访问应用程序或网站可用的任何上下文、资源、工具或提示词。实际上,用户界面AI智能体本身也是一个MCP服务器。事实上,用户界面AI智能体可以将自身功能实现为内部MCP服务器,而非本地或远程MCP服务器。这简化了用户界面AI智能体的代码实现(除非该智能体需要更丰富或更深度集成的资源/工具访问权限)。当然,用户界面AI智能体也可以利用其他远程AI智能体以及任何本地安装或远程可访问的MCP服务器。

结语

综上所述,AI智能体的架构整合了由不同个人和组织开发的各类组件。其真正的优势、能力和灵活性来自于各类组件对行业标准的采用,例如谷歌的Agent-to-Agent(A2A)协议和Anthropic的模型上下文协议(MCP)。本文全面概述了这些组件及其交互方式,强调了精确和非精确数据处理的重要性,以及协调器在管理对话和任务中的作用。

AI技术的不断发展有望带来更复杂、更强大的AI智能体。多AI模型的集成、高级工具和资源的使用,以及自主处理复杂任务的能力,只是未来令人期待的诸多发展方向中的一部分。