Repository navigation
Proposal: Improving Orangu's Code Search with Hybrid Retrieval #336
Replies: 3 comments 4 replies
|
currently the i think you should determine if text is persisted or postings/tokens are stored in the lexical index. A distinct, versioned lexical sidecar that is updated from modified source files is what I would suggest it will also avoid keeping the entire source text while enabling lexical search from cache. |
|
Yes, I think that’s the right direction for the PoC. I’d go with the independently versioned postings sidecar and index the full extracted symbol range. Share the file walk and hash computation with the embedding index, but let each cache track which files it has successfully processed. For quoted phrases, intersecting the postings and reading each candidate file once sounds right. I’d also give verified exact matches priority for explicit identifier or phrase queries. With RRF alone, a result that appears in both lists can outrank an exact hit that only appears in the lexical list. I’d test lexical-only behavior through both /search and semantic_search, including when the embedding server goes down after startup. One benchmark correction: our Rust extractor doesn’t emit standalone constant definitions, so MAX_CHUNK_CHARS and EMBED_BATCH_TOKEN_BUDGET can’t be expected as direct hits with the current chunking. I’d use indexed symbols for the ranking comparison and track those constants separately as coverage gaps. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Proposal: Hybrid (lexical + semantic) ranking for
semantic_searchSummary
Add a lightweight BM25 index over the existing Tree-sitter symbol chunks, and fuse its ranking with the current cosine ranking using Reciprocal Rank Fusion (RRF) — before the existing diversity and graph-expansion steps. The
semantic_searchtool keeps its current interface. As a side effect, the lexical half works without an embeddings server, so the tool can still return ranked results when embeddings are unavailable.I'd like to start with a proof of concept plus a small, committed benchmark on orangu's own repository, and only propose merging if the numbers justify it.
Problem
Today
semantic_searchranks symbols purely by embedding similarity. That works well for conceptual queries ("where do we retry failed requests?") but is weaker for queries that hinge on an exact token:EMBED_BATCH_TOKEN_BUDGET,GraphStore::lookup)"graph_store mutex poisoned")Orangu already has lexical tools, but none of them produce a ranking that can be combined with semantic results:
search_text.gitignore-awareGrepgraph_lookuprgviarun_shell_commandTwo specifics in the current pipeline (
src/embeddings/index.rs,EmbeddingIndex::search) make this more than a theoretical gap:graph_lookuporrg.Current pipeline (for reference)
src/embeddings/chunk.rs): one chunk per extracted symbol, text ="<symbol> in <file>\n<body>", body truncated to 1,600 chars. Chunk ids equal graph node ids.~/.orangu/workspace/<hash>/embeddings/chunks.json, incremental via per-file sha256. Chunk text is not persisted.Proposed design
Lexical index
camelCase,snake_case,::and paths; lowercase; keep the original full identifier as an extra token so exact matches score highest.tantivyor similar seems unjustified unless the benchmark says otherwise.chunks.json(open question below).Fusion
RRF(d) = Σ 1 / (k + rank_i(d))over the lexical and semantic lists,k = 60by default.Degradation
Interface
semantic_search { query }unchanged. Output format (format_hits) unchanged, optionally tagging each hit with which list(s) it came from.--> Updated Design — Based on Maintainer Feedback
Following the discussion and maintainer feedback, the PoC design has been refined as follows.
1. Lexical Index Architecture
2. Query Processing and Verification
3. Ranking and Fusion
4. Fallback Behavior
/searchandsemantic_search.5. Benchmark and Evaluation
The implementation will remain scoped to the lexical postings sidecar, BM25 retrieval, phrase verification, RRF integration, fallback behavior, and benchmarks. Changes to the existing symbol extraction strategy remain outside the initial PoC scope.
All reactions