feat(citations): add source ranking to tests and tooling (closes #933) - #1018
Open
arcgod-design wants to merge 1 commit into
Open
feat(citations): add source ranking to tests and tooling (closes #933)#1018arcgod-design wants to merge 1 commit into
arcgod-design wants to merge 1 commit into
Conversation
…rshanGK#933) Adds a zero-dependency source-ranking algorithm to backend/services/citation_utils.py that produces a deterministic ranking of retrieved RAG sources: Three signals: - relevance (cosine distance 0..2 -> 1..0 — perfect match = 1) - recency (365-day linear decay — today = 1 / 1year ago = 0) - authority (filename-pattern rules — README 0.55, docs/ 0.70, backend/services/ 0.55, uncategorized fallback 0.40, official/spec keyword 0.85) Configurable RankWeights dataclass with normalise() for callers who provide unbalanced weights. Defaults: relevance 0.65, recency 0.10, authority 0.25 — bias toward cosine-similarity relevance. rank_sources() returns a list of {source, score, components} dicts sorted by composite score descending; ties broken deterministically by source filename then chunk index ascending (no clock dependency). New tooling: scripts/rank_sources.py — CLI that reads a JSON source list from stdin or a file, pulls optional 'distance' and 'created_at' metadata from each entry, calls rank_sources, and outputs ranked JSON or plaintext report. Bound to the same DEFAULT_AUTHORITY_RULES as the inline function. New tests: backend/tests/test_citation_ranking.py — 41 pytest cases: - _parse_isoformat (5): ISO-Z, naive, aware UTC, missing, garbage. - _relevance_score (5): perfect 0 -> 1, worst 2 -> 0, midpoint 1 -> 0.5, NaN -> 0, non-numeric -> 0. - _recency_score (8): today=1, 365d=0, older=0, future clock-skew=1, missing/empty=0, 180d~0.5 [within 0.02]. - _authority_score (9): README.md, docs/foo.md, frontend/src/, backend/services/, unknown fallback, official keyword, empty, custom-rule override. - RankWeights (3): defaults, zero-sum normalised, proportional scale, as_dict round-trip. - rank_sources (8): empty -> empty, single source has score, higher relevance first, tie by filename then chunk, all-zero weights -> key sort, recency > authority when biased, now-kwarg determinism, custom authority override, missing relevance -> 0.5, short dist list padded. - CLI tooling/scripts (3): JSON input ranked, plain mode output, missing input file -> exit 2. Backward-compatible: build_sources' signature and behavior are unchanged (post-imDarshanGK#933 additions appended below it in the same file). Existing test_citations.py (21 cases) continues to pass unmodified. Acceptance criteria from issue imDarshanGK#933: [x] Implement the change in the tests and tooling [x] Add or update tests, docs, or validation for the touched path
|
@arcgod-design is attempting to deploy a commit to the Darshan's projects Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
Adds a source-ranking algorithm to the citation-utils module and tests/tooling — closing issue #933's "Add source ranking to tests and tooling".
Previously
build_sources()returned sources in the order ChromaDB returned them (cosine-similarity nearest-to-farthest), with no weighting or tie-breaking. This PR addsrank_sources()which produces a deterministic, explainable ranking from three human-intuitive signals: relevance, recency, and authority.Why
ChromaDB retrieval returns sources ordered by pure cosine distance. In the real world:
README.mdordocs/official-spec.mdcarries more authority thannotes.txt.The ranking function exposes a tunable
RankWeightsdataclass so a maintainer can adjust the signal mix, and the tooling CLI lets a contributor experiment offline without ChromaDB.What changed
Backend service
backend/services/citation_utils.py— the existing file is extended (backward-compatible;build_sourcesunchanged):New dataclasses:
RankWeights(relevance=0.65, recency=0.10, authority=0.25;.normalised()handles zero-sum gracefully)RankedSource(source dict, composite score, components breakdown)New free functions:
_parse_isoformat(value)— ISO-8601 / naive / aware → UTC datetime_relevance_score(distance)— cosine distance 0..2 → 1..0; NaN/non-numeric → 0_recency_score(created_at, now)— 365-day linear decay; future clock-skew → 1; missing → 0_authority_score(filename, rules, base)— filename-pattern matching with a default rulesetrank_sources(sources, *, relevance_distances, recency_timestamps, weights, authority_rules, authority_base, now)— composite score, deterministic tie-break (filename then chunk ascending)Default authority rules:
README.md0.55,docs/**/*.md0.70,backend/services/0.55,backend/routes/0.45,backend/tests/0.30,frontend/src/0.40, keywordofficial/spec/rfc0.85, unknown 0.40.Tooling
scripts/rank_sources.py— offline CLI that reads a JSON source list (stdin or file), pulls optionaldistanceandcreated_atmetadata from each entry, callsrank_sources, and outputs ranked JSON or plaintext. Accepts--relevance-weight,--recency-weight,--authority-weight. Exit 2 on bad input, 1 on empty list. Example:$ cat sources.json | python scripts/rank_sources.py --plain Ranked 3 source(s) (relevance_w=0.65 recency_w=0.10 authority_w=0.25): 1. [0.512] docs/csrf-protection.md chunk=0 (rel=0.50 rec=0.20 auth=0.70) 2. [0.463] README.md chunk=2 (rel=0.50 rec=0.00 auth=0.55) 3. [0.400] uncategorized.txt chunk=0 (rel=0.50 rec=0.00 auth=0.40)Tests
backend/tests/test_citation_ranking.py— 41 pytest cases, all pass:now-kwarg determinism, custom authority override, missing relevance→0.5, short dist list padded.test_citations.py(21 cases) still passes unmodified — backward-compatible.Verification
The
retrieve_contextflow inrag_service.pyis not changed — the ranking function is opt-in. A future PR can wirerank_sourcesinto the chat pipeline afterbuild_sources(out of scope per issue #933's "tests and tooling" title).Acceptance criteria
Closes #933.