Background
query.similarity-threshold is inconsistent across profiles:
src/main/resources/application.yml → 0.7
src/main/resources/application-docker.yml → 0.50
RetrievalEngine.retrieveRelevantChunks filters results with score >= threshold using cosine similarity from the local all-MiniLM-L6-v2 embedding model (384 dims). MiniLM cosine scores for topically similar but non-verbatim chunks typically fall in the 0.2–0.6 range, so 0.7 frequently discards valid matches and returns zero chunks.
Impact
- With the default (non-Docker) profile, users get "no relevant documents found" for questions that do have answers in the corpus.
- Behavior differs between Docker and local runs, making the system unpredictable across environments.
- Empty retrieval triggers the out-of-scope guardrail, producing the fixed refusal reply even for valid questions.
How to reproduce
- Run with the default profile (
mvn spring-boot:run), threshold 0.7.
- Ingest a Java 25 doc, e.g.
POST /api/ingest?documentPath=docs/specs/<file>.html.
- Ask a paraphrase-style question via
POST /api/chat/query that matches a doc section semantically but not verbatim.
- Observe
RetrievalEngine logs "Found 0 documents above threshold" and the answer is the out-of-scope refusal.
Where the fix should land
Pick a single threshold tuned against the actual corpus with the MiniLM model and apply it to both profiles (or centralize it with a documented default). First measure the score distribution over the corpus for known-good queries (scores are already logged per chunk), then choose the value. Add a YAML comment explaining the rationale.
Files touched
src/main/resources/application.yml
src/main/resources/application-docker.yml
src/main/java/br/com/arquivolivre/myjavagenie/config/QueryConfig.java (only if a constraint/validation is added)
- Retrieval tests under
src/test/java/...
Acceptance criteria
Background
query.similarity-thresholdis inconsistent across profiles:src/main/resources/application.yml→0.7src/main/resources/application-docker.yml→0.50RetrievalEngine.retrieveRelevantChunksfilters results withscore >= thresholdusing cosine similarity from the localall-MiniLM-L6-v2embedding model (384 dims). MiniLM cosine scores for topically similar but non-verbatim chunks typically fall in the 0.2–0.6 range, so0.7frequently discards valid matches and returns zero chunks.Impact
How to reproduce
mvn spring-boot:run), threshold0.7.POST /api/ingest?documentPath=docs/specs/<file>.html.POST /api/chat/querythat matches a doc section semantically but not verbatim.RetrievalEnginelogs "Found 0 documents above threshold" and the answer is the out-of-scope refusal.Where the fix should land
Pick a single threshold tuned against the actual corpus with the MiniLM model and apply it to both profiles (or centralize it with a documented default). First measure the score distribution over the corpus for known-good queries (scores are already logged per chunk), then choose the value. Add a YAML comment explaining the rationale.
Files touched
src/main/resources/application.ymlsrc/main/resources/application-docker.ymlsrc/main/java/br/com/arquivolivre/myjavagenie/config/QueryConfig.java(only if a constraint/validation is added)src/test/java/...Acceptance criteria
query.similarity-thresholdwith a documented rationale.mvn spotless:checkpasses.