AI 网关零代码解决 AI 幻觉问题

news2024/9/21 0:41:53

作者:邢云阳,Higress Contributor

前言

什么是 AI Agent

随着大模型技术的快速发展,越来越多的公司在实际业务中落地了大模型应用。但是人们逐渐发现了大模型能力的不足。例如:由于大模型的训练数据是有限的,因此一些垂直领域的知识,如金融,医疗等等,大模型无法回答,或者容易出现幻觉。并且随着业务的复杂度提高,如何能让大模型像人一样思考,深度的分析解决问题,也对大模型的理解力提出了挑战。

在这样的背景下,业界提出了 AI Agent 的概念。AI Agent 中文翻译成智能体,旨在让大模型像人脑一样思考问题,通过在思考过程中的不断反馈以及工具的调用,最终实现逐步完成给定目标的过程。例如,用户使用外卖助手 Agent,只需告诉 Agent,我想点一份肯德基的上校鸡块,Agent 便可以实现搜索肯德基商家,选择食物,下单,支付等一系列的思考过程以及工具调用,无需人工参与。

什么是 AI Gateway

AI Gateway 的定义是 AI Native 的 API Gateway,是基于 API Gateway 的能力来满足 AI Native 的需求。例如:

  • 将传统的 QPS 限流扩展到 Token 限流。

  • 将传统的负载均衡/重试/fallback 能力延伸,支持对接多个大模型厂商 API,提高整体稳定性。

  • 扩展可观测能力,支持不同模型之间效果对比的 A/B Test,以及对话上下文链路 Tracing 等。

Higress [ 1] 是阿里云开源的一款 AI Gateway,基于 API Gateway 的能力,再加上基于 Wasm 插件扩展的大量 AI 插件,就可以满足上述所有 AI Native 的需求。

我也是基于 Higress 的 Wasm 插件扩展能力,开发了一个 AI Agent 插件,通过发挥 API Gateway 对于 API 管理的优势,用 API 赋能 AI Agent,基于 Agent ReAct 能力,可以实现零代码快速构建一个 AI Agent 应用。

本文将以高德地图和心知天气两个服务为例,介绍一下如何零代码使用 AI Agent 插件构建一个同时支持地图服务和天气服务的 Agent,同时会探讨 AI Agent 插件的实现原理。

AI Agent 插件使用

apiKey 申请

高德地图提供了地图相关业务的 API 服务,例如地点搜索,导航等等;心知天气提供了天气情况查询的相关 API 服务。两个服务都提供了每日免费的 API 调用次数,方便用户测试。

使用这两个服务需要去其官方网址,注册账号,申请 apiKey,有了 apiKey,便可以根据官方 API 文档去调用 API。官方文档的链接我放在下方,这里就不再赘述申请 apiKey 的过程。

高德地图:入门指南-Web 服务 API丨高德地图 API(amap.com) [ 2]

心知天气:查看/修改你的 API 密钥(yuque.com) [ 3]

Higress服务配置

为了让插件能够访问通义千问大模型以及高德地图和心知天气服务,需要在 Higress 的路由管理-服务中,配置服务。服务类型为 DNS 域名:

插件参数配置

在插件配置中,选择实例级插件规则,配置如下:

dashscope: #通义千问大模型客户端配置
  apiKey: sk-xxxxxxxxxxxxxxxxxxxxxxx
  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: fcxxxxxxxxxxxxxxxxxx
  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: SMxxxxxxxxxxxxxx
  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: {}

插件配置分三部分,第一部分 dashscope,是通义千问大模型服务的相关信息,第二部分 promptTemplate,是自定义 agent react 模板的配置项,示例中的 language 是指使用中文模板,第三部分 apis 是外部 API 服务的相关配置,包含服务相关信息 apiProvider 以及 api(tools) 的 OpenAPI 文档,这一部分是实现 agent 调用外部工具的关键,agent 会通过理解 OpenAPI 文档来理解参数应该赋什么值。

插件效果

示例请求一:

curl 'http://<这里换成网关公网IP>/api/openai/v1/chat/completions' \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
--data-raw '{"messages":[{"role":"user","content":"我想在济南市鑫盛大厦附近喝咖啡,给我推荐几个"}],"model":"qwen","stream":false}'

示例响应一:

{...,"content":" 在济南市鑫盛大厦附近,您可以选择以下咖啡店:\n1. luckin coffee 瑞幸咖啡(鑫盛大厦店),位于新泺大街1299号鑫盛大厦2号楼大堂;\n2. 三庆齐盛广场挪瓦咖啡(三庆·齐盛广场店),位于新泺大街与颖秀路交叉口西南60米;\n3. luckin coffee 瑞幸咖啡(三庆·齐盛广场店),位于颖秀路1267号;\n4. 库迪咖啡(齐鲁软件园店),位于新泺大街三庆齐盛广场4号楼底商;\n5. 库迪咖啡(美莲广场店),位于高新区新泺大街1166号美莲广场L117号;以及其他一些选项。希望这些建议对您有所帮助!"...}

示例请求二:

curl 'http://<这里换成网关公网IP>/api/openai/v1/chat/completions' \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
--data-raw '{"messages":[{"role":"user","content":"济南市现在的天气情况如何?"}],"model":"qwen","stream":false}'

示例响应二:

{..."content":" 济南市现在的天气状况为阴天,温度为31℃。此信息最后更新于2024年8月9日15时12分(北京时间)。"...}

示例请求三:

curl 'http://<这里换成网关公网IP>/api/openai/v1/chat/completions' \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
--data-raw '{"messages":[{"role":"user","content":"济南市现在的天气情况如何?用华氏度表示,用日语回答"}],"model":"qwen","stream":false}'

示例响应三:

{..."content":" 济南市の現在の天気は雨曇りで、気温は88°Fです。この情報は2024年8月9日15時12分(東京時間)に更新されました。"...}

AI Agent 实现原理

ReAct 原理

AI Agent 插件的实现是使用了 ReAct(Reasoning and Action),ReAct 一词来自于论文《ReAct: Synergizing Reasoning and Acting in Language Models》,其核心思想是通过思维链的方式,引导模型将复杂问题进行拆分,一步一步地推理(Reasoning)和行动(Action),同事还引入了观察(Observation)环节,在每次执行(Action)之后,都会先观察(Observation)当前现状,然后再进行下一步的推理(Reasoning)。

ReAct,就是要让开发者引导大模型进行推理,然后根据推理结果,判断需要采取哪个行动(调用工具),与外界环境互动。

ReAct 的工作流程如下:

插件实现逻辑

插件的工作流程如下:

AI Proxy 插件配置在默认阶段,而 AI Agent 可以配置在确保比 AI Agent 优先级高的阶段,比如认证阶段。这样可以保证用户的 http request 可以先被 AI Agent 拦截到。

AI Agent 的处理过程分为三个部分。

1. 参数配置

使用 AI Agent 需要先按上一章节的插件参数配置的格式配置好服务以及 api 相关参数,也就是图中第 0 步要做的工作。

2. prompt 模板

首先,因为 Agent 是一个一步一步思考,多次调用工具的过程,因此是一个多轮对话场景,因此 AI Agent 维护了一个 messageStore,用来存储历史对话。

整个 Agent ReAct 的控制核心就在于 prompt 模板,中文版本的模板如下:

尽你所能回答以下问题。你可以使用以下工具:

{tools}

请使用以下格式,其中Action字段后必须跟着Action Input字段,并且不要将Action Input替换成Input或者tool等字段,不能出现格式以外的字段名,每个字段在每个轮次只出现一次:
Question: 你需要回答的输入问题
Thought: 你应该总是思考该做什么
Action: 要采取的动作,动作只能是{tools_name}中的一个 ,一定不要加入其它内容
Action Input: 行动的输入,必须出现在Action后。
Observation: 行动的结果
...(这个Thought/Action/Action Input/Observation可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 对原始输入问题的最终答案
再次重申,不要修改以上模板的字段名称,开始吧!

Question: {input}

该模板指导了大模型的推理过程。

在 AI Agent 的 onHttpRequestBody 阶段,接收到用户的 query 后,例如:我要在北京五道口附近喝咖啡,帮我推荐一下,会将 query 填入 {input} 部分,同时将插件参数配置中的 api 名称,功能以及 OpenAPI 文档放在 {tools} 部分,将 api 名称放在 {tools_name} 部分。

将该 prompt 模板存入到 messageStore 中,格式为:

role: user
msg: {prompt模板}

之后通过 proxywasm.ReplaceHttpRequestBody 函数用 prompt 模板替换掉用户的原始 query,通过 ai-proxy 发送给大模型。

此部分对应图中的 1,2,3,4 步骤。

3. 推理过程(工具调用)

大模型的返回会在 AI Agent 的 onHttpResponseBody 阶段拦截到。此时首先将回复内容存储到 messageStore 中,格式为:

role: assistant
msg: {大模型的回复}

之后需要通过正则表达式来判断大模型的返回内容。

例如上文的例子,大模型会返回如下内容:

Thought: 为了提供咖啡店的推荐,我首先需要获取五道口这一地点的经纬度坐标。

Action: get_location_coordinate

Action Input: {"keywords": "五道口", "region": "北京市"}

通过正则表达式取出 Action 与 Action Input 的值,就得到了需要调用的工具名称以及参数的值。

由于通常外部 API 都会提供一个认证 apiKey,只有配置了 apiKey,才能使用 api 接口。以本例子为例,需要在 url 中包含 key={apiKey} 的参数,所以我在 apiProvider 中对 apiKey 做了设计。包含 name 和 value 两个字段,name 表示实际服务商要求的 apiKey 的名称,例如本例中的 key,value 是具体的 apiKey 值。

程序还会根据 OpenAPI 文档拼接处 url 以及查看 method 是什么,从而发送对应的 http 请求,例如本例子是要发送:

GET https://restapi.amap.com/v5/place/text?key=xxxxxx&keywords=五道口&region=北京市

该 API 的回复为:

{"status":0,"message":"成功","result":{"location":{"lng":116.352978,"lat":39.982849},"precise":1,"confidence":100,"comprehension":100}}

将该回复拼接到 Observation 后面,作为新的 query,在存储到 messageStore 后,将整个历史对话发送给大模型。此时由于处在插件的 onHttpResponseBody 阶段,无法再通过 ai-proxy 访问大模型,因此需要自己去调用 dashscope client 访问大模型。

大模型会返回如下内容:

Thought: 现在我得到了五道口的经纬度坐标,接下来我可以使用这些坐标来搜索附近的咖啡店。

Action: search_nearby_pois

Action Input: {"keywords": "咖啡", "longitude": "116.352978", "latitude": "39.982849"}

程序通过正则得到 Action 与 Action Input 后,会重复刚才的过程,组装新的 url,向高德地图发请求,然后把结果存 messageStore 后给到大模型。整个过程是一个不断递归调用的过程。

大模型会再次返回:

Thought: 我现在知道最终答案

Final Answer: 在北京市五道口附近有几家咖啡店可以选择,包括:
- 星巴克五道口店
- Costa Coffee五道口店
- 漫咖啡五道口店

您可以根据个人喜好选择前往。

这一次,程序通过可以检测到回复中包含了 Final Answer,这说明大模型已经得到了最终答案,无需再次调用工具了。因此检测到 Final Answer 就是结束递归调用的条件,此时就可以将 Final Answer 的答案通过 proxywasm.ReplaceHttpResponseBody 函数替换掉 response body 返回给用户了。

该部分对应图中的 5,6,7,8 步骤。

总结

本文主要介绍了 AI Agent 的背景,概念,探讨了 AI Agent 网关插件的使用方法,效果以及实现原理。希望对你有帮助!

插件的实现已经提交 PR 给 Higress 开源社区,可以到这里查看完整的代码实现:https://github.com/alibaba/higress/pull/1192

也欢迎大家提出宝贵建议,可以直接在上面 PR 中评论,或者在 Higress 社区交流群(钉钉群号:30735012403)里一起沟通。

相关链接:

[1] Higress

https://github.com/alibaba/higress

[2] 入门指南-Web 服务 API丨高德地图 API(amap.com)

https://lbs.amap.com/api/webservice/gettingstarted

[3] 查看/修改你的 API 密钥(yuque.com)

https://seniverse.yuque.com/hyper_data/api_v3/gc03wk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2085556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

身体发出的“高压”警报,曹启富医生教你识别高血压症状

高血压&#xff0c;这一慢性“隐形杀手”&#xff0c;正悄然影响着越来越多人的健康。随着生活节奏的加快和不良生活习惯的积累&#xff0c;其发病率逐年攀升&#xff0c;成为威胁人类健康的重要疾病之一。今天&#xff0c;我们有幸邀请到心脑血管科专家曹启富医生&#xff0c;…

摩博会15天倒计时!ONEOS 恒石智能强强联手,即将携多款MODEL系列芯片打造的智能仪表璀璨亮相

随着2024年第二十二届中国国际摩托车博览会&#xff08;摩博会&#xff09;的临近&#xff0c;国内领先的操作系统提供商ONEOS与智能硬件领域的佼佼者恒石智能宣布强强合作&#xff0c;将于9月13日至16日在重庆国家会展中心共同揭开多款MODEL系列芯片驱动的彩屏仪表的神秘面纱。…

JavaWeb - Vue项目

创建 命令行 vue create project 图形化界面 vue ui 目录结构 启动 命令行 npm run serve 端口配置 Vue的组件文件以.vue结尾 每个组件有三个部分组成&#xff1a; <template>&#xff1a;模板部分&#xff0c;由它生成HTML代码<script>&#xff1a;控制…

揭秘SQL注入漏洞:为何它成为攻击者的首选?

自Web应用程序开始广泛使用数据库以来&#xff0c;SQL注入漏洞便因其隐蔽性强、潜在危害巨大以及实施门槛相对较低等特性&#xff0c;成为了网络攻击者频繁利用的安全弱点之一。尽管这一漏洞已经存在多年&#xff0c;它仍然是企业组织在数字化转型过程中面临的最为普遍且危险的…

vue2项目 预渲染 Unable to prerender all routes 错误排查与解决方案

前言 今天在做我的Vue2项目的SEO优化时&#xff0c;我采用了prerender-spa-plugin与vue-meta-info的一套官网前端SEO预渲染方案。 但是&#xff0c;在打包时&#xff0c;报错Unable to prerender all routes。尝试了很多种网上方案&#xff0c;都没有成功&#xff0c;最后从源…

用代码和android studio创建flutter项目的区别差异

用代码创建的项目&#xff0c;在lib目录下&#xff0c;不会出现dictory文件夹&#xff0c;操作起来有些不便。

智慧灯塔,照亮企业AI Agent实施明路

AI Agent是能够感知环境&#xff0c;基于目标进行决策并执行动作的智能化应用。随着大模型能力增强以及RAG等技术的成熟&#xff0c;AI Agent的能力得到了质的飞跃。这些模型赋予了AI Agent更接近人类的思维能力&#xff0c;再联动各类工具和组件&#xff0c;使得AI Agent在处理…

虚拟机 Linux 安装 JDK(Vagrant 之二 CentOS7 篇)

本文已首发于&#xff1a;秋码记录 我们已然在上一篇讲解了如何快速的搭建一个Linux虚拟机&#xff0c;通过vagrant命令化工具&#xff0c;我们很方便的构筑了虚拟机&#xff0c;那么&#xff0c;我们所搭建出来的Linux系统主要是为了调试产品&#xff0c;以便产品在部署生产环…

电路笔记(PCB): kicad freerouting自动布线

安装插件 使用自动布线 会自动运行&#xff0c;等待布线完成即可。也可以布到一定程度&#xff0c;单击界面&#xff0c;切换到手动布线。 CG 一个替代的 freerouting 插件 https://forum.kicad.info/t/an-alternative-freerouting-plugin/52736/3

微信视频号的小视频怎么保存?视频号下载助手最实在的下载教程

最近一些朋友在私信问我视频号的视频怎么用下载助手保存到手机相册呢&#xff1f;虽说网络工具很多&#xff0c;但这个工具算是最稳定的工具之一。 软件介绍 工具名称&#xff1a;视频下载助手 工具扩展&#xff1a;视频号下载助手还拥有多种名称如&#xff1a;视频下载小助…

【开端】基于nginx部署的具有网关的web日志分析

一、绪论 基于nginx部署的具有网关的web日志分析&#xff0c;我们可以分析的日志有nginx的access.log &#xff0c;网关的日志和应用的日志 二、日志分析 1、nginx日志 参数 说明 示例 $remote_addr 客户端地址 172.17.0.1 $remote_user 客户端用户名称 -- $time_lo…

在 CentOS 7 上安装 LNMP 环境:MySQL 8.0、PHP 8.3 和 ThinkPHP 8.0

在 CentOS 7 上安装 LNMP 环境&#xff0c;并配置 MySQL 8.0、PHP 8.3 以及 ThinkPHP 8.0&#xff0c;能够为你的 web 应用程序提供一个强大的开发和运行环境。下面是详细的安装步骤&#xff1a; --- ## 在 CentOS 7 上安装 LNMP 环境&#xff1a;MySQL 8.0、PHP 8.3 和 Thin…

鸿蒙( Beta5版)开发实战:基于AVCodecKit【音视频解码】

1&#xff1a;场景描述 场景&#xff1a;基于VideoCoder的音视频解码及二次处理播放。 首先导入选择器picker模块&#xff0c;使用PhotoViewPicker方法拉起图库选择视频文件&#xff0c;将视频文件传递到native侧使用Demuxer解封装器进行解封装&#xff0c;再使用OH_VideoDec…

83、 项目的发布和容器的重启策略

0、强制删除 [rootmaster01 ~]# kubectl run --imagenginx:1.22 nginx1 pod/nginx1 created [rootmaster01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx1 0/1 ContainerCreating 0 1s [rootmaster01 ~]# kubectl delete…

Mysql基础练习题 577.员工奖金 (力扣)

577.编写解决方案&#xff0c;报告每个奖金 少于 1000 的员工的姓名和奖金数额。 建表插入数据&#xff1a; Create table If Not Exists Employee (empId int, name varchar(255), supervisor int, salary int) Create table If Not Exists Bonus (empId int, bonus int) Tr…

Android 查看代码行数(命令行和Statistic插件)

目录 一、命令行 1.1 使用 1.2 结果分析 二、Statistic 2.1 下载 Statistic 插件 2.2 设置 Statistic 插件 2.3 使用 Statistic 插件 相关推荐 一、命令行 find . -name "*.java" -o -name "*.kt" | xargs wc -l find .&#xff1a;从当前目录&am…

基于Material Design风格开源的Avalonia UI控件库

前言 今天大姚给大家分享一款基于Material Design风格开源、免费&#xff08;MIT License&#xff09;的Avalonia UI控件库&#xff1a;Material.Avalonia。 当前项目还处于alpha阶段。 Avalonia介绍 Avalonia是一个强大的框架&#xff0c;使开发人员能够使用.NET创建跨平台应…

Prometheus(七):自动发现服务consule

目录 1 consule配置使用1.1 Prometheus 支持的多种服务发现机制1.2 安装1、基于 docker 的 consul 集群 - docker-compose2、单节点cosule安装-docker安装 1.3 使用1、使用接口注册服务2、配置 Prometheus 对接Consul 实现自动服务发现3、使用接口注册服务2-JSON文件4、relabel…

【微信小程序】全局数据共享 - MobX

1. 什么是全局数据共享 2. 小程序中的全局数据共享方案 3.Mobx的使用 1.npm init -y(根据实际情况选择) 在小程序项目中&#xff0c;可以通过 npm 的方式引入 MobX 。 如果你还没有在小程序中使用过 npm &#xff0c;那先在小程序目录中执行命令&#xff1a; npm init -y2. …

从“输血“到“造血“:“拨改投“政策如何推动产业升级?

在经济发展的浪潮中&#xff0c;“拨改投”政策如同一股清流&#xff0c;以创新之姿重塑了财政资金的传统使用模式。这一政策精髓在于&#xff0c;将财政资金从直接的拨款方式转变为灵活的股权投资方式&#xff0c;不仅激活了市场活力&#xff0c;更引领了产业升级的新风尚。 “…