import type { RunResult } from '../db-adapter/statement.js'; import { featureSetVersion as currentFeatureSetVersion, SEARCH_RANKER_FEATURE_SET_VERSION } from './ranker-features.js'; import { type QuestionType } from './question-type.js'; export interface SearchRankerModel { model_id: string; feature_set_version: string; trained_at: string; training_rows_count: number; coefficients: number[]; intercept: number; question_type_weights: Record; training_window?: EffectiveTrainingWindow; } export interface RankerTrainerInput { adapter: RankerTrainerAdapter; since?: string; until?: string; minFeedbackRows?: number; minDistinctQueries?: number; featureSetVersion?: string; now?: Date; } export interface EffectiveTrainingWindow { since: string; until: string; retention_cutoff_at: string; retention_days_at_train_time: number; retention_warning: boolean; } export interface TrainOfflineRankerResult { status: 'trained' | 'insufficient_data'; model?: SearchRankerModel; effectiveWindow: EffectiveTrainingWindow; counts: { feedbackRows: number; distinctQueries: number; }; } export interface BaselineMetrics { ndcg: number; mrr: number; per_query: Record; } export interface RankerEvaluation { bm25: BaselineMetrics; vector: BaselineMetrics; rrf: BaselineMetrics; logistic: BaselineMetrics; learned: BaselineMetrics; passes: boolean; } export interface RankerTrainerAdapter { prepare(sql: string): { run(...params: unknown[]): RunResult; get(...params: unknown[]): unknown; all(...params: unknown[]): unknown[]; }; transaction?(fn: () => T): T | (() => T); } interface QualityCandidate { id: string; source_type: string; bm25_score: number; vector_score: number; case_rollup_score: number; recency_score: number; relevance: number; } interface QualityFixture { query: string; question_type: QuestionType; candidates: QualityCandidate[]; } export declare const RANKER_QUALITY_FIXTURES: readonly QualityFixture[]; export declare function trainOfflineRanker(input: RankerTrainerInput): Promise; export declare function scoreWithRankerModel(model: SearchRankerModel, row: Record, query: string, questionType: QuestionType): number; export declare function evaluateAgainstBaselines(_input: RankerTrainerInput, model: SearchRankerModel): Promise; export declare function insertRankerModelVersion(adapter: RankerTrainerAdapter, model: SearchRankerModel, evaluation: RankerEvaluation): Promise<{ model_id: string; active: boolean; }>; export declare function activateRankerModel(adapter: RankerTrainerAdapter, model_id: string): Promise<'activated' | 'quality_gate_failed' | 'feature_set_mismatch' | 'not_found'>; export declare function ndcgAtK(results: readonly T[], relevanceMap: Map, k: number): number; export declare function mrr(results: readonly T[], relevantSet: Set): number; export declare function seedQualityFixtureFeedback(adapter: RankerTrainerAdapter, createdAt?: string): void; export { SEARCH_RANKER_FEATURE_SET_VERSION, currentFeatureSetVersion as featureSetVersion }; //# sourceMappingURL=ranker-trainer.d.ts.map