feat: add chunk BM25 and reproducible RRF retrieval
This commit is contained in:
+2
-1
@@ -1,5 +1,6 @@
|
||||
import { apiRequest } from './services/session'
|
||||
import type { VectorRetrievalResult } from './services/vectors'
|
||||
import type { ChunkKeywordResult, HybridResult } from './services/hybrid'
|
||||
|
||||
export const getHealth = () => apiRequest<{status:string}>('/api/health')
|
||||
export const askQuestion = (question:string) => apiRequest<{answer:string;status:string;sources:{title:string;source_url?:string|null}[]}>('/api/chat',{method:'POST',body:JSON.stringify({question})})
|
||||
@@ -15,6 +16,6 @@ export function reviewKnowledge(id:number,payload:{expected_version:number;verif
|
||||
export type RetrievalHit={rank:number;knowledge_id:number;knowledge_version:number;document_id:number|null;document_version:number|null;source_id:number|null;source_version:number|null;source_name:string|null;source_url:string;title:string;category:string;snippet:string;snippet_start:number;snippet_end:number;score:number;matched_terms:string[]}
|
||||
export type RetrievalResult={run_id:string;query:string;mode:'keyword';status:'ok'|'no_evidence';top_k:number;category:string|null;query_terms:string[];corpus_size:number;corpus_fingerprint:string;total_hits:number;results:RetrievalHit[];elapsed_ms:number;created_at:string;config:{tokenizer:string;scorer:string;k1:number;b:number;title_weight:number;stopwords_version:string}}
|
||||
export function retrieveKnowledge(payload:{query:string;mode?:'keyword';top_k?:number;category?:string}){return apiRequest<RetrievalResult>('/api/retrieval',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)})}
|
||||
export type RetrievalRunResult = RetrievalResult | VectorRetrievalResult
|
||||
export type RetrievalRunResult = RetrievalResult | VectorRetrievalResult | ChunkKeywordResult | HybridResult
|
||||
export function getRetrievalRun(runId:string){return apiRequest<RetrievalRunResult>(`/api/retrieval/runs/${encodeURIComponent(runId)}`)}
|
||||
export function getRetrievalRuns(page=1,pageSize=20){return apiRequest<{items:RetrievalRunResult[];total:number;page:number;page_size:number}>(`/api/retrieval/runs?page=${page}&page_size=${pageSize}`)}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { apiRequest } from './session'
|
||||
import type { RetrievalHit, RetrievalResult } from '../api'
|
||||
import type { IndexVersion } from './indexes'
|
||||
import type { EmbeddingSpace } from './vectors'
|
||||
|
||||
type ChunkHit = RetrievalHit & { chunk_id: string; chunk_ordinal: number }
|
||||
type ChunkConfig = { ranking_unit: 'chunk'; lexical: RetrievalResult['config']; chunking: IndexVersion['config']; tie_break: 'knowledge_id,chunk_ordinal,chunk_id' }
|
||||
type ChunkSnapshot = { run_id: string; query: string; status: 'ok' | 'no_evidence'; top_k: number; category: string | null; query_terms: string[]; text_index_version_id: string; text_generation: number; catalog_revision: number; corpus_fingerprint: string; corpus_size: number; total_hits: number; elapsed_ms: number; created_at: string }
|
||||
export type ChunkKeywordResult = ChunkSnapshot & { mode: 'keyword_chunks'; results: ChunkHit[]; config: ChunkConfig }
|
||||
export type RankedCandidate = { chunk_id: string; rank: number; score: number }
|
||||
export type HybridResult = ChunkSnapshot & {
|
||||
mode: 'hybrid'; vector_version_id: string; generation: number; lexical_total_hits: number; vector_total_hits: number;
|
||||
lexical_candidates: RankedCandidate[]; vector_candidates: RankedCandidate[];
|
||||
results: (ChunkHit & { lexical_rank: number | null; lexical_score: number | null; vector_rank: number | null; vector_score: number | null; lexical_contribution: number; vector_contribution: number })[];
|
||||
config: ChunkConfig & { scorer: 'rrf-v1'; rrf_k: 60; weights: [1, 1]; candidate_k: number; vector_scorer: 'pgvector-cosine-exact-v1'; space: EmbeddingSpace }
|
||||
}
|
||||
type Request = { query: string; top_k?: number; category?: string }
|
||||
export const retrieveKeywordChunks = (payload: Request & { mode?: 'keyword_chunks' }) => apiRequest<ChunkKeywordResult>('/api/retrieval/chunks', { method: 'POST', body: JSON.stringify(payload) })
|
||||
export const retrieveHybrid = (payload: Request & { mode?: 'hybrid'; candidate_k?: number }) => apiRequest<HybridResult>('/api/retrieval/hybrid', { method: 'POST', body: JSON.stringify(payload) })
|
||||
Reference in New Issue
Block a user