Assessor_2.0/server/regulatory/regulatory-rag-runtime.ts

58 lines
3.0 KiB
TypeScript

import { createEmbeddingClientFromEnvironment, type EmbeddingEnvironment } from './embedding-client';
import { createQdrantRegulatoryIndexFromEnvironment, type QdrantEnvironment } from './qdrant-regulatory-index';
import { RegulatoryFindingRetrievalService } from './regulatory-finding-retrieval';
import {
DenseRegulatoryCandidateRetriever,
RegulatoryIngestionService,
RegulatoryRetrievalPipeline
} from './regulatory-rag-service';
export interface RegulatoryRagEnvironment extends EmbeddingEnvironment, QdrantEnvironment {
ASSESSOR_RAG_CHUNK_CHARACTERS?: string;
ASSESSOR_RAG_EMBEDDING_BATCH_SIZE?: string;
}
export function createRegulatoryRagRuntime(
environment: RegulatoryRagEnvironment = {
ASSESSOR_QDRANT_URL: process.env.ASSESSOR_QDRANT_URL,
ASSESSOR_QDRANT_API_KEY: process.env.ASSESSOR_QDRANT_API_KEY,
ASSESSOR_QDRANT_TIMEOUT_MS: process.env.ASSESSOR_QDRANT_TIMEOUT_MS,
ASSESSOR_RAG_EMBEDDING_BASE_URL: process.env.ASSESSOR_RAG_EMBEDDING_BASE_URL,
ASSESSOR_RAG_EMBEDDING_MODEL: process.env.ASSESSOR_RAG_EMBEDDING_MODEL,
ASSESSOR_RAG_EMBEDDING_API_KEY: process.env.ASSESSOR_RAG_EMBEDDING_API_KEY,
ASSESSOR_RAG_EMBEDDING_DIMENSIONS: process.env.ASSESSOR_RAG_EMBEDDING_DIMENSIONS,
ASSESSOR_RAG_EMBEDDING_REQUEST_DIMENSIONS: process.env.ASSESSOR_RAG_EMBEDDING_REQUEST_DIMENSIONS,
ASSESSOR_RAG_EMBEDDING_TIMEOUT_MS: process.env.ASSESSOR_RAG_EMBEDDING_TIMEOUT_MS,
ASSESSOR_RAG_CHUNK_CHARACTERS: process.env.ASSESSOR_RAG_CHUNK_CHARACTERS,
ASSESSOR_RAG_EMBEDDING_BATCH_SIZE: process.env.ASSESSOR_RAG_EMBEDDING_BATCH_SIZE
}
): {
ingestion: RegulatoryIngestionService;
retrieval: RegulatoryRetrievalPipeline;
findingRetrieval: RegulatoryFindingRetrievalService;
index: ReturnType<typeof createQdrantRegulatoryIndexFromEnvironment>;
embeddingModel: string;
} {
const embeddings = createEmbeddingClientFromEnvironment(environment);
const index = createQdrantRegulatoryIndexFromEnvironment(embeddings.dimensions, embeddings.model, environment);
const dense = new DenseRegulatoryCandidateRetriever(embeddings, index);
const retrieval = new RegulatoryRetrievalPipeline(dense);
return {
ingestion: new RegulatoryIngestionService(embeddings, index, {
maximumChunkCharacters: boundedInteger(environment.ASSESSOR_RAG_CHUNK_CHARACTERS, 1_600, 200, 20_000, 'ASSESSOR_RAG_CHUNK_CHARACTERS'),
embeddingBatchSize: boundedInteger(environment.ASSESSOR_RAG_EMBEDDING_BATCH_SIZE, 32, 1, 128, 'ASSESSOR_RAG_EMBEDDING_BATCH_SIZE')
}),
retrieval,
findingRetrieval: new RegulatoryFindingRetrievalService(retrieval),
index,
embeddingModel: embeddings.model
};
}
function boundedInteger(value: string | undefined, fallback: number, minimum: number, maximum: number, name: string): number {
if (!value?.trim()) return fallback;
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) throw new Error(`${name} must be an integer between ${minimum} and ${maximum}.`);
return parsed;
}