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开发,这段话有说的不对的,还望大佬们指正。

相关推荐
aigcapi1 天前
AI搜索排名提升:GEO优化如何成为企业增长新引擎
人工智能
彼岸花开了吗1 天前
构建AI智能体:八十、SVD知识整理与降维:从数据混沌到语义秩序的智能转换
人工智能·python·llm
MM_MS1 天前
Halcon图像锐化和图像增强、窗口的相关算子
大数据·图像处理·人工智能·opencv·算法·计算机视觉·视觉检测
韩师傅1 天前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端
AI大佬的小弟1 天前
【小白第一课】大模型基础知识(1)---大模型到底是啥?
人工智能·自然语言处理·开源·大模型基础·大模型分类·什么是大模型·国内外主流大模型
山土成旧客1 天前
【Python学习打卡-Day40】从“能跑就行”到“工程标准”:PyTorch训练与测试的规范化写法
pytorch·python·学习
lambo mercy1 天前
无监督学习
人工智能·深度学习
阿里巴巴P8资深技术专家1 天前
基于 Spring AI 和 Redis 向量库的智能对话系统实践
人工智能·redis·spring
闲人编程1 天前
消息通知系统实现:构建高可用、可扩展的企业级通知服务
java·服务器·网络·python·消息队列·异步处理·分发器
sunfove1 天前
致暗夜行路者:科研低谷期的自我心理重建
人工智能