Merge branch 'refactor/web/extract-duplicate-result-filter' into feat/web/correction-search-abstraction

This commit is contained in:
Joshua Horton 2026-04-24 09:13:55 -05:00
commit e59e474923
3 changed files with 23 additions and 8 deletions

View file

@ -631,9 +631,25 @@ export async function *getBestMatches<
if((priorResultsQueue.peek()?.totalCost ?? Number.POSITIVE_INFINITY) <= spaceQueue.peek().currentCost) {
const result = priorResultsQueue.dequeue();
// Just pass it through the filter, even if it _was_ already filtered once before.
filter(result);
return result;
// There's no guarantee that the filter closure is the same instance as
// before.
//
// As a filter function may contain caching and/or deduplication
// components, we pass pre-existing results through the filter so that
// it may reconstruct related state and thus cache/deduplicate new
// results based upon old results.
//
// See `initTokenResultFilterer()`, which maintains a map used for
// deduplication.
//
// As these _are_ pre-existing results, we know that they previously
// passed through the filter with a `true` response. However, as #14366
// isn't implemented, it IS technically possible that a lower-cost
// result was found after a higher-cost result in some cases; therefore
// there is a chance such a duplicate may exist. On that basis,
// re-filtering even for prior results is reasonably motivated at this
// time.
return filter(result) ? result : null;
}
let lowestCostSource = spaceQueue.dequeue();

View file

@ -52,7 +52,7 @@ export class LegacyQuotientSpur extends SearchQuotientSpur {
return new LegacyQuotientSpur(parentNode, inputs, inputSource) as this;
}
protected buildEdgesFromResults(priorResults: ReadonlyArray<TokenResultMapping>) {
protected buildEdgesFromResults(priorResults: ReadonlyArray<TokenResultMapping>): SearchNode[] {
// With a newly-available input, we can extend new input-dependent paths from
// our previously-reached 'extractedResults' nodes.
let outboundNodes = priorResults.map((result) => {

View file

@ -11,9 +11,8 @@ import { ContextState, determineContextSlideTransform } from './correction/conte
import { ContextTransition } from './correction/context-transition.js';
import { ExecutionTimer } from './correction/execution-timer.js';
import ModelCompositor from './model-compositor.js';
import { getBestMatches, SearchNode } from './correction/distance-modeler.js';
import { SearchQuotientNode } from './correction/search-quotient-node.js';
import { initTokenResultFilterer, TokenResultMapping } from './correction/token-result-mapping.js';
import { getBestTokenMatches } from './correction/distance-modeler.js';
import { TokenResultMapping } from './correction/token-result-mapping.js';
const searchForProperty = defaultWordbreaker.searchForProperty;
@ -535,7 +534,7 @@ export async function correctAndEnumerate(
let rawPredictions: CorrectionPredictionTuple[] = [];
let bestCorrectionCost: number;
const correctionPredictionMap: Record<string, Distribution<Suggestion>> = {};
for await(const match of getBestMatches<SearchNode, TokenResultMapping, SearchQuotientNode>(searchModules, timer, initTokenResultFilterer())) {
for await(const match of getBestTokenMatches(searchModules, timer)) {
// Corrections obtained: now to predict from them!
const tokenization = tokenizations.find(t => t.spaceId == match.spaceId);