Skip to content

feat(qm_query): add VECTOR_DISTANCE_THRESHOLD per Ch 14 Gulli - #86

Open
AdairBear wants to merge 5 commits into
LLMQuant:masterfrom
AdairBear:lifts/qm-query-distance-threshold
Open

feat(qm_query): add VECTOR_DISTANCE_THRESHOLD per Ch 14 Gulli#86
AdairBear wants to merge 5 commits into
LLMQuant:masterfrom
AdairBear:lifts/qm-query-distance-threshold

Conversation

@AdairBear

Copy link
Copy Markdown

Summary

  • Adds distance_threshold: float = 0.7 parameter to qm_query MCP tool and underlying query() in qm_mcp/query.py
  • After vector search, candidates with cosine distance > threshold are filtered before synthesis — no noise chunks when the corpus lacks a topic
  • All candidates below threshold → empty sources list + structured INFO log, not k noise chunks fed to the LLM
  • Default 0.7 is backward-compatible; existing callers (CLI, Hermes, Conductor) get the filter for free

Pattern

VECTOR_DISTANCE_THRESHOLD (Ch 14, Gulli — Agentic Design Patterns). Threshold semantics: cosine_distance = 1 - cosine_similarity; keep candidate if similarity >= (1 - threshold).

Test plan

  • pytest qm_mcp/test_distance_threshold.py -v — 8 tests, all green
  • ruff check + ruff format --check — clean

🤖 Generated with Claude Code

AdairBear and others added 5 commits June 12, 2026 10:52
QuantMind v0.2 ships ingestion + LLM extraction only; its persistence,
embedding, semantic-query, and Data-MCP layers are unbuilt future PRs. This
adds that missing Stage-2 layer as a self-contained package that reuses
QuantMind's own venv and fetch+format layer:

- store.py   filesystem CorpusStore (JSON + .npy vectors, stable-hash dedup)
- embed.py   OpenAI embeddings + grounded answer synthesis + summarizer
- ingest.py  fetch_arxiv/url/local -> markdown -> summarize -> embed -> store
             (skips the brittle paper_flow Paper-tree: gpt-4o-mini emits
             non-UUID node ids that the Paper schema rejects)
- query.py   embed question -> cosine top-k -> grounded, cited answer
- server.py  FastMCP stdio server: qm_ingest_arxiv/url/pdf/text, qm_query,
             qm_list_corpus, qm_delete_item
- cli.py     seeding + shell use; seed_corpus.txt; _smoke_mcp.py handshake test

Secrets load from ~/.hermes/.env; uses VOICE_TOOLS_OPENAI_KEY (real OpenAI)
since Hermes OPENAI_API_KEY is an OpenRouter key with no embeddings endpoint.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds `grpo_suitability: high|medium|low` to every corpus entry at ingest
time, implementing the weak-vs-strong discrimination-gap framework from
Kulikov et al. (FAIR at Meta, arXiv:2606.25996).

V1 is a pure deterministic heuristic (no live model calls):
- long + arxiv source + code present → high
- short + news/unknown source + no code → low
- everything else → medium

Changes:
- qm_mcp/grpo_suitability.py: GrpoSuitabilityScorer with score_entry(),
  length_band, domain_band, code_present helpers; V2 solver-gap hooks
  documented as TODOs
- qm_mcp/ingest.py: score computed in _persist() and persisted to both
  items/<id>.json and ingestion_log.jsonl; backward-compatible (existing
  entries not touched)
- qm_mcp/test_grpo_suitability.py: 22 pytest cases covering heuristic
  correctness, domain-band edge cases, backward compat, idempotency
- docs/grpo_suitability.md: framework reference, V1 rule table, V2 plan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keeps the coverage floor enforced by CI (scripts/verify.sh) while
allowing sub-package test suites (e.g. qm_mcp/) to run standalone
without a false failure when quantmind code is not exercised.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds `distance_threshold: float = 0.7` to `qm_query` (MCP tool) and
the underlying `query()` function. After vector search, candidates with
cosine distance > threshold are filtered out before synthesis and
source assembly. When all candidates fail the filter, the function
returns an empty sources list and logs a structured INFO message rather
than injecting noise chunks into the LLM context.

Threshold semantics: cosine_distance = 1 - cosine_similarity; keep
if similarity >= (1 - threshold). Default 0.7 preserves backward
compatibility for existing callers (CLI, Hermes, Conductor).

Tests: qm_mcp/test_distance_threshold.py — 8 cases covering high-quality
pass, poor-match filter, all-filtered empty return + log, and threshold
override.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@keli-wen keli-wen added type: feature Adds a new capability or observable behavior area: mind Memory, tools, MCP integration, and the cognitive layer labels Jul 14, 2026
@github-actions

Copy link
Copy Markdown

This pull request has been inactive for 14 days and is now marked stale. It will be closed in 7 days if there is no further activity. Comment or remove the stale label to keep it open.

@github-actions github-actions Bot added the stale label Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: mind Memory, tools, MCP integration, and the cognitive layer stale type: feature Adds a new capability or observable behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants