跳转至

AiProxyController(OpenAI 兼容代理转发)

cn.myapps.ai.controller.AiProxyController —— 将客户端 OpenAI 兼容大模型请求(chat/completionscompletionsembeddingsmodels 等)反向代理转发至配置的上游网关(ai.base-url,如 http://ai-proxy.myapps.cn/v1)。透传上游响应(含状态码、响应头、响应体),并对请求体做必要规整(注入默认 model、去除 stream / stream_options、量化 temperature)。

基址特殊:类级 @RequestMapping(path = "/ai/api") 为**硬编码**(不使用 ${myapps.context-path.ai:} 占位符)。因此无论部署侧如何配置 context-path,该控制器的路径前缀恒为 /ai/api。这是为了在 lite 统一部署(context-path 为 /)下与各模块路径前缀 /ai 保持一致。

  • Tag:AI 代理
  • 基址/ai/api(硬编码)
  • 鉴权:否(obpm-ai 无鉴权过滤器,详见 index.md「鉴权说明」)
  • 响应:透传上游响应,ResponseEntity<byte[]> 统一 Resource

1. 转发 OpenAI 兼容 API

/llm-proxy/** 后的子路径(如 chat/completions)转发至上游 {ai.base-url}/<子路径>,支持七种 HTTP 方法。请求体字节透传(POST/PUT/PATCH 的 JSON 体在转发前会被规整),上游响应字节与状态码、响应头原样回传(去除 hop-by-hop 与 Access-Control-* 头,避免与本机 CorsFilter 冲突)。

  • 接口类型:REST 资源
  • 请求方式GET / POST / PUT / PATCH / DELETE / HEAD / OPTIONS(同一 Java 方法,方法级 @RequestMapping(method = {...}) 列举全部七种)
  • 请求路径/ai/api/llm-proxy/**(通配;如 /ai/api/llm-proxy/chat/completions/ai/api/llm-proxy/v1/embeddings/ai/api/llm-proxy/models
  • 鉴权:否
  • Tag:AI 代理

请求参数

参数名 位置 类型 必填 说明
子路径 path string /llm-proxy/ 之后的路径片段(如 chat/completions),转发至上游 {ai.base-url}/<子路径>
query query string 任意查询串,原样拼接到上游 URI
headers header 客户端请求头转发至上游,但跳过 hop-by-hop 头(connection/keep-alive/transfer-encoding/host 等)与 Authorization(避免误用客户端 key)
body body byte[] 请求体字节;POST/PUT/PATCH 的 application/json 体在转发前会被规整(见下文「请求体规整」)

请求体规整(仅 POST/PUT/PATCH + application/json

  • 注入默认 model:若请求体未指定 model 字段,注入 aiConfig.getModel()
  • chat/completions 路径额外处理
  • 强制覆盖 modelaiConfig.getModel()
  • 移除 streamstream_options 字段(上游如智谱不兼容 LangChain 显式的 stream:false);
  • temperature 量化为两位小数(BigDecimal.setScale(2, HALF_UP)),避免 Float 误差。

请求示例

POST /ai/api/llm-proxy/chat/completions HTTP/1.1
Content-Type: application/json

{
  "messages": [
    { "role": "user", "content": "你好" }
  ],
  "temperature": 0.7
}

转发后上游实际收到(假设 aiConfig.getModel()qwen-plus):

{
  "model": "qwen-plus",
  "messages": [
    { "role": "user", "content": "你好" }
  ],
  "temperature": 0.70
}

响应

结构Mono<ResponseEntity<byte[]>>,透传上游响应, 统一 Resource

  • 状态码:上游返回的 HTTP 状态码原样回传。
  • 响应头:上游响应头透传(跳过 transfer-encoding / connection / Access-Control-*)。
  • 响应体:上游响应字节原样回传(可能是 JSON,也可能是 SSE 流式 data: 行,由上游决定)。

成功示例(HTTP 200,JSON 形式,OpenAI 兼容):

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "model": "qwen-plus",
  "choices": [
    { "index": 0, "message": { "role": "assistant", "content": "你好!" }, "finish_reason": "stop" }
  ]
}

失败示例

  • 上游错误(如 401 / 429):原样透传上游状态码与响应体。
  • 转发异常(HTTP 500):{"error":{"message":"<异常消息>"}}Content-TypeWebClient 默认决定。
  • 预检 OPTIONS(HTTP 200,空体):直接由控制器返回,不转发上游(上游通常无 CORS 头),正常情况下由本机 CorsFilter 在过滤器链最前处理。

异步超时

该端点经 AiProxyAsyncTimeoutInterceptor 设置 Servlet 异步超时为 300000 ms(5 分钟)(见 cn.myapps.ai.config.AiProxyWebMvcConfig),避免大模型慢响应被全局默认超时中断。