UNPKG

@prism-lang/confidence

Version:

Confidence extraction library for Prism - standardized patterns for extracting confidence values from LLMs and other sources

270 lines (233 loc) 6.64 kB
import { ConfidenceBudget, ConfidenceContract, DifferentialConfidence } from './types'; /** * Confidence budget for high-stakes decisions */ export class ConfidenceBudgetManager { private budget: ConfidenceBudget; constructor(minTotal: number) { this.budget = { minTotal, items: [] }; } /** * Add a confident value to the budget */ add(value: any, confidence: number): void { this.budget.items.push({ value, confidence }); } /** * Check if budget is met */ met(): boolean { const total = this.getTotal(); return total >= this.budget.minTotal; } /** * Get current total confidence */ getTotal(): number { return this.budget.items.reduce((sum, item) => sum + item.confidence, 0); } /** * Get remaining confidence needed */ getRemaining(): number { return Math.max(0, this.budget.minTotal - this.getTotal()); } /** * Get budget status */ getStatus(): { met: boolean; total: number; required: number; remaining: number; items: number; } { const total = this.getTotal(); return { met: this.met(), total, required: this.budget.minTotal, remaining: this.getRemaining(), items: this.budget.items.length }; } /** * Clear the budget */ clear(): void { this.budget.items = []; } } /** * Confidence contract for defining requirements */ export class ConfidenceContractManager { private contract: ConfidenceContract; constructor(requirements: { [check: string]: number }) { this.contract = { requirements }; } /** * Verify results meet contract requirements */ verify(results: { [check: string]: { value: any; confidence: number } }): { passed: boolean; failures: Array<{ check: string; required: number; actual: number }>; } { const failures: Array<{ check: string; required: number; actual: number }> = []; for (const [check, required] of Object.entries(this.contract.requirements)) { const result = results[check]; if (!result) { failures.push({ check, required, actual: 0 }); } else if (result.confidence < required) { failures.push({ check, required, actual: result.confidence }); } } return { passed: failures.length === 0, failures }; } /** * Get contract summary */ getSummary(): string { const reqs = Object.entries(this.contract.requirements) .map(([check, conf]) => `${check}: ${(conf * 100).toFixed(0)}%`) .join(', '); return `Confidence contract requiring: ${reqs}`; } /** * Check if a single result meets its requirement */ checkRequirement(check: string, confidence: number): boolean { const required = this.contract.requirements[check]; return required ? confidence >= required : true; } } /** * Differential confidence for multi-aspect analysis */ export class DifferentialConfidenceManager { private aspects: DifferentialConfidence = {}; /** * Set confidence for a specific aspect */ setAspect(aspect: string, confidence: number): void { this.aspects[aspect] = Math.max(0, Math.min(1, confidence)); } /** * Get confidence for a specific aspect */ getAspect(aspect: string): number { return this.aspects[aspect] || 0; } /** * Get all aspects */ getAllAspects(): DifferentialConfidence { return { ...this.aspects }; } /** * Get aspect summary */ getSummary(): string { const parts = Object.entries(this.aspects) .sort((a, b) => b[1] - a[1]) .map(([aspect, conf]) => `${aspect}: ${(conf * 100).toFixed(0)}%`) .join(', '); return `Differential confidence: ${parts}`; } /** * Get highest confidence aspect */ getHighest(): { aspect: string; confidence: number } | null { const entries = Object.entries(this.aspects); if (entries.length === 0) return null; return entries.reduce((highest, [aspect, conf]) => conf > highest.confidence ? { aspect, confidence: conf } : highest, { aspect: entries[0][0], confidence: entries[0][1] } ); } /** * Get lowest confidence aspect */ getLowest(): { aspect: string; confidence: number } | null { const entries = Object.entries(this.aspects); if (entries.length === 0) return null; return entries.reduce((lowest, [aspect, conf]) => conf < lowest.confidence ? { aspect, confidence: conf } : lowest, { aspect: entries[0][0], confidence: entries[0][1] } ); } /** * Get average confidence across all aspects */ getAverage(): number { const values = Object.values(this.aspects); if (values.length === 0) return 0; return values.reduce((sum, conf) => sum + conf, 0) / values.length; } } /** * Time-aware confidence for temporal decay */ export class TemporalConfidence { private value: number; private timestamp: Date; private halfLife: number; private unit: 'hours' | 'days' | 'weeks' | 'months'; constructor(value: number, options: { halfLife?: number; unit?: 'hours' | 'days' | 'weeks' | 'months'; timestamp?: Date; } = {}) { this.value = value; this.timestamp = options.timestamp || new Date(); this.halfLife = options.halfLife || 30; this.unit = options.unit || 'days'; } /** * Get current confidence accounting for decay */ getCurrent(): number { const age = this.getAge(); const decayFactor = Math.pow(0.5, age / this.halfLife); // Decay towards 0.5 (maximum uncertainty) return this.value * decayFactor + 0.5 * (1 - decayFactor); } /** * Get age in configured units */ getAge(): number { const now = new Date(); const diff = now.getTime() - this.timestamp.getTime(); switch (this.unit) { case 'hours': return diff / (1000 * 60 * 60); case 'days': return diff / (1000 * 60 * 60 * 24); case 'weeks': return diff / (1000 * 60 * 60 * 24 * 7); case 'months': return diff / (1000 * 60 * 60 * 24 * 30); } } /** * Check if confidence has decayed below threshold */ isStale(threshold: number = 0.6): boolean { return this.getCurrent() < threshold; } /** * Get decay explanation */ getDecayExplanation(): string { const current = this.getCurrent(); const age = this.getAge(); const decayPercent = ((this.value - current) / this.value * 100).toFixed(1); return `Original: ${(this.value * 100).toFixed(1)}%, Current: ${(current * 100).toFixed(1)}% (${decayPercent}% decay after ${age.toFixed(1)} ${this.unit})`; } }