SKI-10: Query-SID runtime reproduction#32
Merged
Conversation
SKI-10 Slice 1. Replace the CompiledSIDItem/CompiledSIDItems bundle with ItemSID/QuerySID dataclasses (no base), rename quantizer APIs (train_codebooks, build_item_sids, write_codebooks, load_codebooks), and persist the trained residual quantizer alongside the SID index. - residual_codebooks.npz + residual_codebooks_manifest.json written inside sid_index_dir with relative paths. - manifest.json gains normalize_residuals, codebooks_path, codebooks_manifest_path (additive). - SIDIndexWriteSummary exposes codebooks_path / codebooks_manifest_path. - compile-sid-index CLI table shows `Codebooks path`. - Load path validates NPZ vs sibling manifest; missing/mismatched artifacts raise FileNotFoundError / ValueError with a remediation hint pointing to `uv run sid-reco compile-sid-index`. - Tests cover codebook round-trip, item-assignment reproducibility, malformed NPZ / tampered manifest, and CLI output rows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SKI-10 Slice 2. Add build_query_sid, which places a single runtime query vector on the same residual-K-means coordinates that build_item_sids produced at compile time. - Shares _prepare_level_inputs / _assign_to_centroids with build_item_sids by wrapping the 1-D query vector into 1×D, so the per-level normalization policy recorded on the codebooks applies unchanged. - QuerySID / build_query_sid are now exported from sid_reco.sid. - Reproducibility test: for every row of a fixture matrix, the query and item paths match under both normalize_residuals=True and False. - Same reproducibility holds after a write_codebooks / load_codebooks round-trip. - Rejects 2-D, empty, and mismatched-dim query vectors with ValueError. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SKI-10 Slice 3. Wire the query-SID computation into semantic retrieval so that every recommendation response — library and CLI — carries the query's coordinates alongside the items it ranks. - semantic_search loads residual codebooks before opening FAISS and raises with a clear remediation hint when they are missing. - The taxonomy-aligned query is encoded once; FAISS still uses the L2- normalized copy while build_query_sid consumes the raw vector so the per-level normalization matches compile time. - SemanticCandidate now carries sid_path (tuple[int, ...]) preserved from id_map.jsonl; SemanticSearchResult and RecommendationResponse carry query_sid (QuerySID). - `recommend` CLI prints a `Query SID:` line after the confidence summary. - Tests assert query_sid reproducibility against fixture item embeddings, candidate sid_path preservation, and a missing-codebook FileNotFoundError path; regression assertions on recipe_ids and summaries remain intact. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- compiler.load_codebooks now loads with allow_pickle=False and checks codebooks_path in the manifest so a renamed or swapped .npz file is rejected before downstream SID assignment. - semantic_search._load_id_map rejects id_map.jsonl lines whose sid_path and sid_string disagree, closing a silent-drift hole noticed during review of the query-SID runtime pipeline. - test_cli_compile_sid_index pins Rich's COLUMNS so the "Codebooks path" cell is not truncated, and asserts the full path instead of a substring to exercise the new guarantee. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the runtime shape landed on the Python side so the demo
JSON preview and final-delivery view match the new contract:
- buildSid now returns {sid_string, sid_path} with a deterministic
0..255 token hash per level (mock stand-in, never compared to a
real Phase 1 codebook).
- buildQuerySid derives a QSID from the interest sketch using the
same hash and falls back to "any" when a facet is missing.
- Confidence result carries query_sid through to the JSON preview
alongside per-item sid_path, and the FinalDelivery card switches
to the sid_string field.
- New tests cover query_sid shape, sid_path integer range, and
the "any" fallback; existing sid-format test is tightened.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
code_update-level refresh after the compiler and semantic-search hardening plus the demo query_sid alignment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
한 줄 요약
compile-sid-index가 학습한 residual K-means quantizer를 런타임 artifact로 저장하고recommend가 이를 다시 로드해 query를 item과 같은 SID 공간에 할당·노출하도록 바꿉니다. 이유는 현재 query는 FAISS 벡터 공간에서만 매칭되고 item과 같은 SID 좌표를 가지지 못해,query_sid를 downstream 의사결정에 쓸 수 없기 때문입니다.배경 / 문제
train_codebooks가 학습한 residual quantizer는 compile 시점에 item을 SID로 할당한 뒤 버려집니다. 런타임 query는 L2-정규화만 거쳐 FAISS에 쏘고, item SID와 같은 계층 좌표를 전혀 갖지 못합니다.RecommendationResponse는 item별sid_string은 실어 보내지만 query 자체의 SID 좌표는 비어 있어, 향후 SID locality 기반의 검색 반경·그룹 confidence·rerank prior 작업을 얹을 축이 없습니다. 또한 SID 타입 레이어에CompiledSIDItems번들이TrainedResidualCodebooks와 4개 필드가 중복돼 있었습니다.residual_codebooks.npz+residual_codebooks_manifest.json)로 저장, (2)recommend가 이를 같은 정규화 규칙으로 재사용해 taxonomy-aligned query를 SID path에 할당, (3)query_sid를SemanticSearchResult→RecommendationResponse→ CLI → demo mock까지 관통시킵니다. 검색 점수·adaptive radius·rerank 정책은 건드리지 않습니다.PR 대시보드
query_sid추가,compile-sid-index산출물에 codebook artifact 추가)main변경 묶음별 리뷰 가이드
src/sid_reco/sid/compiler.py,src/sid_reco/sid/indexing.py,src/sid_reco/sid/__init__.pyCompiledSIDItems번들을ItemSID+QuerySID두 구체 타입으로 분해.train_codebooks/build_item_sids/write_codebooks/load_codebooks로 명명 정리.write_sid_index_outputs가 codebook artifact까지 함께 저장하고SIDIndexWriteSummary에 경로 2개 추가.load_codebooks는allow_pickle=False+ 사이블링 manifest 필드 전수 검증.compiler.py의TrainedResidualCodebooks/write_codebooks/load_codebooks/build_query_sid네 섹션만 대조src/sid_reco/recommendation/semantic_search.py,src/sid_reco/recommendation/types.py,src/sid_reco/recommendation/pipeline.py,src/sid_reco/recommendation/__init__.pybuild_query_sid는 raw 벡터를 쓴다(per-level 정규화 규칙을 compile과 동일 유지).SemanticCandidate에sid_path: tuple[int,...]추가(id_map의sid_path/sid_string일관성 검사),SemanticSearchResult/RecommendationResponse에query_sid추가.semantic_search.search_semantic_candidates의raw_vector/query_matrix/build_query_sid분기만 보면 충분src/sid_reco/cli.pycompile-sid-index결과 테이블에Codebooks path행 추가.recommend결과 아래Query SID:한 줄 출력.cli.py의compile_sid_index표 빌더와recommend출력 블록apps/demo/data/pipeline.js,apps/demo/src/components.jsx,apps/demo/tests/pipeline.test.cjsbuildSid가{sid_string, sid_path}반환(mock-only 0..255 해시),buildQuerySid추가(sketch 누락 시anyfallback), JSON preview에query_sid+ per-itemsid_path노출, FinalDelivery 카드가sid_string필드 사용.pipeline.js의hashToken/buildSid/buildQuerySid세 함수만 보면 계약을 전부 읽을 수 있음tests/test_sid_compiler.py,tests/test_sid_indexing.py,tests/test_semantic_search.py,tests/test_cli_compile_sid_index.py,tests/test_cli_recommend.py,tests/test_recommendation_pipeline.py,tests/test_confidence_mapping.py,tests/test_zero_shot_rerank.pyquery_sidshape/"any" fallback 테스트 추가. 기존 테스트들은query_sid필드에 맞춰 업데이트.SPEC.md,graphify-out/**code_update모드로 자동 리프레시.SPEC.md의 목표/비목표/제공하는 계약 섹션Before / After
Before
train_codebooks가 학습한 residual quantizer는 할당 직후 폐기되었고,sid_index/에는 item 좌표만 남아 있었음.recommend는 taxonomy-aligned query 텍스트를 L2-정규화 해 FAISS로 쏘는 것이 끝이었고, query-SID는 존재하지 않았음.CompiledSIDItem/CompiledSIDItems로 양분돼 있었고, 번들 필드 4개(branching_factor/depth/embedding_dim/levels)가TrainedResidualCodebooks와 중복.apps/demo는 문자열 SID 하나만 노출.After
compile-sid-index가sid_index_dir/안에residual_codebooks.npz+residual_codebooks_manifest.json을 함께 저장하고, top-levelmanifest.json에 상대경로와normalize_residuals를 실어 보냄.recommend는 FAISS 열기 전 codebook을 로드(없으면 clear error로 실패). taxonomy-aligned query를 한 번 인코딩하고 FAISS에는 정규화본을,build_query_sid에는 raw 벡터를 사용 — per-level 정규화 규칙이 compile과 동일하게 유지됨.ItemSID/QuerySID두 구체 타입으로 정리.CompiledSIDItems와compile_residual_kmeans편의 래퍼는 삭제.RecommendationResponse.query_sid),recommendCLI, demo mock 파이프라인 JSON preview에query_sid가 노출됨. 모든SemanticCandidate에는 id_map 검증을 거친sid_path가 따라옴.검증
uv run pytest148 passed (기존 flaky 2건test_graphify_auto_refresh는 CI/pre-push ignore 룰에 동일하게 제외됨)uv run ruff check .uv run mypy srcnode --test apps/demo/tests/pipeline.test.cjs22/22graphify-out/BUILD_INFO.jsonmode=code_update(source 변경만)남은 리스크 / 후속 작업
residual_codebooks.npz/residual_codebooks_manifest.json이 없으므로recommend가FileNotFoundError로 실패함. 기본 경로data/processed/foodcom/sid_index/는.gitignore에 포함돼 있고, 사용자는uv run sid-reco compile-sid-index로 재생성하면 됨 (에러 메시지에 동일 힌트 포함).apps/demo의 해시 기반sid_path는 mock-only. 실제 Phase 1 codebook과 비교하면 안 됨 (코드/테스트/SPEC 모두에서 이 계약을 명시).load_codebooks가allow_pickle=False로 읽고 사이블링 manifest의 모든 필드를 검증하므로, NPZ만 교체하거나 manifest만 바꿔도 즉시 실패함. 이는 의도된 fail-fast.semantic_search.py의 raw vs normalized 벡터 분리, (2)compiler._validate_manifest_against_npz의 필드 집합, (3)indexing.write_sid_index_outputs의 시그니처 변경.