Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion buildSrc/src/main/groovy/DownloadSpecsPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,46 @@ class DownloadSpecsPlugin implements Plugin<Project> {

if (content.contains(allOfBlock)) {
content = content.replace(allOfBlock, replacement)
file.text = content
println('Successfully patched SynonymItemSchema')
} else {
println('Warning: SynonymItemSchema allOf block not found, skipping patch')
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is monkey patching the actual contents of the API spec, and isn't used anywhere else. I'd avoid this and instead merge typesense/typesense-api-spec#112 first, since it's going to add it regardless.

// Patch: Add rerank_hybrid_matches to SearchParameters
// The server accepts this parameter for all search endpoints (single and multi),
// but the spec only defines it on MultiSearchCollectionParameters.
println('Patching OpenAPI spec: adding rerank_hybrid_matches to SearchParameters')
String searchParamsAnchor = '''\
conversation_id:
description: >
The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM.
type: string

MultiSearchParameters:'''

String searchParamsReplacement = '''\
conversation_id:
description: >
The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM.
type: string
rerank_hybrid_matches:
type: boolean
description: >
When true, computes both text match and vector distance scores for all matches in hybrid search.
Documents found only through keyword search will get a vector distance score, and
documents found only through vector search will get a text match score.
default: false

MultiSearchParameters:'''

if (content.contains(searchParamsAnchor)) {
content = content.replace(searchParamsAnchor, searchParamsReplacement)
println('Successfully added rerank_hybrid_matches to SearchParameters')
} else {
println('Warning: SearchParameters anchor not found, skipping rerank_hybrid_matches patch')
}

file.text = content
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.typesense.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.typesense.model.SearchParameters;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Bug: rerank_hybrid_matches was only available on MultiSearchCollectionParameters,
* forcing users to use multi_search even for single collection hybrid search.
* The Typesense server accepts this parameter for all search endpoints.
*/
class SearchParametersRerankHybridTest {

private final ObjectMapper mapper = new ObjectMapper();

@Test
void testRerankHybridMatchesDefaultsToFalseAndSerializes() {
SearchParameters params = new SearchParameters();
assertFalse(params.isRerankHybridMatches());

Map<String, Object> map = mapper.convertValue(params, Map.class);
assertEquals(false, map.get("rerank_hybrid_matches"));
}

@Test
void testRerankHybridMatchesTrueSerializesToCorrectJsonKey() {
SearchParameters params = new SearchParameters()
.q("search term")
.queryBy("title")
.rerankHybridMatches(true);

assertTrue(params.isRerankHybridMatches());

Map<String, Object> map = mapper.convertValue(params, Map.class);
assertTrue(map.containsKey("rerank_hybrid_matches"),
"Serialized map must contain 'rerank_hybrid_matches' key for Typesense server compatibility");
assertTrue((Boolean) map.get("rerank_hybrid_matches"));
}

@Test
void testRerankHybridMatchesFalseIsIncludedInSerialization() {
SearchParameters params = new SearchParameters()
.q("*")
.rerankHybridMatches(false);

Map<String, Object> map = mapper.convertValue(params, Map.class);
assertFalse((Boolean) map.get("rerank_hybrid_matches"));
}
}