Higress model-router 插件实战:基于 LLM model 参数与自动路由的智能分发指南
【免费下载链接】higress🤖 AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress
本篇技术指南以 Higress 开源仓库中model-router插件为核心,围绕其基于 LLM 协议model参数的三种路由模式(模型名直传、provider 提取、自动路由)展开,结合 插件实现源码 与 单元测试 讲解配置字段、执行原理与边界行为。读完本文,你将掌握如何利用该插件为多个模型提供方共享同一网关入口,并通过请求头实现按模型、按提供方乃至按用户消息内容的路由分发。
插件定位与运行属性
model-router是 Higress 官方维护的 Go 语言 WASM 插件,实现位于 plugins/wasm-go/extensions/model-router,版本号为2.0.2(见 VERSION)。其核心能力是从 LLM 协议请求体中解析model参数,并将其映射为请求头,供后续网关路由规则(如基于 header 的匹配)使用,同时可按需改写请求体中的model字段。
从插件声明(main.go)可以看到它的关键运行属性:
| 属性 | 值 |
|---|---|
| 插件名称 | model-router |
| 执行阶段 | 认证阶段(Authentication phase) |
| 执行优先级 | 900 |
| 请求体缓冲上限 | 100 MB(DefaultMaxBodyBytes) |
| 重建缓冲上限 | 200 MB(WithRebuildMaxMemBytes) |
插件在认证阶段执行,意味着它在身份校验、路由匹配的早期即可完成 model 参数的解析与 header 注入,后续的路由规则可以直接消费这些 header。由于需要读取并可能改写请求体,插件在处理请求头时会先检查路径后缀是否命中,命中后移除content-length头并申请 100 MB 的请求体缓冲(见 main.go)。
配置字段详解
插件的全部配置通过 JSON 结构传入,字段定义与默认值如下表(与 README_EN.md 一致,并补充源码解析细节):
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
|---|---|---|---|---|
modelKey | string | 选填 | model | 请求 body 中 model 参数的位置(JSON 路径) |
addProviderHeader | string | 选填 | - | 从 model 参数解析出的 provider 名字写入哪个请求 header |
modelToHeader | string | 选填 | - | 将完整 model 参数直接写入哪个请求 header |
enableOnPathSuffix | array of string | 选填 | 见下文 | 仅对这些路径后缀的请求生效,可配置为"*"匹配所有路径 |
keepOriginalModelName | bool | 选填 | false | 配合addProviderHeader使用,设为true时仍提取 provider 写入 header,但不改写请求体中的 model 字段 |
autoRouting | object | 选填 | - | 自动路由配置(基于用户消息内容),详见后文 |
enableOnPathSuffix的默认值在源码中硬编码(见 main.go),覆盖了 OpenAI 兼容协议的主流接口路径:
["/completions", "/embeddings", "/images/generations", "/audio/speech", "/fine_tuning/jobs", "/moderations", "/image-synthesis", "/video-synthesis", "/rerank", "/messages", "/responses"]注意:源码默认值比文档表格多出
/responses,这是 OpenAI Responses API 的路径后缀。文档中描述为"/completions","/embeddings","/images/generations","/audio/speech","/fine_tuning/jobs","/moderations","/image-synthesis","/video-synthesis","/rerank","/messages",实际生效范围以源码为准。
路径匹配时插件会先剔除 URL 中的查询参数再做后缀比较(main.go),因此/v1/chat/completions?stream=true也能正确命中/completions后缀,这一点有专门测试TestOnHttpRequestHeaders_PathWithQueryStripped锁定(main_extra_test.go)。若配置为"*",则对所有路径生效。
模式一:基于 model 参数直接路由
这是最基础的使用方式:将请求体中的 model 参数原样提取并写入指定请求头,供后续路由匹配使用。
配置
modelToHeader: x-higress-llm-model处理效果
假设原始 LLM 请求体为:
{ "model": "qwen-long", "frequency_penalty": 0, "max_tokens": 800, "stream": false, "messages": [{ "role": "user", "content": "What is the GitHub address of the Higress project's main repository?" }], "presence_penalty": 0, "temperature": 0.7, "top_p": 0.95 }经过插件处理后,会新增请求头(可用于路由匹配):
x-higress-llm-model: qwen-long请求体保持不变。源码中该逻辑位于 main.go:modelToHeader配置非空时,直接用gjson读取modelKey路径的值并写入 header。
典型应用
- 网关侧配置 header 匹配路由,将不同模型名的请求分发到不同的上游服务;
- 若网关后端是支持按 header 识别模型的服务,此模式可保证请求体与路由目标完全一致,不产生任何改写。
模式二:提取 provider 字段用于路由
当网关需要按「模型提供方」分流(例如同一个入口同时代理 DashScope、OpenAI 等多个上游)时,可以让客户端在 model 参数中通过/分隔符同时携带 provider 与模型名。
注意:这种模式要求客户端在 model 参数中通过
/分隔的方式来指定 provider,例如dashscope/qwen-long。
配置
addProviderHeader: x-higress-llm-provider处理效果
原始请求体:
{ "model": "dashscope/qwen-long", "frequency_penalty": 0, "max_tokens": 800, "stream": false, "messages": [{ "role": "user", "content": "What is the GitHub address of the Higress project's main repository?" }], "presence_penalty": 0, "temperature": 0.7, "top_p": 0.95 }插件处理后新增请求头:
x-higress-llm-provider: dashscope同时请求体被改写为(model 字段只剩模型名部分):
{ "model": "qwen-long", "frequency_penalty": 0, "max_tokens": 800, "stream": false, "messages": [{ "role": "user", "content": "What is the GitHub address of the Higress project's main repository?" }], "presence_penalty": 0, "temperature": 0.7, "top_p": 0.95 }底层实现
源码使用strings.SplitN(modelValue, "/", 2)将 model 值切分为 provider 与 model 两部分(main.go):
- 若切分得到两段,则把第一段写入
addProviderHeader指定的 header,第二段通过sjson.SetBytes回写请求体中的 model 字段; - 若 model 值不包含
/(只有一段),则只记录 debug 日志,既不设置 provider header 也不改写请求体。这一不对称行为有测试TestHandleJsonBody_ModelWithoutSlash_AddProviderConfigured和TestHandleMultipartBody_ModelWithoutSlash专门验证(main_extra_test.go)。
值得注意的是,modelToHeader与addProviderHeader可以同时配置:前者写入完整 model 值(含 provider 前缀),后者写入拆分后的 provider 值。测试TestOnHttpRequestBody_JSON验证了model: "openai/gpt-4o"时x-model: openai/gpt-4o与x-provider: openai会同时出现(main_test.go)。
模式三:保留原始模型名(keepOriginalModelName)
问题背景
当使用 AI 模型聚合平台(如百炼/DashScope)接入第三方厂商模型时,部分模型名称本身包含/(例如MiniMax/MiniMax-M2.7),但它并不是provider/model格式。此时若直接使用addProviderHeader,插件会把MiniMax-M2.7误判为模型名并改写请求体中的 model 字段,导致上游无法识别模型。
配置
addProviderHeader: x-higress-llm-provider keepOriginalModelName: true处理效果
以 model 为MiniMax/MiniMax-M2.7为例,经过插件后:
- 请求头
x-higress-llm-provider设置为MiniMax(provider 提取能力保留); - 请求体中的 model 字段保持为
MiniMax/MiniMax-M2.7(不被改写)。
源码在拆分出 provider 后判断config.keepOriginalModelName,为true时跳过sjson.SetBytes改写逻辑(main.go)。对应测试TestKeepOriginalModelName同时覆盖了 JSON 与 multipart 两种请求体格式(main_test.go)。
模式四:自动路由(基于用户消息内容)
该能力已完整实现在 main.go 中,并配套了大量单元测试;当请求中的 model 参数设置为
higress/auto时,插件会自动分析用户消息内容,根据配置的正则规则选择合适的模型进行路由。
autoRouting 配置结构
autoRouting为 object 类型,包含以下子字段:
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
|---|---|---|---|---|
enable | bool | 必填 | false | 是否启用自动路由功能 |
defaultModel | string | 选填 | - | 当没有规则匹配时使用的默认模型 |
rules | array of object | 选填 | - | 路由规则数组,按顺序匹配 |
rules中每条规则包含:
| 名称 | 数据类型 | 填写要求 | 描述 |
|---|---|---|---|
pattern | string | 必填 | 正则表达式,用于匹配用户消息内容 |
model | string | 必填 | 匹配成功时设置的模型名称,写入x-higress-llm-model请求头 |
配置示例
autoRouting: enable: true defaultModel: "qwen-turbo" rules: - pattern: "(?i)(画|绘|生成图|图片|image|draw|paint)" model: "qwen-vl-max" - pattern: "(?i)(代码|编程|code|program|function|debug)" model: "qwen-coder" - pattern: "(?i)(翻译|translate|translation)" model: "qwen-turbo" - pattern: "(?i)(数学|计算|math|calculate)" model: "qwen-math"工作原理
- 当检测到请求体中的 model 参数值为
higress/auto(源码常量AutoModelPrefix)时,触发自动路由逻辑; - 从请求体的
messages数组中提取最后一个role为user的消息内容(extractLastUserMessage,见 main.go); - 按配置的规则顺序,依次使用正则表达式匹配用户消息(
matchAutoRoutingRule); - 匹配成功时,将对应的 model 值设置到
x-higress-llm-model请求头,并同步改写请求体中的 model 字段; - 如果所有规则都未匹配,则使用
defaultModel配置的默认模型; - 如果未配置
defaultModel且无规则匹配,则不设置路由头(会记录警告日志)。
使用示例
客户端请求:
{ "model": "higress/auto", "messages": [ { "role": "system", "content": "你是一个有帮助的助手" }, { "role": "user", "content": "请帮我画一只可爱的小猫" } ] }由于用户消息中包含「画」关键词,匹配到第一条规则,插件会设置请求头:
x-higress-llm-model: qwen-vl-max测试TestAutoRoutingIntegration完整验证了这一链路,包括:关键词命中(画/代码)、未命中回退默认模型、未配置默认模型时不设置路由头、以及 model 非higress/auto时不触发自动路由(main_test.go)。
支持的消息格式
自动路由支持两种常见的 content 格式:
- 字符串格式(标准文本消息):
{ "role": "user", "content": "用户消息内容" }- 数组格式(多模态消息,如包含图片):
{ "role": "user", "content": [ {"type": "text", "text": "用户消息内容"}, {"type": "image_url", "image_url": {"url": "..."}} ] }对于数组格式,插件会提取最后一个type为text的内容进行匹配(见 main.go)。extractLastUserMessage的相关边界行为(多条 user 消息取最后一条、无 user 消息返回空、数组多段文本取最后一段)均有测试覆盖(main_test.go)。
正则表达式说明
- 规则按配置顺序依次匹配,第一个匹配成功的规则生效(有测试验证「图片」与「代码」同时命中时优先前者,见
TestMatchAutoRoutingRule的 "first matching rule wins" 用例); - 支持标准 Go 正则语法;
- 推荐使用
(?i)标志实现大小写不敏感匹配; - 使用
|可以匹配多个关键词; - 非法正则(编译失败)与空 pattern/model 的规则会在配置解析阶段被跳过并记录警告日志(main.go),相关行为由
TestParseConfigAutoRouting验证。
请求体格式支持与容错行为
插件根据content-type分发处理逻辑(main.go):
| Content-Type | 处理方式 |
|---|---|
application/json | 走handleJsonBody,解析 JSON 并可能改写 model 字段 |
multipart/form-data | 走handleMultipartBody,逐 part 解析,改写名为modelKey的表单字段 |
| 其他类型 | 直接放行(ActionContinue),不注入任何 header |
multipart 场景下,插件使用mime/multipart逐 part 读取并重建请求体,仅改写modelKey对应的字段,其余字段(如prompt、文件字段)原样保留——测试TestOnHttpRequestBody_Multipart验证了这一点(main_test.go)。
插件的容错遵循「fail-open」原则,任何异常都不阻断请求:
- 非法 JSON 请求体:记录错误日志后直接放行,不注入 header(
TestHandleJsonBody_InvalidJson_PassThrough); - multipart 的 content-type 解析失败、缺少 boundary、part 头损坏:均记录日志后放行(
TestHandleMultipartBody_BadContentType、TestHandleMultipartBody_NoBoundary、TestHandleMultipartBody_NextPartError); - 请求体缺失 model 参数:不做任何处理(
TestOnHttpRequestBody_JSON的 "no change when model not provided" 用例)。
以上容错测试均位于 main_extra_test.go。
构建与使用方式
该插件属于 Higress 的 Go 语言 WASM 插件,目录内 Makefile 提供了构建命令:
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm main.go在网关侧,通过 WasmPlugin 资源配置插件(model-router)并挂载到目标路由/域名即可生效。插件目录中的 go.mod 声明了依赖(依赖higress-group/proxy-wasm-go-sdk与higress-group/wasm-goSDK,以及tidwall/gjson、tidwall/sjson用于 JSON 读写)。发布清单 catalog.json 显示model-router归类为 managed 插件,logicalId 为model-router,消费方包括 Higress 控制台(higress-console),因此你也可以直接在 Higress 控制台的插件市场中搜索「model-router」进行可视化配置。
总结
model-router插件为多模型、多提供方的 LLM 网关场景提供了三种互补的路由手段:modelToHeader用于按模型名精确路由,addProviderHeader用于按提供方分流并自动归一化请求体,autoRouting则进一步实现「按用户消息内容智能选模」的自动路由。配合enableOnPathSuffix的路径收敛与 100 MB 的请求体缓冲上限,插件既能覆盖主流 OpenAI 兼容接口,也能安全处理大体积的多模态请求。若需继续深入了解插件的测试细节与边界行为,可直接阅读 main.go、main_test.go 与 main_extra_test.go。
【免费下载链接】higress🤖 AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考