事情起因
在开发大模型应用时,需要实现RAG功能,就引入了es作为向量数据库。 pom文件引入:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-elasticsearch-store-spring-boot-starter</artifactId>
</dependency>
下载的依赖中包含:co.elastic.clients:elasticsearch-java:8.13.4,这个依赖项就是出现问题的地方。
报错信息如下:
java.lang.NoSuchMethodError: 'co.elastic.clients.elasticsearch._types.KnnSearch$Builder co.elastic.clients.elasticsearch._types.KnnSearch$Builder.k(java.lang.Integer)'
但是在本地运行时一切正常!
问题排查
进入到这个类中进行查看:
package co.elastic.clients.elasticsearch._types;
//----------------------------------------------------------------
// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST.
//----------------------------------------------------------------
//
// This code is generated from the Elasticsearch API specification
// at https://github.com/elastic/elasticsearch-specification
//
// Manual updates to this file will be lost when the code is
// re-generated.
//
// If you find a property that is missing or wrongly typed, please
// open an issue or a PR on the API specification repository.
//
//----------------------------------------------------------------
// typedef: _types.KnnSearch
/**
*
* @see <a href="../doc-files/api-spec.html#_types.KnnSearch">API
* specification</a>
*/
@JsonpDeserializable
public class KnnSearch implements JsonpSerializable {
报错信息中提示的缺失的方法,在源码中是存在的,为什么会打包后会提示方法不存在呢?
接着,我下载了这个类的源码,其中的注释引起了我的注意,这是通过Elasticsearch API specification自动生成的。
难道打包时,生成的类中不包含这个方法吗?
我没有直接去验证打包后的类中是否包含该方法,我拿着这个注释去问ChatGPT,这是它给的回复:
co.elastic.clients.elasticsearch._types代码 不是手写的,而是 根据 Elasticsearch API 规范自动生成。
根据这个提示,如果API规范变了,那么自动生成时,代码也会变,我按照ChatGPT给的提示,指定了elasticsearch-java的最新版本:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-elasticsearch-store-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.17.1</version>
</dependency>
打包部署后,就恢复了正常。使用了最新的版本后,查看本地的源码,原来报错(NoSuchMethodError)所指的方法已经不存在了。
总结
出现这个问题的原因推测:打包时,使用的最新的APi规范生成了代码,生成的代码中把老版本依赖的方法删除了,导致线上使用的老版本找不到方法的问题。
当不指定版本时,至于为什么打包时会使用最新api规范生成代码,在本地开发时却还是沿用的老版本的规范,这个问题还不清楚,知道的同学可以告知一下。
建议:在引入依赖时,指定版本。
🎯最后
推荐一下开源AI WEB开发框架:X.Ryder 🚀