alibaba / higress

🤖 AI Gateway | AI Native API Gateway
https://higress.io
Apache License 2.0
3.18k stars 503 forks source link

Higress的可定制化AI Agent网关插件设计 #1174

Closed xingyunyang01 closed 2 months ago

xingyunyang01 commented 2 months ago

背景: 因为大模型的能力,存在着各种不足,因此chatgpt尝试使用actions去连接外部世界。其在GPTs中,解决了场景落地问题。例如用户如果想做一个地图助手的AI应用,只需要配置高德地图API的schema描述信息与API key,就可以完成该应用的开发。GPTs可以理解各个API的作用,以及如何调用,并能根据用户query来决定何时调用。这其实就是一个可定制化的agent。

ai-agent插件设计: ai-agent设计为一个可定制化的api agent,用户按照规定的格式在插件配置中配置插件规则,例如API的作用,url,请求参数,参数说明等等信息,配置好参数化,该网关插件就变成了具备特定功能的agent插件,例如配置地图api,可以变为地图助手,配置翻译api,可以变成翻译助手。

ai-agent

如图所示分为三个部分

  1. 参数配置: 对应图中的第0步,共三种配置。 1.dashscope服务的client信息,用于在ai-agent中请求通义千问大模型 2.外部api服务商的client信息以及tools信息,例如如果要使用高德地图就配置高德地图的服务信息。 3.agent react模板的可自定义字段 本配置的具体参数配置字段如下: 名称 数据类型 填写要求 默认值 描述
    dashscope.apiKey string 必填 - 用于在访问通义千问服务时进行认证的令牌。
    dashscope.serviceName string 必填 - 通义千问服务名
    dashscope.servicePort int 必填 - 通义千问服务端口
    dashscope.domain string 必填 - 访问通义千问服务时域名
    apis.apiProvider.apiKey.in string 选填 - 在访问外部API服务时进行认证的令牌是放在header中还是放在query中,默认是header。
    apis.apiProvider.apiKey.name string 选填 - 用于在访问外部API服务时进行认证的令牌的名称。
    apis.apiProvider.apiKey.value string 选填 - 用于在访问外部API服务时进行认证的令牌的值。
    apis.apiProvider.serviceName string 必填 - 访问外部API服务名
    apis.apiProvider.servicePort int 必填 - 访问外部API服务端口
    apis.apiProvider.domain string 必填 - 访访问外部API时域名
    apis.api string 必填 - 工具的OpenAPI文档
    promptTemplate.language string 必填 - Agent ReAct模板的语言类型,包括CH和EN两种
    promptTemplate.chTemplate.question string 选填 - Agent ReAct中文模板的question部分
    promptTemplate.chTemplate.thought1 string 选填 - Agent ReAct中文模板的thought1部分
    promptTemplate.chTemplate.actionInput string 选填 - Agent ReAct中文模板的actionInput部分
    promptTemplate.chTemplate.observation string 选填 - Agent ReAct中文模板的observation部分
    promptTemplate.chTemplate.thought2 string 选填 - Agent ReAct中文模板的thought2部分
    promptTemplate.chTemplate.finalAnswer string 选填 - Agent ReAct中文模板的finalAnswer部分
    promptTemplate.chTemplate.begin string 选填 - Agent ReAct中文模板的begin部分
    promptTemplate.enTemplate.question string 选填 - Agent ReAct英文模板的question部分
    promptTemplate.enTemplate.thought1 string 选填 - Agent ReAct英文模板的thought1部分
    promptTemplate.enTemplate.actionInput string 选填 - Agent ReAct英文模板的actionInput部分
    promptTemplate.enTemplate.observation string 选填 - Agent ReAct英文模板的observation部分
    promptTemplate.enTemplate.thought2 string 选填 - Agent ReAct英文模板的thought2部分
    promptTemplate.enTemplate.finalAnswer string 选填 - Agent ReAct英文模板的finalAnswer部分
    promptTemplate.enTemplate.begin string 选填 - Agent ReAct英文模板的begin部分

示例:

dashscope:
  apiKey: xxxxxxxxxxxxxxxxxx
  domain: dashscope.aliyuncs.com
  serviceName: dashscope
  servicePort: 443
promptTemplate:
  language: CH
apis:
- apiProvider:
    domain: restapi.amap.com
    serviceName: geo
    servicePort: 80
    apiKey: 
      in: query
      name: key
      value: xxxxxxxxxxxxxxx
  api: |
    openapi: 3.1.0
    info:
      title: 高德地图
      description: 获取 POI 的相关信息
      version: v1.0.0
    servers:
      - url: https://restapi.amap.com
    paths:
      /v5/place/text:
        get:
          description: 根据POI名称,获得POI的经纬度坐标
          operationId: get_location_coordinate
          parameters:
            - name: keywords
              in: query
              description: POI名称,必须是中文
              required: true
              schema:
                type: string
            - name: region
              in: query
              description: POI所在的区域名,必须是中文
              required: true
              schema:
                type: string
          deprecated: false
      /v5/place/around:
        get:
          description: 搜索给定坐标附近的POI
          operationId: search_nearby_pois
          parameters:
            - name: keywords
              in: query
              description: 目标POI的关键字
              required: true
              schema:
                type: string
            - name: location
              in: query
              description: 中心点的经度和纬度,用逗号隔开
              required: true
              schema:
                type: string
          deprecated: false
    components:
      schemas: {}
- apiProvider:
    domain: api.seniverse.com
    serviceName: seniverse
    servicePort: 80
    apiKey: 
      in: query
      name: key
      value: xxxxxxxxxxxxxxx
  api: |
    openapi: 3.1.0
    info:
      title: 心知天气
      description: 获取 天气预办相关信息
      version: v1.0.0
    servers:
      - url: https://api.seniverse.com
    paths:
      /v3/weather/now.json:
        get:
          description: 获取指定城市的天气实况
          operationId: get_weather_now
          parameters:
            - name: location
              in: query
              description: 所查询的城市
              required: true
              schema:
                type: string
            - name: language
              in: query
              description: 返回天气查询结果所使用的语言
              required: true
              schema:
                type: string
                default: zh-Hans 
                enum:
                  - zh-Hans 
                  - en 
                  - ja 
            - name: unit
              in: query
              description: 表示温度的的单位,有摄氏度和华氏度两种
              required: true
              schema:
                type: string
                default: c 
                enum:
                  - c 
                  - f 
          deprecated: false
    components:
      schemas: {}

在上述参数配置中,为了使插件使用更加简单快捷友好,apis的部分可以结合higress网关的产品形态做了下文所介绍的设计。 因为在apis部分配置的有两块,一是服务信息,而是tools信息,因此考虑在higress的服务创建页面,增加可视化的OpenAPI配置页面。引导用户在配置服务(即上文中的toolsClientInfo要用的)后,用符合OpenAPI(swagger)规范的方式去配置tools对应的API。之后设计一个一键导出tools配置信息的按钮,点击后,可以在后台将apis配置,以yaml格式输出。 以上面的示例为例,apiProvider就是服务信息,api就是tools信息。需要将两部分的yaml分别反序列化到map[string]interface{}类型的结构中,之后将两个结构的内容拼接到一起,做一次序列化即可得到完整的yaml并输出。

  1. agent prompt模板 对应图中的1,2,3,4步骤。 在httprequest阶段,收到用户query后,代码会将tools信息以及query填入到prompt模板。prompt模板是agent的核心,规定了agent的思考过程以及输出格式,完成模板组装后,替换http request中的content,然后resume,该请求会继续通过ai-proxy来请求大模型。

  2. 工具调用 对应图中的5,6,7,8步骤。 在httpresponse阶段,会收到大模型的第一次返回,该返回信息的内容是大模型告诉我们需要调用哪个工具,以及工具的入参是什么。此时,代码需要根据返回信息的要求,去执行工具函数,拿到结果,然后添加到历史记录中,通过调用dashscope client告诉大模型工具的执行结果,然后再次等待大模型的返回,循环该过程,直到得到Final Answer跳出循环,resume response。 在这一阶段,工具函数是API的http get或者post请求,需要封装成参数无关的通用方法,即无论api是什么内容,只要是get或者post就都可以调用工具执行。从大模型拿到函数入参的解析,以及封装请求这一部分,也需要做成通用的。

本插件目前仅支持非流式模式。

johnlanni commented 2 months ago

tools client info 应该支持配置多个服务的信息。tools里每一项应该可以选择指定一个服务。

xingyunyang01 commented 2 months ago

tools client info 应该支持配置多个服务的信息。tools里每一项应该可以选择指定一个服务。

已修改设计,支持了该功能。以及增加了从服务配置OpenAPI,转换tools配置的新功能的设计。