背景

在项目开发过程中,我们发现多个大模型被部署在不同的服务器上,由于各服务器的IP地址、端口以及API密钥各不相同,导致在项目中切换模型时操作繁琐。为此,我计划设计一个统一入口,通过API密钥实现路由转发功能。

设计思路

在请求大模型时,请求体中需包含模型名称信息,例如:

{
  "model": "Qwen3-32B",
  // "stream": true, // 是否启用流式输出
  "messages": [
    {
      "role": "user",
      "content": "你好,请回复 你好/no_think"
    }
  ]
}

我们的目标是根据请求体中的 model 字段实现路由转发,例如将 32B 模型请求转发至服务器A,16B 模型请求转发至服务器B。

当前项目采用 Higress 作为AI路由组件,但 Higress 无法直接读取请求体内容,仅支持读取请求头参数和路径参数。

这是出于性能考虑的设计原则:网关必须保持"路由快速、轻量"的特性,body是业务数据,网关无需关心,否则在高并发场景下读取 body 可能出现性能问题。

方案设计

核心需求

路由转发需要实现以下两个功能:

  1. 解析请求体内容,并将 model 信息写入请求头,用于后续 higress 转发
  2. 根据配置查询,将不同模型的 api-key 添加到请求头

可选方案

调研发现目前有多种实现方式,核心思想都是增加中间层处理,主要方案包括:

  1. Nginx
  2. 自定义Higress WASM插件
  3. OpenResty(基于Nginx + Lua)
  4. Java代码实现

Java实现示例

在调研阶段,我们编写了一个简单的Demo验证功能可行性:

SpringBoot 3.3.6 + JDK17

@Slf4j
@Configuration
public class WebClientConfiguration {

    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }

}
@Slf4j
@RestController
@RequestMapping("/llm/proxy")
public class LlmProxyController {

    @Autowired
    private WebClient.Builder webClientBuilder;

    @PostMapping(value = "")
    public Publisher<?> chat(@RequestBody Map<String, Object> body, ServerHttpResponse response) {
        // 从请求体中提取模型名称
        String model = (String) body.getOrDefault("model", "");
        boolean stream = Boolean.TRUE.equals(body.get("stream"));
        log.info("请求模型:{}, 流式输出:{}", model, stream);

		// todo 查询模型管理表,读取模型 api-key等配置


		// 请求higress统一入口, 根据 header 做转发
        WebClient client = webClientBuilder
            .baseUrl("http://10.198.22.xxxx:31035")
            .defaultHeader("x-llm-model", model) // 关键点:新增header:模型名称
            .defaultHeader("Authorization", "Bearer " + "xxxx")
            .build();

		// 流式、非流式统一返回
        if (stream) {
            // 设置流式响应头
            response.getHeaders().setContentType(MediaType.TEXT_EVENT_STREAM);
            
            return client.post()
                .uri("/v1/chat/completions")
                .bodyValue(body)
                .retrieve()
                .bodyToFlux(String.class);
        }

        // 普通响应模式
        return client.post()
            .uri("/v1/chat/completions")
            .bodyValue(body)
            .retrieve()
            .bodyToMono(Object.class);
    }
}

验证

调用发现无论是 流式请求 还是 非流式请求,都是能通过一个接口实现转发的:

非流式请求:
**在这里插入图片描述**

流式请求:
在这里插入图片描述
在这里插入图片描述

结论

  1. 多模型的统一入口方案是可行的。
  2. 基于java的方式还是太过简陋,这里只是验证可行性,也为大家提供一个思路。
  3. 推荐方式还是 OpenResty 或者 nginx,后续如果有时间继续补充。
  4. 自定义插件方式,由于每个ai 路由各不相同,适配起来相对麻烦,这里不做推荐。
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐