Spring AI集成Milvus向量存储时抛出'distance'键不存在异常
问题场景
基于Spring AI 1.0.0.M1、Ollama、Docker运行的Milvus 2.3.0构建RAG应用,文档插入正常,但执行以下检索语句时抛出distance键未找到异常:
List documents = vectorStore.similaritySearch(SearchRequest.defaults().query(question.question()).withTopK(5));
异常栈信息
io.milvus.exception.ParamException: The key name is not found
at io.milvus.response.QueryResultsWrapper$RowRecord.get(QueryResultsWrapper.java:158) ~[milvus-sdk-java-2.4.2.jar!/:na]
at org.springframework.ai.vectorstore.MilvusVectorStore.getResultSimilarity(MilvusVectorStore.java:373) ~[spring-ai-milvus-store-1.0.0-M1.jar!/:na]
at org.springframework.ai.vectorstore.MilvusVectorStore.lambda$similaritySearch$1(MilvusVectorStore.java:360) ~[spring-ai-milvus-store-1.0.0-M1.jar!/:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]
at org.springframework.ai.vectorstore.MilvusVectorStore.similaritySearch(MilvusVectorStore.java:369) ~[spring-ai-milvus-store-1.0.0-M1.jar!/:na]
at com.rbc.newton.ai.rag.services.OllamaAIServiceImpl.getAnswer(OllamaAIServiceImpl.java:59) ~[!/:0.0.1-SNAPSHOT]
at com.rbc.newton.ai.rag.controller.QueryController.askQuestion(QueryController.java:20) ~[!/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.11.jar!/:6.1.11]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.26.jar!/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.11.jar!/:6.1.11]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.26.jar!/:na]
用户创建Milvus Collection的代码
ConnectConfig connectConfig = ConnectConfig.builder() .uri(CLUSTER_ENDPOINT) .build(); MilvusClientV2 client = new MilvusClientV2(connectConfig); CreateCollectionReq.CollectionSchema schema = client.createSchema(); schema.addField(AddFieldReq.builder() .fieldName("embedding") .dataType(DataType.FloatVector) .dimension(1024) .description("vector embedding") .build()); schema.addField(AddFieldReq.builder() .fieldName("id") .dataType(DataType.Int64) .isPrimaryKey(true) .autoID(true) .build()); CreateCollectionReq quickSetupReq = CreateCollectionReq.builder() .collectionName(collection_name) .collectionSchema(schema) .dimension(1024) .vectorFieldName("embedding") .metricType("COSINE") .enableDynamicField(true) .build(); client.createCollection(quickSetupReq); IndexParam indexParamForVectorField = IndexParam.builder() .fieldName("embedding") .indexName("vector_index") .indexType(IndexParam.IndexType.IVF_FLAT) .metricType(IndexParam.MetricType.COSINE) .extraParams(Map.of("nlist", 1, "nprobe", 1)) .build(); List<IndexParam> indexParams = new ArrayList<>(); indexParams.add(indexParamForVectorField); CreateIndexReq createIndexReq = CreateIndexReq.builder() .collectionName(collection_name) .indexParams(indexParams) .build(); client.createIndex(createIndexReq);
问题原因与解决方法
原因
Spring AI 1.0.0.M1的MilvusVectorStore实现默认期望检索结果包含distance字段,但Milvus 2.3.0未显式指定返回该字段时,结果中不会生成该键;同时使用的milvus-sdk-java-2.4.2与Milvus 2.3.0版本不匹配,存在协议兼容性问题。
解决步骤
- 版本对齐:将milvus-sdk-java降级到2.3.x版本,保持客户端与服务端版本一致,避免协议差异导致的字段返回异常。
- 显式配置返回字段:在Spring AI配置中指定返回
distance字段,例如在application.properties中添加:spring.ai.vectorstore.milvus.return-fields=id,embedding,distance - 自定义搜索请求:若上述配置无效,可直接使用MilvusClientV2构建搜索请求,显式指定返回
distance字段,再手动转换为Spring AI的Document对象:SearchReq searchReq = SearchReq.builder() .collectionName(collection_name) .data(List.of(questionEmbedding)) .annsField("embedding") .topK(5) .metricType(MetricType.COSINE) .outputFields(List.of("id", "distance")) .build(); SearchResults results = client.search(searchReq); // 手动转换结果为List<Document>
内容的提问来源于stack exchange,提问作者user26841525

