ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

curl 正常、Spring AI 却 400:Spring AI 对接 vLLM DeepSeek 模型完整排查指南

curl 正常、Spring AI 却 400:Spring AI 对接 vLLM DeepSeek 模型完整排查指南 curl 正常、Spring AI 却 400Spring AI 对接 vLLM DeepSeek 模型完整排查指南【免费下载链接】spring-aiAn Application Framework for AI Engineering项目地址: https://gitcode.com/GitHub_Trending/spr/spring-ai你正用 Spring AI 的 OpenAiChatModel 对接 vLLM 部署的 DeepSeek 模型配置确认无误调用却稳定返回 400服务端坚称请求体缺失。本文完整记录这次排查从现象对照、根因定位到用 Jetty 客户端动手修复的验证清单帮你快速解决 Spring AI 对接 vLLM 报 400 的问题。现象对照curl 正常 vs OpenAiChatModel 400 请求体缺失这类 400 错误最让人抓狂的点是它的双重标准。你的应用里base-url指向 vLLM 服务的/v1端点API Key、模型名均已反复核对同一份参数抄到终端里用curl打过去响应一切正常可一旦 Spring AI 的 OpenAiChatModel 发起调用就稳定失败日志长这样400 - {object:error,message:[{type: missing, loc: (body,), msg: Field required, input: None}],type:BadRequestError,param:null,code:400}注意input: None这个细节——服务端表示它没收到任何请求体。而 curl 那边明明把 body 发出去了。此刻你该问自己的第一个问题是请求体真的发出去了吗还是发出去了只是服务端没读出来根因剖析分块传输编码才是 vLLM 400 的元凶chunked transfer encoding 是什么chunked transfer encoding 是一种把 HTTP 请求体切成多块、逐块发出去的方式不需要在头部预先写死总长度。生活化的类比搬家时不把所有行李一次搬完而是一趟一趟送最后再补一个到此结束的空块收尾。默认 HTTP 客户端为什么会触发它Spring 默认的 HTTP 客户端在发送 body 时特定条件下会启用这种分块模式——比如内容长度无法预先确定的场景。请求本身完全合法只是 body 的送法多了一层分块包装。vLLM 为什么解析失败问题出在 vLLM 一侧它对分块编码的请求体处理有缺陷读不出实际内容于是判定 body 为缺失直接拒绝并返回 400。至此整条链路闭环curl 发完整 body → 正常Spring AI 默认客户端发分块 body → vLLM 读空 → 400。动手修复快速替换 HTTP 客户端为 Jetty 的完整步骤过渡方案一句话概括把 HTTP 客户端换成 Jetty。Jetty 客户端与 vLLM 之间不触发这个解析问题是目前最快的通路。引入 Jetty 依赖在 pom.xml 中加入两个依赖dependency groupIdorg.eclipse.jetty/groupId artifactIdjetty-client/artifactId /dependency dependency groupIdorg.eclipse.jetty/groupId artifactIdjetty-reactive-httpclient/artifactId /dependency前者服务阻塞式调用后者服务响应式场景缺一不可。用 Jetty 客户端重建 OpenAiApi通过 builder 显式指定 Jetty 客户端重建 OpenAiApiOpenAiApi openAiApi OpenAiApi.builder() .baseUrl(chatConfig.getBaseUrl()) .apiKey(chatConfig.getApiKey()) .restClientBuilder(RestClient.builder() .requestFactory(new JettyClientHttpRequestFactory())) .webClientBuilder(WebClient.builder() .clientConnector(new JettyClientHttpConnector())) .build();再把该 OpenAiApi 交给 OpenAiChatModel。注意restClientBuilder与webClientBuilder都要配置前者管同步调用后者管流式stream响应漏掉任何一个都可能让问题换个姿势复现。修复后验证清单重发修复前失败的同一请求确认返回 200 且模型响应正常单独验证streaming 场景确认 WebClient 侧的 Jetty 客户端已生效查看 vLLM 端日志确认请求体被正确解析、无字段缺失告警回归同服务的其他接口如 embedding防止改动引入新问题补丁之外vLLM 400 问题的三条长期建议Jetty 方案属于过渡手段根本矛盾仍在两端的协议兼容性上vLLM 修复 chunked transfer encoding 兼容——这是 HTTP 协议的基本要求服务端理应正确处理Spring AI 增加对 vLLM 这类服务的针对性适配——把 HTTP 客户端做成更易配置项能显著降低排查成本开发者养成关注 HTTP 客户端配置项的习惯——对接自托管推理服务前先弄清底层到底是谁在发请求写在最后这次 400 的根源不在配置而在传输层的协议兼容性同样的 body不同的送法两种结果。如果你正卡在同一类报错上先拿 curl 做对照实验再按上文步骤把客户端切到 Jetty——大概率十分钟就能跑通。【免费下载链接】spring-aiAn Application Framework for AI Engineering项目地址: https://gitcode.com/GitHub_Trending/spr/spring-ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表