Skip to content

feat(search): default to potion-code-16M-v2, invalidate stale-model caches#77

Merged
amondnet merged 9 commits into
mainfrom
amondnet/potion-code-v2
Jul 11, 2026
Merged

feat(search): default to potion-code-16M-v2, invalidate stale-model caches#77
amondnet merged 9 commits into
mainfrom
amondnet/potion-code-v2

Conversation

@amondnet

@amondnet amondnet commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Closes #73. Ports upstream semble#219 (949559b).

Changes

  • dense.rsDEFAULT_MODEL_NAME minishlab/potion-code-16Mminishlab/potion-code-16M-v2 (+ doc/comment sync).
  • index.rstry_reuse now compares manifest.model_id against the resolved model name. A cache built with a different model (e.g. the old v1 default) is treated as stale and rebuilt — its persisted vectors are incompatible with queries embedded by the new model. Mirrors the intent of upstream's _metadata_matches. New test try_reuse_rejects_stale_model.
  • search.rs — drop chunks whose fused score is exactly 0.0 before ranking, matching upstream combined_scores = {chunk: score for ... if score}. Strengthened search_alpha_one_is_semantic to assert the BM25-only chunk is dropped at alpha=1.0.
  • DocsREADME.md / README.ko.md prose + references/semble.md default-model row synced (bilingual).

Verification

  • cargo fmt --all ✅ · cargo clippy --all-targets --all-features -- -D warnings ✅ (clean)
  • cargo test --workspace ✅ — 258 lib + 20 CLI tests pass (incl. new try_reuse_rejects_stale_model)
  • CLI smoke: csp search "add numbers" <dir> returns real-embedding results with the new default model (no stub fallback → v2 resolves + loads from HF).

Notes

  • Old on-disk caches (~/.csp/index/) built with v1 auto-invalidate on the next query/index thanks to the model_id gate — no manual csp clear index needed.
  • The 0.0-score filter is a near-no-op under normal adaptive alpha (RRF never yields 0), but applies at alpha ∈ {0.0, 1.0} where one leg is fully weighted out — kept for behavioral parity.

Summary by cubic

Sets minishlab/potion-code-16M-v2 as the default embedding model, drops 0.0 fused‑score chunks, and auto‑rebuilds caches when the model, model kind, or chunk size changes. Adds streamed, cross‑platform content hashing and splits cache orchestration and the cosine backend; aligns with semble#219 and satisfies #73.

  • Bug Fixes

    • Validate vector metadata (reject overflow/zero‑dim) and preserve empty‑index dimensions during load to avoid corrupt reads.
    • Track the runtime embedding model kind (real vs stub) in cache keys to prevent unsafe reuse.
    • Normalize paths when computing content hashes to avoid cache misses on Windows.
  • Refactors

    • Stream source content hashing via compute_content_hash_from_paths to avoid loading all files when validating caches.
    • Expand test coverage for cache reuse and reranking (new unit tests across cache orchestration, dense backend, index, and search).

Written for commit 1f5a6c3. Summary will update on new commits.

…aches

Port semble#219: bump the default Model2Vec model to
`minishlab/potion-code-16M-v2` and drop chunks with a 0.0 fused score
before ranking.

- dense.rs: DEFAULT_MODEL_NAME -> potion-code-16M-v2 (+ doc/comments).
- index.rs: try_reuse now compares manifest.model_id against the
  resolved model name, so a cache built with a different model (e.g. the
  old v1 default) is treated as stale and rebuilt — its persisted
  vectors are incompatible with v2-embedded queries. New test
  try_reuse_rejects_stale_model.
- search.rs: filter combined scores == 0.0 before rerank, matching
  upstream `combined_scores = {... if score}`; strengthen
  search_alpha_one_is_semantic to assert the BM25-only chunk is dropped.
- README.md / README.ko.md / references/semble.md: model name sync.

Refs #73
@codacy-production

codacy-production Bot commented Jul 11, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 79 complexity · 6 duplication

Metric Results
Complexity 79
Duplication 6

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@amondnet amondnet self-assigned this Jul 11, 2026
@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.41577% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/csp/src/indexing/cache_orchestrator.rs 94.87% 4 Missing ⚠️
crates/csp/src/indexing/dense/backend.rs 98.12% 3 Missing ⚠️
crates/csp/src/indexing/index.rs 75.00% 2 Missing ⚠️
crates/csp/src/indexing/cache.rs 96.29% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates the default Model2Vec model to potion-code-16M-v2 across documentation, code, and tests. It implements cache invalidation upon model changes by checking the model ID in the index manifest, and filters out search results with a fused score of exactly 0.0 before ranking. The reviewer flagged that index.rs, search.rs, and dense.rs exceed the organization's 500 LOC limit, recommending that these files be split by responsibility.

Comment thread crates/csp/src/indexing/index.rs Outdated
Comment thread crates/csp/src/search.rs
Comment thread crates/csp/src/indexing/dense.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 6 files

Architecture diagram
sequenceDiagram
    participant CLI as CLI / Search Request
    participant LoadIndex as load_or_build_index()
    participant TryReuse as try_reuse()
    participant Manifest as Manifest File (cache)
    participant Model as Dense Model (potion-code-16M-v2)
    participant BM25 as BM25 Index
    participant Search as search() / fused scoring
    participant Rerank as rerank / filter zero scores

    Note over CLI,Rerank: CURRENT-STATE FLOW (after PR)

    CLI->>LoadIndex: search(query, source, options)
    LoadIndex->>TryReuse: try_reuse(cache_dir, source_hash, expected_model)

    alt Cache exists & manifest.model_id == expected_model
        TryReuse->>Manifest: read manifest.json
        Manifest-->>TryReuse: { model_id, chunk_size, content_hash }
        Note over TryReuse: Same model → vectors compatible
        TryReuse-->>LoadIndex: cached CspIndex (load from disk)
        LoadIndex-->>CLI: loaded index
    else Cache missing or model_id mismatch (e.g., old v1 cache)
        TryReuse-->>LoadIndex: None (stale/missing)
        LoadIndex->>Model: load_model(expected_model)  // NEW: v2 from HF
        Model-->>LoadIndex: static embeddings model
        LoadIndex->>LoadIndex: compute embeddings for all chunks
        LoadIndex->>BM25: build BM25 index
        LoadIndex->>LoadIndex: save new manifest with model_id = expected_model
        LoadIndex-->>CLI: new index
    end

    CLI->>Search: search(query, index, alpha)
    Search->>Search: compute semantic scores (model)
    Search->>Search: compute BM25 scores
    Search->>Search: fused score = alpha*sem + (1-alpha)*bm25
    Search->>Search: CHANGED: retain only scores != 0.0
    Note over Search: Drops chunks with exactly 0.0 (e.g., alpha=1.0, BM25-only)
    Search->>Rerank: rank with optional rerank
    Rerank-->>Search: ranked results
    Search-->>CLI: search results
Loading

Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR upgrades the default embedding model to minishlab/potion-code-16M-v2, adds model-aware cache validation to prevent stale cache reuse, and filters zero-score chunks from fused search results. The refactoring splits the large index.rs and dense.rs into focused sub-modules with co-located tests.

  • Model bump + cache invalidation: DEFAULT_MODEL_NAME updated to -v2; try_reuse in the new cache_orchestrator now gates reuse on both model_id and model_kind, so any on-disk cache built with a different model or a different runtime implementation (real vs. stub) is automatically rebuilt on the next query.
  • Zero-score filter: combined.retain(|_, &mut score| score != 0.0) drops BM25-only chunks at alpha=1.0 and semantic-only chunks at alpha=0.0, matching upstream semble#219's combined_scores = {... if score} idiom.
  • Backend hardening: SelectableBasicBackend::load now uses checked arithmetic for overflow, rejects zero-dim non-empty indexes, and preserves the persisted dimension for empty indexes; compute_content_hash_from_paths streams file I/O instead of loading all bodies up front, with path separators normalised for Windows.

Confidence Score: 5/5

Safe to merge. All changed paths are covered by new or updated tests, the cache validation logic is conservative, and the zero-score filter only activates at the exact alpha boundaries where it is intentional.

The model bump and cache-invalidation logic are tightly scoped and well-tested: try_reuse validates model_id, model_kind, and chunk_size before reuse, and the fallback is a clean rebuild with no data loss path. The zero-score retain is a mathematically exact comparison safe against floating-point accumulation errors because RRF denominators are always >= 61. Backend hardening addresses real edge cases with targeted tests. The public API surface is unchanged.

No files require special attention. All touched modules have corresponding tests and the changes are well-bounded.

Important Files Changed

Filename Overview
crates/csp/src/indexing/cache_orchestrator.rs New module: extracts load_or_build_index + try_reuse; adds model_id + model_kind + chunk_size validation before cache reuse.
crates/csp/src/search.rs Adds combined.retain to drop exactly-zero fused scores; logic is correct for exact float comparison at alpha boundary values.
crates/csp/src/indexing/dense/backend.rs SelectableBasicBackend extracted to own file; adds overflow-safe size check, zero-dim guard, and empty-index dimension preservation.
crates/csp/src/indexing/index.rs IndexManifest gains model_kind field; save() writes it; parse_manifest validates it strictly; load_or_build_index delegated to cache_orchestrator.
crates/csp/src/indexing/cache.rs Refactored to add streaming compute_content_hash_from_paths; path separator normalization for Windows cross-platform parity.
crates/csp/src/indexing/cache_orchestrator/tests.rs New test suite: covers chunk_size invalidation, model_kind mismatch, model_id staleness, and full miss-hit-invalidate cycle.
crates/csp/src/search/tests.rs Tests extracted to separate module; search_alpha_one_is_semantic strengthened to assert BM25-only chunk is dropped at alpha=1.0.
crates/csp/src/indexing/dense.rs DEFAULT_MODEL_NAME bumped to v2; Model::kind() added; backend code moved to backend.rs; comment sync applied.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[load_or_build_index] --> B[resolve_cache_dir]
    B --> C[compute_content_hash_from_paths]
    C --> D{try_reuse}
    D --> E{manifest.json exists?}
    E -- No --> R[rebuild]
    E -- Yes --> F{chunk_size matches?}
    F -- No --> R
    F -- Yes --> G{model_id matches?}
    G -- No --> R
    G -- Yes --> H[load_model to get kind]
    H --> I{model_kind matches?}
    I -- No --> R
    I -- Yes --> J{content hash matches?}
    J -- No --> R
    J -- Yes --> K[CspIndex::load_from_disk]
    K --> L[Cache reused]
    R --> M[CspIndex::from_path or from_git]
    M --> N[index.save with model_id + model_kind]
    N --> O[Fresh index]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[load_or_build_index] --> B[resolve_cache_dir]
    B --> C[compute_content_hash_from_paths]
    C --> D{try_reuse}
    D --> E{manifest.json exists?}
    E -- No --> R[rebuild]
    E -- Yes --> F{chunk_size matches?}
    F -- No --> R
    F -- Yes --> G{model_id matches?}
    G -- No --> R
    G -- Yes --> H[load_model to get kind]
    H --> I{model_kind matches?}
    I -- No --> R
    I -- Yes --> J{content hash matches?}
    J -- No --> R
    J -- Yes --> K[CspIndex::load_from_disk]
    K --> L[Cache reused]
    R --> M[CspIndex::from_path or from_git]
    M --> N[index.save with model_id + model_kind]
    N --> O[Fresh index]
Loading

Reviews (4): Last reviewed commit: "test: strengthen cache and reranking cov..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 5 untouched benchmarks


Comparing amondnet/potion-code-v2 (1f5a6c3) with main (9c27272)

Open in CodSpeed

@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the indexing and search modules of the csp crate. Key changes include updating the default Model2Vec model to minishlab/potion-code-16M-v2, extracting the cache orchestration logic into a dedicated cache_orchestrator module, splitting dense backend and search tests into separate files, and filtering out chunks with a fused score of 0.0 during search. The reviewer feedback suggests two improvements: safely handling missing git commands in tests to prevent panics in environments without git, and optimizing the vector loading loop in SelectableBasicBackend::load using chunks_exact(4) to eliminate bounds checks and improve performance.

Comment thread crates/csp/src/indexing/index/tests.rs
Comment thread crates/csp/src/indexing/dense/backend.rs
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates the default Model2Vec model to minishlab/potion-code-16M-v2 for parity with semble#219, refactors the indexing module by extracting cache orchestration and dense vector backend logic into separate files, and drops chunks with a fused score of exactly 0.0 before ranking. A medium-severity issue was identified in the dense backend where calculating the expected vector file size could result in an integer overflow, and using checked multiplication is recommended to improve robustness.

Comment thread crates/csp/src/indexing/dense/backend.rs Outdated
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the indexing and search modules of the csp crate by extracting cache orchestration into cache_orchestrator.rs, moving SelectableBasicBackend to dense/backend.rs, and organizing tests into separate files. It also updates the default Model2Vec model to minishlab/potion-code-16M-v2 and filters out chunks with a fused score of 0.0 before ranking. Feedback is provided regarding a high-severity Denial of Service (DoS) vulnerability in dense/backend.rs where a zero-dimension vector with a non-zero row count can trigger an Out Of Memory (OOM) panic during allocation.

Comment thread crates/csp/src/indexing/dense/backend.rs
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates the default Model2Vec model to minishlab/potion-code-16M-v2 (aligning with semble#219), modularizes the codebase by extracting dense backend and search tests into dedicated files, and introduces the cache_orchestrator module to handle index build-or-reuse logic. Additionally, search logic is updated to drop chunks with a fused score of exactly 0.0 before ranking. Feedback was provided regarding a potential dimension distortion issue when loading an empty index in SelectableBasicBackend::load, as well as a memory bloat risk in collect_source_files when reading all file contents into memory simultaneously.

Comment thread crates/csp/src/indexing/dense/backend.rs Outdated
Comment thread crates/csp/src/indexing/cache_orchestrator.rs Outdated
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이번 Pull Request는 csp 인덱싱의 글로벌 온디스크 캐시 오케스트레이션을 포팅하고, 기본 모델을 minishlab/potion-code-16M-v2로 업데이트하며, 대규모 리포지토리에서 메모리 점유를 줄이기 위해 파일 단위로 스트리밍하여 콘텐츠 해시를 계산하도록 개선했습니다. 또한 벡터 백엔드 및 검색 테스트 코드를 별도 파일로 분리하여 모듈화했습니다. 리뷰 피드백으로는 Windows와 Unix/Linux 환경 간의 경로 구분자(백슬래시와 슬래시) 차이로 인해 플랫폼 간 콘텐츠 해시가 일관되지 않게 생성되어 캐시가 무효화될 수 있는 문제가 지적되었으며, 경로 구분자를 슬래시로 통일할 것을 권장했습니다.

Comment thread crates/csp/src/indexing/cache_orchestrator.rs Outdated
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@codacy-production

codacy-production Bot commented Jul 11, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 89 complexity · 10 duplication

Metric Results
Complexity 89
Duplication 10

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이번 풀 리퀘스트는 기본 Model2Vec 임베딩 모델을 minishlab/potion-code-16M-v2로 업그레이드하고, 대용량 리포지토리에서 메모리 효율성을 높이기 위해 스트리밍 방식의 파일 해싱(compute_content_hash_from_paths)을 도입하며, 온디스크 인덱스 캐시 빌드 및 재사용 오케스트레이터(cache_orchestrator.rs)를 추가하는 변경사항을 담고 있습니다. 또한 검색 점수가 0.0인 청크를 필터링하는 로직이 추가되었습니다. 리뷰 피드백에서는 오프라인 상태에서 실제 모델 로드가 실패하여 스텁 모델로 폴백되었을 때, 실제 모델로 빌드된 기존 캐시를 그대로 재사용함으로써 검색 결과가 왜곡되는 문제를 지적했습니다. 이를 해결하기 위해 try_reuse 함수에서 스텁 모델과 기대 모델 간의 불일치를 검증하는 필터링 로직을 추가할 것을 제안합니다.

Comment thread crates/csp/src/indexing/cache_orchestrator.rs
@amondnet

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이번 풀 리퀘스트는 기본 임베딩 모델을 minishlab/potion-code-16M-v2로 업데이트하고, 대규모 저장소에서 메모리 효율성을 높이기 위해 파일 콘텐츠 해시를 스트리밍 방식으로 계산하는 기능을 도입했습니다. 또한 캐시 오케스트레이션 로직을 cache_orchestrator 모듈로 분리하고, SelectableBasicBackend 및 관련 테스트 코드를 구조화된 서브모듈로 정리했습니다. 검색 로직에서는 융합 점수가 0.0인 청크를 필터링하는 변경사항이 포함되었습니다. 이번 변경사항에 대해 검토를 진행하였으며, 별도의 피드백은 없습니다.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 12 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread crates/csp/src/search/tests.rs
Comment thread crates/csp/src/indexing/cache_orchestrator/tests.rs Outdated
Comment thread crates/csp/src/indexing/dense/backend.rs
@sonarqubecloud

Copy link
Copy Markdown

@amondnet amondnet merged commit 1d2ea9e into main Jul 11, 2026
14 checks passed
@amondnet amondnet deleted the amondnet/potion-code-v2 branch July 11, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parity(#219): update default embedding model to potion-code-16M-v2

1 participant