资讯动态

Spring AI 对接 vLLM 的 400 错误排查

发布时间:2026/9/18 11:59:39 来源:尧图企业网站定制
Spring AI 对接 vLLM 的 400 错误排查【免费下载链接】spring-aiAn Application Framework for AI Engineering项目地址: https://gitcode.com/GitHub_Trending/spr/spring-ai你拿 Spring AI 的 OpenAiChatModel 对接 vLLM 起的 DeepSeek 服务baseUrl、apiKey、model 核对过三遍curl 一发模型就出词Java 这边一调用却是 400 打回报错还一直咬死“缺必填字段”。配置没问题的前提下问题出在请求体的发送方式上。咱们接的 DeepSeek 服务多轮交互大致长上图这样每一轮的提问、答案按序流转中间夹着模型自己的推理。这交互本身很平常偏偏它配出来的 400 很“冤”。排错心路先做标准动作拿服务端日志核对过 apiKeybaseUrl 和模型名又验了一遍再用 curl 手工复现同一个请求——模型回复流畅一点问题没有。到这一步基本排除配置因素怀疑指向 Spring AI 在请求上做了什么手脚。我把 OpenAiChatModel 实际发出的请求体打出来和 curl 那份逐字段对照model、messages 全在结构一致。内容没毛病。再把服务端吐回来的响应细读一遍。状态码之外真正有用的是这么一行msg: Field required, input: None。白话翻译对方认为请求体是空的才抱怨“必填字段缺失”。明明发了 body它为什么看到 None思路一转我不再看请求“里有什么”改看请求“怎么发出去”。抓了两路流量对比连接头差异就出来了curl 的请求带着 Content-LengthSpring 默认客户端发出的请求没有 Content-Lengthbody 改用分块传输编码chunked一段一段往外推。拿 curl 复现特别有说服力给同一个请求加上分块传输头vLLM 立刻返回一模一样的 400报错措辞分毫不差。验证下来卡住的不是内容不是配置就是分块传输这件事。底层机制用寄快递打比方。正常发件会先在运单上写好总重量也就是 Content-Length 头收货仓库照总重备好货架再收货分块传输则像不写总重把货物拆成一箱箱陆续发过去收货方得靠“零长度结尾”的信号才知道发完了。vLLM 的请求解析写得比较直白看不到 Content-Length它不等 body直接把空值交给参数校验于是报“必填字段缺失”。而 Spring 默认 HTTP 客户端对 JSON body 习惯走分块形式自托管推理服务又大多只按“带总重”的形态实现解析——两边一碰就是这个看似冤枉的 400。落地修复修法不复杂把 OpenAiApi 的请求工厂从默认换成 Jetty它发请求会老老实实带 Content-Lengthbody 得以完整落到服务端。先加 Jetty 客户端依赖下面声明 Jetty 的 HTTP 客户端常规Rest请求走这个包如果你的对话走流式还要再补一个 artifactId 为 jetty-reactive-httpclient 的依赖groupId 相同。dependency groupIdorg.eclipse.jetty/groupId artifactIdjetty-client/artifactId /dependency把 OpenAiApi 的请求工厂换成 Jetty构建 OpenAiApi 时把 RestClient 的请求工厂和 WebClient 的连接器都指到 Jetty前两行保留你已有的 baseUrl 与 apiKey 即可。OpenAiApi openAiApi OpenAiApi.builder() .baseUrl(chatConfig.getBaseUrl()) .apiKey(chatConfig.getApiKey()) .restClientBuilder(RestClient.builder() .requestFactory(new JettyClientHttpRequestFactory())) .webClientBuilder(WebClient.builder() .clientConnector(new JettyClientHttpConnector())) .build();验证点改完发一次同样的对话请求只要拿到正常的 token 流且抓包里请求头由分块换成了 Content-Length就算通了。延伸一句这个坑其实点破了一条协议兼容性的实战经验框架默认 HTTP 客户端和第三方服务都自认“标准”可标准里留白的那部分分块传不传、允不允许两端各自实现了没有没人替你保证。对接自托管推理服务时先用 curl 这类最轻的客户端探一遍把“内容错了”和“发送方式不被接受”拆开定位能少走很多弯路。另外默认请求工厂不灵时换 requestFactory 这类低成本的适配手段远比重写 HTTP 层划算。【免费下载链接】spring-aiAn Application Framework for AI Engineering项目地址: https://gitcode.com/GitHub_Trending/spr/spring-ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价