-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(rag): normalize Milvus L2 retrieval scores #3070
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -588,6 +588,7 @@ private List<Document> searchDocumentsInMilvus( | |
| .databaseName(databaseName) | ||
| .collectionName(collectionName) | ||
| .data(Collections.singletonList(queryVector)) | ||
| .metricType(metricType) | ||
| .limit(limit) | ||
| .outputFields( | ||
| Arrays.asList( | ||
|
|
@@ -609,8 +610,9 @@ private List<Document> searchDocumentsInMilvus( | |
| if (searchResults != null && !searchResults.isEmpty()) { | ||
| for (SearchResp.SearchResult result : searchResults.get(0)) { | ||
| try { | ||
| // Get score | ||
| double score = result.getScore(); | ||
| // Milvus returns a distance for L2. Convert it to a higher-is-better score | ||
| // before applying the shared threshold. | ||
| double score = normalizeScore(result.getScore()); | ||
|
|
||
| // Apply score threshold if specified | ||
| if (scoreThreshold != null && score < scoreThreshold) { | ||
|
|
@@ -631,6 +633,23 @@ private List<Document> searchDocumentsInMilvus( | |
| return results; | ||
| } | ||
|
|
||
| /** | ||
| * Converts a raw Milvus result to the score contract used by AgentScope. | ||
| * | ||
| * <p>L2 results are distances where lower values are more similar, so map them to a | ||
| * monotonically decreasing score in the [0, 1] range. Other supported metrics already return | ||
| * scores in the expected direction and are left unchanged. | ||
| * | ||
| * @param rawScore the raw score or distance returned by Milvus | ||
| * @return a higher-is-better score | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| */ | ||
| private double normalizeScore(double rawScore) { | ||
| if (metricType == IndexParam.MetricType.L2) { | ||
| return 1.0 / (1.0 + rawScore); | ||
| } | ||
| return rawScore; | ||
| } | ||
|
|
||
| /** | ||
| * Reconstructs a Document from Milvus search result. | ||
| * | ||
|
|
@@ -923,6 +942,8 @@ public Builder connectTimeoutMs(long connectTimeoutMs) { | |
| * Sets the metric type for vector similarity search. | ||
| * | ||
| * <p>Default is COSINE. Other options include L2 (Euclidean) and IP (Inner Product). | ||
| * When opening an existing collection, this must match the collection's vector index. | ||
| * L2 distances are converted to {@code 1 / (1 + distance)} scores before thresholding. | ||
| * | ||
| * @param metricType the metric type | ||
| * @return this builder | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing
metricTypeexplicitly toSearchReqis new behaviour: previously Milvus searched with the metric recorded on the collection index, now it searches with the configured metric. When a store connects to an existing collection whose index metric differs from the builder default (COSINE), this turns a previously-working search into a provider-side error or wrong ranking. Could you validate the configured metric againstdescribeIndex/describeCollectionat connect time and fail fast with a message naming both values? The javadoc note alone will be easy to miss for people who configured the store before this change.