天池大赛Higress插件官方demo详细部署+调试

news2024/11/17 3:48:15

天池大赛Higress插件官方demo详细部署+调试

契机

使用Higress AI网关优化AI调用成本。就是基于向量召回相似问题的缓存,降低LLM API调用成本。就是开发一个网关插件做QA缓存嘛。前文已经成功复现了hello-world插件,这次结合官方提供的AI-Cache插件自己动手改改,再写点注释放到天池大赛去跑跑分,环境搭建起来确实有很多要注意的地方,所以记录下来。

前期准备

文档中所有变量都是${your_qwen_token}这种形式,需要你自己替换

#docker仓库准备,不多赘述,以后docker login的时候需要这个页面设置的访问凭证
#这个是调试插件CI/CD的关键
https://cr.console.aliyun.com/cn-hangzhou/instance/repositories

#申请千问token
[https://help.aliyun.com/zh/dashscope/opening-service](https://help.aliyun.com/zh/dashscope/opening-service)
#保存变量${your_qwen_token}

#上传文件到千问,文件下载位置见下图
#地址:https://tianchi.aliyun.com/competition/entrance/532192/informatio
#下载下来,解压缩得到doc.md
curl --location --request POST 'https://dashscope.aliyuncs.com/compatible-mode/v1/files' \
  --header 'Authorization: ${your_qwen_token}' \
  --form 'file=@./doc.md' \
  --form 'purpose=file-extract'
#得到结果如下
{"id":"${your_file_id}","object":"file","bytes":79439,"created_at":1719468299,"filename":"doc.md","purpose":"file-extract","status":"processed"}
#保存变量${your_file_id}

在这里插入图片描述

本地搭建调试

docker运行higress

#本地新建docker-compose.yml如下
#我们只需要网关即可,不需要其他的httpbin容器

version: '3.9'
services:
  higress:
	  #这个镜像包含redis,并且包含了ai-proxy插件
    image: registry.cn-hangzhou.aliyuncs.com/ztygw/aio-redis:1.4.0-rc.1
    environment:
	    #开启日志输出
      - GATEWAY_COMPONENT_LOG_LEVEL=misc:error,wasm:debug
    ports:
      #管理页面端口
      - "8080:8080/tcp"
	    #llm端口
      - "8001:8001/tcp"
      #redis端口
      - "6379:6379/tcp"
    restart: always
    

#直接启动起来
docker compose up

higress管理页面配置

此时容器运行起来了,访问http://localhost:8001,进入higress管理页面,密码随便

创建服务来源

首先创建官方文档中的DNS类型的服务,域名是 dashscope.aliyuncs.com,端口是443

在这里插入图片描述

然后创建一个redis固定地址服务来源,服务地址写127.0.0.1:6379,名称直接写redis

在这里插入图片描述

最后你的服务来源应该如下
在这里插入图片描述

路由配置

创建一条前缀匹配/的路由,转发给上面创建的服务,并附加注解:

higress.io/backend-protocol: HTTPS

higress.io/proxy-ssl-name: dashscope.aliyuncs.com

higress.io/proxy-ssl-server-name: on

就按照下图填写就完了

在这里插入图片描述

配置AI代理插件

这里要把插件打开,并且把 y o u r q w e n t o k e n , {your_qwen_token}, yourqwentoken{your_file_id}填写上去

在这里插入图片描述

LLM访问验证

上面配置好了,此时你的llm就可以使用了

#测试访问
#注意这里是8080端口
curl 'http://localhost:8080/api/openai/v1/chat/completions' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Content-Type: application/json' \
  --data-raw '{"model":"qwen-long","frequency_penalty":0,"max_tokens":800,"stream":false,"messages":[{"role":"user","content":"higress项目主仓库的github地址是什么"}],"presence_penalty":0,"temperature":0.7,"top_p":0.95}'

#如果返回如下格式说明成功
{
    "id": "from-cache",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "Higress项目的GitHub主仓库地址为: https://github.com/higress-group/higress-group.github.io"
            },
            "finish_reason": "stop"
        }
    ],
    "model": "gpt-4o",
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 0,
        "completion_tokens": 0,
        "total_tokens": 0
    }
}

官方demo添加

加点日志

上面我们已经把项目拷贝下来了,找到官方ai-cache的demo的parseConfig方法,在这里加点日志,等下我们去观察日志插件是否生效

在这里插入图片描述

func parseConfig(json gjson.Result, c *PluginConfig, log wrapper.Log) error {
	log.Info("开始读取配置...")

	// 读取redis的基本配置
	c.RedisInfo.ServiceName = json.Get("redis.serviceName").String()
	if c.RedisInfo.ServiceName == "" {
		log.Error("Redis 服务名不能为空")
		return errors.New("redis service name must not be empty")
	}
	log.Infof("Redis 服务名: %s", c.RedisInfo.ServiceName)

	c.RedisInfo.ServicePort = int(json.Get("redis.servicePort").Int())
	if c.RedisInfo.ServicePort == 0 {
		if strings.HasSuffix(c.RedisInfo.ServiceName, ".static") {
			// use default logic port which is 80 for static service
			c.RedisInfo.ServicePort = 80
		} else {
			c.RedisInfo.ServicePort = 6379
		}
	}
	log.Infof("Redis 服务端口: %d", c.RedisInfo.ServicePort)

	c.RedisInfo.Username = json.Get("redis.username").String()
	log.Infof("Redis 用户名: %s", c.RedisInfo.Username)

	c.RedisInfo.Password = json.Get("redis.password").String()
	log.Info("Redis 密码已读取")

	c.RedisInfo.Timeout = int(json.Get("redis.timeout").Int())
	if c.RedisInfo.Timeout == 0 {
		c.RedisInfo.Timeout = 1000
	}
	log.Infof("Redis 超时时间: %d ms", c.RedisInfo.Timeout)

	c.CacheKeyFrom.RequestBody = json.Get("cacheKeyFrom.requestBody").String()
	if c.CacheKeyFrom.RequestBody == "" {
		c.CacheKeyFrom.RequestBody = "messages.@reverse.0.content"
	}
	log.Infof("Cache Key From RequestBody: %s", c.CacheKeyFrom.RequestBody)

	c.CacheValueFrom.ResponseBody = json.Get("cacheValueFrom.responseBody").String()
	if c.CacheValueFrom.ResponseBody == "" {
		c.CacheValueFrom.ResponseBody = "choices.0.message.content"
	}
	log.Infof("Cache Value From ResponseBody: %s", c.CacheValueFrom.ResponseBody)

	c.CacheStreamValueFrom.ResponseBody = json.Get("cacheStreamValueFrom.responseBody").String()
	if c.CacheStreamValueFrom.ResponseBody == "" {
		c.CacheStreamValueFrom.ResponseBody = "choices.0.delta.content"
	}
	log.Infof("Cache Stream Value From ResponseBody: %s", c.CacheStreamValueFrom.ResponseBody)

	c.ReturnResponseTemplate = json.Get("returnResponseTemplate").String()
	if c.ReturnResponseTemplate == "" {
		c.ReturnResponseTemplate = `{"id":"from-cache","choices":[{"index":0,"message":{"role":"assistant","content":"%s"},"finish_reason":"stop"}],"model":"gpt-4o","object":"chat.completion","usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}`
	}
	log.Info("Return Response Template 已读取")

	c.ReturnStreamResponseTemplate = json.Get("returnStreamResponseTemplate").String()
	if c.ReturnStreamResponseTemplate == "" {
		c.ReturnStreamResponseTemplate = `data:{"id":"from-cache","choices":[{"index":0,"delta":{"role":"assistant","content":"%s"},"finish_reason":"stop"}],"model":"gpt-4o","object":"chat.completion","usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}` + "\n\ndata:[DONE]\n\n"
	}
	log.Info("Return Stream Response Template 已读取")

	c.CacheKeyPrefix = json.Get("cacheKeyPrefix").String()
	if c.CacheKeyPrefix == "" {
		c.CacheKeyPrefix = DefaultCacheKeyPrefix
	}
	log.Infof("Cache Key Prefix: %s", c.CacheKeyPrefix)

	c.redisClient = wrapper.NewRedisClusterClient(wrapper.FQDNCluster{
		FQDN: c.RedisInfo.ServiceName,
		Port: int64(c.RedisInfo.ServicePort),
	})
	log.Info("Redis 客户端实例已创建")

	err := c.redisClient.Init(c.RedisInfo.Username, c.RedisInfo.Password, int64(c.RedisInfo.Timeout))
	if err != nil {
		log.Errorf("Redis 客户端初始化失败: %v", err)
		return err
	}
	log.Info("Redis 客户端初始化成功")

	log.Info("配置初始化成功")
	return nil
}
还有一个问题onHttpRequestHeaders函数
最后有一个*return types.HeaderStopIteration
最好先改成return types.ActionContinue

我不太懂HeaderStopIteration含义,之前卡住的时候我改成ActionContinue就好了*

打包插件+push

#进入ai-cache的目录
cd ~/higress/plugins/wasm-go/extensions/ai-cache

#用tinygo打包
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags="custommalloc nottinygc_finalizer" ./

#需要看看本地有main.wasm生成没有
#作者验证过,macos+arm打包不了

#当前目录新建一个DockerFile
vim DockerFile
#写入
FROM scratch
COPY main.wasm plugin.wasm

#登陆阿里云docker
docker login --username=${your_docker_username} registry.cn-hangzhou.aliyuncs.com
#输入密码${your_docker_psw}

#开始build,注意我这里版本是1.0.0
docker build -t registry.cn-hangzhou.aliyuncs.com/${your_docker_namespace}/${your_docker_repository}:1.0.0 -f Dockerfile .

#推送到远程docker
docker push registry.cn-hangzhou.aliyuncs.com/${your_docker_namespace}/${your_docker_repository}:1.0.0

#此时得到你的插件地址了
registry.cn-hangzhou.aliyuncs.com/${your_docker_namespace}/${your_docker_repository}:1.0.0

添加ai-cache插件

继续访问higress管理页面http://localhost:8001,新增插件

插件名称:ai-cache

镜像地址:上面你推送过去的地址,这个的ocl://前缀可以不填写,他是自己加上的

执行阶段:认证阶段

优先级:99

~现在插件没有启动,还要其他配置

在这里插入图片描述

访问日志查看

#进入higress容器内部,比如我本地CONTAINER ID = ac11f4f3588a
docker exec -it ${your_container_id} bash

#查看日志
#由于我们之前配置了环境变量GATEWAY_COMPONENT_LOG_LEVEL=misc:error,wasm:debug
tail -f /var/log/higress/gateway.log

配置+启动插件

这里要先复制,再开启,配置如下

在这里插入图片描述

cacheKeyFrom:
  requestBody: "messages.@reverse.0.content"
cacheStreamValueFrom:
  responseBody: "choices.0.delta.content"
cacheValueFrom:
  responseBody: "choices.0.message.content"
redis:
  serviceName: "redis.static"
  timeout: 2000
returnResponseTemplate: |
  {"id":"from-cache","choices":[{"index":0,"message":{"role":"assistant","content":"%s"},"finish_reason":"stop"}],"model":"gpt-4o","object":"chat.completion","usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}
returnStreamResponseTemplate: |-
  data:{"id":"from-cache","choices":[{"index":0,"delta":{"role":"assistant","content":"%s"},"finish_reason":"stop"}],"model":"gpt-4o","object":"chat.completion","usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}
  data:[DONE]

此时看看刚才我们开启的日志,出现以下字样说明没问题了

在这里插入图片描述

验证ai-cache

#测试访问
#注意这里是8080端口
curl 'http://localhost:8080/api/openai/v1/chat/completions' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Content-Type: application/json' \
  --data-raw '{"model":"qwen-long","frequency_penalty":0,"max_tokens":800,"stream":false,"messages":[{"role":"user","content":"higress项目主仓库的github地址是什么"}],"presence_penalty":0,"temperature":0.7,"top_p":0.95}'

#连续两次访问,如果间隔很短,就说明生效了

#我们之前把redis映射出来了,可以用redis客户端上去看看key,这里就不多赘述了

迭代升级

后续去higress管理页面,修改ai-cache的镜像地址就行
所以每次代码更新,需要打包代码,打包镜像,推送到docker仓库,修改插件镜像地址

写到最后

请添加图片描述

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

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

相关文章

二叉树遍历练习题

2.已知某二叉树的前序遍历序列为5 7 4 9 6 2 1,中序遍历序列为4 7 5 6 9 1 2,则其后序遍历序列为( ) A.4 2 5 7 6 9 1 B.4 2 7 5 6 9 1 C.4 7 6 1 2 9 5 D.4 7 2 9 5 6 1 答案:C 解析: 通过前序遍历找…

失眠焦虑植物神经紊乱应该怎么改善饮食?

在快节奏的现代社会中,越来越多的人受到植物神经紊乱的困扰,尤其是失眠、焦虑、胸闷气短等症状频发。这些症状不仅影响日常生活和工作效率,还可能引发一系列健康问题。今天,我们就来谈谈如何通过调整饮食来改善这些症状。 饮食调整…

Java [ 基础 ] 方法引用 ✨

✨探索Java基础✨ Java基础:方法引用 方法引用是Java 8中引入的一种新特性,它使得代码更加简洁和易读。方法引用提供了一种可以直接引用已有方法作为Lambda表达式的替代方案。本文将深入介绍方法引用的基本概念、使用方法、具体实例及其在实际开发中的…

HCIA4.26-5.10

OSPF ——开放式最短路径优先协议 无类别链路状态IGP动态路由协议 距离矢量协议 运行距离矢量协议的路由器会周期性的泛洪自己的路由表,通过路由之间的交互,每台路由器都从相邻的路由器学习到路由条目,随后加载进自己的路由表中。对于网络…

简单分享下python封装

目录: 一、简介,什么是封装 二、封装的优点与好处 三、封装的示例 四、可封装的场景 一、简介,什么是封装 通俗理解:封装,简而言之,就是把数据(变量)和操作这些数据的方法&#xff0…

全球AI新闻速递7.1

全球AI新闻速递 1.科大讯飞发布讯飞星火 V4.0。 2.成都人形机器人创新中心:基于视觉扩散架构的人形机器人任务生成式模型 R-DDPRM。 3.安徽省人形机器人产业创新中心获批,将打造国内首创、世界领先研究基地。 4.亳州牵手华为打造华佗中医药大模型。 …

系统安全及应用(命令)

目录 一、账号安全控制 1.1 系统账号清理 1.2 密码安全控制 1.3 历史记录控制 1.4 终端自动注销 二、系统引导和登陆控制 2.1 限制su命令用户 2.2 PAM安全认证 示例一:通过pam 模块来防止暴力破解ssh 2.3 sudo机制提升权限 2.3.1 sudo命令(ro…

SRS流媒体服务器安装与推拉流测试

一、首先打开SRS Github https://github.com/ossrs/srs二、在Linux系统下安装SRS 1. git clone https://github.com/ossrs/srs2、克隆完后进入trunk文件夹 cd srs/trunk3.进行环境配置 ./configure 检测当前环境是否满足 4.进行编译 make 5.编译完成后运行 ./objs/srs …

统计学期末名词解释说明

基本名词解释P值、显著性、显著水平、样本量、三大分布等 20基本名词详细解释: √P值: 相关名词:显著性、显著性差异、0.01水平显著、0.05水平显著。 P值,也称显著性值或者Sig.值,用于描述某件事情发生的概率情况&a…

器件频频更换为哪桩

曾想象,在一家大型研发型企业里有如下案例: 硬件工程师设计电路选择了器件库中的某器件,在批量试产产品时,却发现没有库存,即时申请采购,却发现货期相当长,一时难以采购,甚至根本不…

【ElementPlus源码】Scrollbar 滚动条

文章目录 thumbclickThumbHandlerstartDragmouseMoveDocumentHandlermouseUpDocumentHandlerclickTrackHandler其他 barScrollbar导出的方法noresize更新滚动条相关属性 utilsruntime.tsbuildProps 看源码时候做的笔记。若有问题,请指出! 路径相关格式请…

什么是协程?协程和线程的区别

文章目录 前置知识应用程序和内核阻塞和非阻塞同步和异步并发和并行IO 发展历史同步编程异步多线程/进程异步消息 回调函数(响应式编程) 协程协程基本概念go 示例代码协程和线程的区别 个人简介 前置知识 在了解协程前,我们先理解一些相关的…

VBA数据库解决方案第十二讲:如何判断数据库中数据表是否存在

《VBA数据库解决方案》教程(版权10090845)是我推出的第二套教程,目前已经是第二版修订了。这套教程定位于中级,是学完字典后的另一个专题讲解。数据库是数据处理的利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

平安养老险陕西分公司参加2024上半年省级单位驻富平帮扶团联席会

6月28日,平安养老险陕西分公司工会副主席武媛携驻村工作队赴富平县庄里镇永安村参加2024上半年度省级单位驻富平帮扶团联席会议。 会议由省委金融办副主任、省委金融工委委员李嘉辉及省委金融办选派挂职干部、富平县副县长席玮共同主持。 会上,席玮县长带…

全球AI新闻速递6.28

全球AI新闻速递 1.首款 Transformer 专用 AI 芯片 Sohu 登场。 2.钉钉:宣布对所有AI大模型厂商开放,首批7家接入。 3.华为联合清华大学发布《AI 终端白皮书》。 4.国家卫生健康委:推动AI技术在制定个性化营养、运动干预方案中的应用。 …

地下水电站3D虚拟仿真展示平台

借助先进的VR技术,我们将水电站的每一个角落、每一处细节都以三维全景的形式真实呈现。您可以自由穿梭于水电站的各个区域,无论是发电机组、巍峨的水坝,还是错综复杂的输水管道,都近在咫尺。感受水流的澎湃力量,聆听机…

中文TeX,各种数学符号和表格

\documentclass{article} \usepackage{amsmath,amssymb,amsfonts} \usepackage{CJKutf8} \begin{document}\begin{CJK}{UTF8}{gkai}%正文放在此行下与\end{CJK}之间就行你好, LaTeX!平方根 $\sqrt{x}$立方根 $\sqrt[3]{x}$分数的代码是 $\frac{a}{b}$求和的代码是 $\sum_{i1}^{…

自闭症儿童能不能用药

在星贝育园自闭症儿童康复学校,我们一直秉持着谨慎且保守的态度对待自闭症儿童的用药问题。我们坚定地认为,在大多数情况下,药物并非自闭症儿童康复的首选。 自闭症是一种神经发育障碍,其核心症状包括社交沟通障碍、重复刻…

API-元素尺寸与位置

学习目标: 掌握元素尺寸与位置 学习内容: 元素尺寸与位置仿京东固定导航栏案例实现bilibili点击小滑块移动效果 元素尺寸与位置: 使用场景: 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个…

快钱支付股东全部股权已被质押!

根据近期工商信息,第三方支付机构快钱支付清算信息有限公司(简称“快钱支付”)实际控股方快钱金融服务(上海)有限公司(简称“快钱金融”),作为出质股权标的企业,被出质给…