Uh oh!
There was an error while loading. Please reload this page.
OpenConceptLab/ocl_issues#2388 | custom encoder model for reranking - #8
Conversation
paynejd
left a comment
There was a problem hiding this comment.
Review — OpenConceptLab/ocl_issues#2388
1. Add drop-in models to ENCODER_MODEL_OPTIONS with descriptions
Currently rerankerModels.js only has the default. Add 3 additional drop-in compatible models (no backend code changes needed — these all work with the existing CrossEncoder in sentence-transformers 3.3.1):
exportconstENCODER_MODEL_OPTIONS=[{id: 'BAAI/bge-reranker-v2-m3',description: 'Multilingual, general-purpose (0.6B)',},{id: 'cross-encoder/ms-marco-MiniLM-L-6-v2',description: 'Fast and lightweight, English-only (23M)',},{id: 'ncbi/MedCPT-Cross-Encoder',description: 'Biomedical domain, trained on PubMed (110M)',},{id: 'Alibaba-NLP/gte-reranker-modernbert-base',description: 'Balanced quality, supports longer descriptions (149M)',},]This changes the data shape from string array to object array, so RerankerConfig.jsx needs updating to use option.id and display option.description in the dropdown. Each model offers a genuinely different tradeoff:
- ms-marco-MiniLM: 27x smaller than default, ~10x faster — good for latency-critical or large batch runs
- MedCPT: only biomedical-domain cross-encoder available, trained on 18M PubMed query-article pairs — most relevant for health terminology mapping
- gte-modernbert: near-default quality at 4x smaller, 8192 token context window (vs 128 default) for longer concept descriptions
2. Log the encoder model on rerank events
At line 2226, the rerank_finished log should include which model was used:
log({action: 'rerank_finished',description: `Reranked with ${encoderModel}`},index)Same for rerank_failed at line 2231:
log({action: 'rerank_failed',description: `Rerank failed with ${encoderModel}`},index)This is visible in the row's Discuss/log panel and persists with the project — important for debugging and reproducibility when users are experimenting with different models.
3. Fix prop naming inconsistency
MapProject.jsx passes rerankerConfig={encoderModel} and setRerankerConfig={setEncoderModel} to ConfigurationForm, but the value is a plain string, not a config object. The naming is misleading. Suggest renaming to encoderModel/setEncoderModel or rerankerModel/setRerankerModel throughout.
4. Fix Spanish translation accents
In es/translations.json:
"Configuracion del reranker"→"Configuración del reranker""automaticamente"→"automáticamente"
5. Coordinate Closes keyword with oclapi2#839
Both PRs say "Closes OpenConceptLab/ocl_issues#2388". Whichever merges first will auto-close the issue prematurely. Suggest this PR (oclmap) keeps the Closes since it's the user-facing final piece, and oclapi2#839 changes to Ref #2388.
Related follow-up tickets filed:
- OpenConceptLab/ocl_issues#2463 — Upgrade
sentence-transformersfrom 3.3.1 to 5.4+ - OpenConceptLab/ocl_issues#2464 — Add Qwen3-Reranker models (blocked by #2463)
snyaggarwal
commented
Apr 13, 2026
Done 1 and 2. Rest are accepted |
paynejd
left a comment
There was a problem hiding this comment.
Follow-up review — items 3, 4, 7, 8
Code suggestions below — you can accept these directly from GitHub.
Item 6 (Qwen3-Reranker-0.6B): confirmed backend is on sentence-transformers==5.4.0 — no issue, 0.6B is fine enabled.
Item 5 (Closes keyword coordination with oclapi2#839): still outstanding — please check.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…back Addresses 6 of 10 issues from snyaggarwal's PR review (bridge / multi-algo flows in a build with PRIVATE_PACKAGES_GIT enabled). #6 deferred pending diagnostics; #1/#3 expected to resolve transitively. #9 — Every candidate duplicated. mergeIntoRowMatchState now drops existing candidates whose algorithm_id matches the incoming invocation before merging the new set (mirrors the legacy onResponse `reject(...)` on allCandidates). Concept_rows whose concept_key is no longer referenced by any surviving candidate are pruned. Without this, every re-fetch (legacy load + auto-match, or repeated $match calls) stacked fresh candidate UUIDs with identical concept_keys, surfacing as duplicates in algorithm view. #5 / #10 — Fetch More: re-fires + doesn't update. Pagination append branch in onResponse now feeds the appended page into the unified state via mergeIntoRowMatchState(..., {append: true}). The new option short-circuits the same-algo drop in #9 so earlier pages stay put while the new page stacks on top. Without this, Fetch More fired the request but the unified read path never saw the new results. #4 — Target Code column always empty (and likely #3 — Candidates table view not complete). Concept.jsx grew a legacyToRowView() wrapper at the top of the component. When `concept` is a legacy concept-shape object (id, display_name, url, search_meta) instead of a unified-model tuple, the wrapper synthesizes a minimal rowView so the rest of the render path works unchanged. Covers Target Code column, Search results, decision tables, anywhere Concept is invoked with a legacy projection (mapSelected, searchedConcepts). #7 — Mapped CIEL bridge concept indicator missing in algorithm view. Concept.jsx bridge branch now passes the real isSelectedForMap function to the bridge intermediary's algoScoreFirst row instead of hard-coding `false` and `placeholderMap`. The intermediary IS mappable per spec (it gets its own ConceptRow + bucket); when the user maps it from Unified view, algorithm view now shows the Mapped indicator. #8 — Rerank sent rows with empty display_name (-100000 sentinel score). buildRerankRowsForRow filters out ConceptRows whose ConceptDefinition has no usable display_name (typically bridge cascade targets still 'pending' before ensureLoaded fills them). scheduleRerank stays re-eligible (any ConceptRow with rerank_score===undefined keeps the row scheduled), so once ensureLoaded completes the rerank refires. #2 — Bridge target mapping not logged. _onMap previously gated the log call on `concept?.url`. Bridge cascade targets may arrive without an ocl_url until $resolveReference resolves them, so the action silently dropped from project history. Log now fires when EITHER url or id is present, with object_id surfaced as a fallback identifier. Not addressed in this commit: - #1 — Score not on top (bridge case): hypothesis is this resolves transitively once #8 lands (bridge targets get rerank scores after ensureLoaded completes instead of being stuck at undefined). - #3 — Candidates table view incomplete: hypothesis is this is the same root cause as #4 (Concept bails on legacy shape). Fixed by the legacyToRowView wrapper. - #6 — Auto Match doesn't fire calls with bridge-only algo: code review doesn't reveal a smoking gun. Needs Sunny's console / network log, or a diagnostic-logging follow-up. Two-algo (bridge + ES) works in the same env which suggests state / guard issue specific to the bridge-only path. Verified: 79/79 tests pass, eslint clean, NODE_ENV=production npm run build green. Bridge / scispacy / AI Assistant staging exercise still gates merge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Linked Issue
Ref OpenConceptLab/ocl_issues#2388