Spring AI调用Embedding模型返回HTTP 400:Invalid HTTP request received分析处理

调用Embedding模型失败

Spring AI项目使用的Embedding模型是公司平台部署的,请求模型服务的时候报错,返回了HTTP 400 - Invalid HTTP request received错误。然后换成云厂商在线Embedding模型地址,正常调通。我用Apifox直接调用公司的模型服务,能正常调通。当时真的百思不得其解。

Spring AI客户端排查

Spring AI项目中我用的Http客户端是apachehttpclient5(后面切成netty的也报同样的错误),代码调试没发现有什么异常的地方,然后把httpclient5的日志级别调成debugorg.apache.hc: debug),再次发送请求,有个请求头引起来我的注意。

shell 复制代码
org.apache.hc.client5.http.wire          : http-outgoing-0 >> "Transfer-Encoding: chunked[\r][\n]"

问了一下AI,这个请求头的意思

Transfer-Encoding: chunked 是一种HTTP分块传输编码。当发送方无法预先知道消息体总长度时(如动态生成内容),可将其分割为多个带大小标记的"块"流式发送。每个块先发十六进制长度,再发数据,以长度为0的块结束。它与Content-Length互斥,不能共存

于是我在Apifox那边也加上这个请求头,调用直接返回同样的错误,去掉就能正常返回向量信息。直接通过Apifox调用在线的Embedding模型地址,并且加上这个请求头,也能成功调通。所以问题大概率出现在公司部署的服务上。因为我找了一圈,也没找到Spring AI有配置相关请求头的地方,所以这种请求方式无法改变(有可能有设置不分块传输的,只是我没发现,我感觉概率应该很低)。

部署的模型服务排查

由于模型是其他部门部署的,所以就去要了一个项目代码,这里称为ProxyA,当时同事告诉我说,这个ProxyA主要是做的代理服务,适配了一下OpenAI的接口格式,项目调用的都是这个服务(说langchain4j是能正常调通的,排除这个服务的问题),再由此服务转发至对应的模型服务(过了两天又拿到了这个服务的代码),模型服务这里称为ModelB

调用过程就是项目--->ProxyA--->ModelB

ProxyA排查

ProxyA使用的是Flask框架,处理/embeddings地址的方法是emb()

python 复制代码
@api_blueprint.route('/embeddings', methods=['POST'])
def emb():

拿到ProxyA代码之后,项目请求我本地的ProxyA地址,再次发送请求,成功的进入到了emb()里面。也就是说,调用ProxyA是没有问题的,是ProxyA调用ModelB出了问题。

后面debug到了一段关键的代码,这个代码就是把项目的请求转发到ModelB服务,关键是这个请求头,没做什么处理,就直接转发给了ModelB服务

python 复制代码
def emb():
	# 省略......
	# 调用具体的模型服务地址,并且把接收到的请求头放进去
	resp = requests.post(ModelB_url, headers=headers, json=data, timeout=10)
	return .....

后面在转发请求代码之前处理了一下,代码如下:

python 复制代码
def emb():
	# 省略......
	# 如果存在Transfer-Encoding: chunked,就去掉,然后加上Content-Length头
	if 'Transfer-Encoding' in headers and headers['Transfer-Encoding'] == 'chunked':
        # 移除Transfer-Encoding头部
		del headers['Transfer-Encoding']
		# 添加Content-Length头部
		import json as json_module
		content_length = len(json_module.dumps(data).encode('utf-8'))
		headers['Content-Length'] = str(content_length)

	# 调用具体的模型服务地址,并且把接收到的请求头放进去
	resp = requests.post(ModelB_url, headers=headers, json=data, timeout=10)
	return .....

处理之后,再次调用,发现Spring AI项目可以正常调用公司部署的Embedding模型了

ModelB排查

后面要到ModelB服务的git权限之后,拉取代码本地试了一下,项目可以直接调通ModelB服务,不再报HTTP 400 - Invalid HTTP request received错误,只是因为格式不对,报了其他的错误。所以ModelB服务也是没有问题的。就是ProxyA服务请求转发的时候出了问题。

没拿到ModelB代码之前,还一顿怀疑是ModelB出了问题,纠结要不要去掉ProxyA里面的那段处理代码(毕竟不是专业Python开发😂)。

总结

ProxyA接收到分块传输请求之后,通过requests.post转发请求的时候,由于没有对请求头进行过滤,导致转发的请求头中存在Transfer-Encoding: chunked,所以调用ModelB的时候出现无效Http请求 的异常。

进到emb()方法中,实际项目对ProxyA的请求已经被完整接收了,也就是数据都传输过来了,但是requests.post转发的时候,json是一个确定的对象,可以明确大小的,也就是转发的时候压根不是分块请求,头部又设置成了分块传输,自然就有问题了。由于我不是python开发,这段话有说的不对的,还望大佬们指正。

相关推荐
GetcharZp28 分钟前
玩转AI绘画,你只差一个节点式“魔法”工具——ComfyUI 保姆级入门指南
人工智能·stable diffusion
集成显卡29 分钟前
使用 Google 开源 AI 工具 LangExtract 进行结构化信息抽取
python·google·openai
久笙&38 分钟前
对象存储解决方案:MinIO 的架构与代码实战
数据库·python·架构
武昌库里写JAVA44 分钟前
使用 Java 开发 Android 应用:Kotlin 与 Java 的混合编程
java·vue.js·spring boot·sql·学习
一休哥助手1 小时前
Naive RAG:简单而高效的检索增强生成架构解析与实践指南
运维·人工智能·架构
程序员鱼皮1 小时前
这套 Java 监控系统太香了!我连夜给项目加上了
java·前端·ai·程序员·开发·软件开发
不甘懦弱1 小时前
阿里云搭建flask服务器
服务器·python·flask
机器之心1 小时前
究竟会花落谁家?DeepSeek最新大模型瞄准了下一代国产AI芯片
人工智能·openai
赵英英俊1 小时前
Python day51
人工智能·pytorch·python
双向331 小时前
金融风控AI引擎:实时反欺诈系统的架构设计与实现
人工智能