@prism-lang/confidence
Version:
Confidence extraction library for Prism - standardized patterns for extracting confidence values from LLMs and other sources
226 lines • 8.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.APIConfidenceExtractor = exports.SensorConfidenceExtractor = void 0;
/**
* Extract confidence from sensor readings
*/
class SensorConfidenceExtractor {
/**
* Calculate confidence based on sensor characteristics
*/
fromSensor(_reading, params) {
const factors = {};
// Age factor - newer calibrations are more reliable
if (params.calibrationDate) {
const daysSinceCalibration = params.age;
factors.calibration = Math.max(0, 1 - daysSinceCalibration / 365); // Decay over a year
}
// Environmental factor
factors.environment = this.assessEnvironmentalConditions(params.environment);
// Historical accuracy
factors.history = params.history;
// Sensor age
const sensorAgeFactor = Math.max(0, 1 - params.age / 3650); // 10 year lifespan
factors.age = sensorAgeFactor;
// Aggregate factors
const confidence = this.aggregateFactors(factors);
return {
value: confidence,
explanation: this.generateSensorExplanation(factors, confidence),
provenance: {
sources: [{
method: 'heuristic',
contribution: 1.0,
raw_value: confidence,
adjusted_value: confidence,
reason: 'Sensor characteristics analysis'
}],
adjustments: Object.entries(factors).map(([type, value]) => ({
type: type,
delta: value - 0.5,
reason: `${type} factor`
})),
timestamp: new Date()
}
};
}
/**
* Extract confidence from multiple sensor readings
*/
fromMultipleSensors(readings, options = {}) {
const confidences = readings.map(r => ({
sensor: r.sensor,
confidence: this.fromSensor(r.value, r.params)
}));
const values = confidences.map(c => c.confidence.value);
let aggregated;
switch (options.aggregation || 'mean') {
case 'median':
values.sort((a, b) => a - b);
aggregated = values[Math.floor(values.length / 2)];
break;
case 'weighted':
// Weight by historical accuracy
const weights = readings.map(r => r.params.history);
const weightedSum = values.reduce((sum, val, i) => sum + val * weights[i], 0);
const totalWeight = weights.reduce((sum, w) => sum + w, 0);
aggregated = totalWeight > 0 ? weightedSum / totalWeight : 0;
break;
default:
aggregated = values.reduce((sum, val) => sum + val, 0) / values.length;
}
return {
value: aggregated,
explanation: `Aggregated confidence from ${readings.length} sensors: ${(aggregated * 100).toFixed(1)}%`
};
}
assessEnvironmentalConditions(environment) {
let score = 1.0;
// Temperature effects
if (environment.temperature !== undefined) {
const optimalTemp = environment.optimalTemperature || 20;
const tempDiff = Math.abs(environment.temperature - optimalTemp);
score *= Math.max(0.5, 1 - tempDiff / 50);
}
// Humidity effects
if (environment.humidity !== undefined) {
const optimalHumidity = environment.optimalHumidity || 50;
const humidityDiff = Math.abs(environment.humidity - optimalHumidity);
score *= Math.max(0.7, 1 - humidityDiff / 100);
}
// Vibration/movement
if (environment.vibration !== undefined) {
score *= Math.max(0.6, 1 - environment.vibration / 10);
}
return score;
}
aggregateFactors(factors) {
const weights = {
calibration: 0.3,
environment: 0.25,
history: 0.35,
age: 0.1
};
let weighted = 0;
let totalWeight = 0;
for (const [factor, value] of Object.entries(factors)) {
const weight = weights[factor] || 0.25;
weighted += value * weight;
totalWeight += weight;
}
return totalWeight > 0 ? weighted / totalWeight : 0.5;
}
generateSensorExplanation(factors, confidence) {
const factorStrings = Object.entries(factors)
.map(([name, value]) => `${name}: ${(value * 100).toFixed(0)}%`)
.join(', ');
return `Sensor confidence: ${(confidence * 100).toFixed(1)}% based on ${factorStrings}`;
}
}
exports.SensorConfidenceExtractor = SensorConfidenceExtractor;
/**
* Extract confidence from API reliability
*/
class APIConfidenceExtractor {
providerHistory = new Map();
/**
* Calculate confidence based on API characteristics
*/
fromAPIReliability(params) {
const factors = {};
// Historical accuracy is primary factor
factors.accuracy = params.historicalAccuracy;
// Latency factor - faster responses often more reliable
if (params.latency !== undefined) {
const latencyScore = Math.max(0, 1 - params.latency / 5000); // 5 second max
factors.latency = latencyScore;
}
// Recency of failures
if (params.lastFailure) {
const hoursSinceFailure = (Date.now() - params.lastFailure.getTime()) / (1000 * 60 * 60);
factors.reliability = Math.min(1, hoursSinceFailure / 24); // Full confidence after 24 hours
}
// Provider reputation
factors.reputation = this.getProviderReputation(params.provider);
const confidence = this.aggregateFactors(factors);
return {
value: confidence,
explanation: this.generateAPIExplanation(params.provider, factors, confidence)
};
}
/**
* Track API call for future confidence calculations
*/
trackAPICall(provider, success, latency) {
if (!this.providerHistory.has(provider)) {
this.providerHistory.set(provider, {
calls: 0,
successes: 0,
totalLatency: 0
});
}
const history = this.providerHistory.get(provider);
history.calls++;
if (success) {
history.successes++;
history.totalLatency += latency;
}
else {
history.lastFailure = new Date();
}
}
/**
* Get calculated reliability for a provider
*/
getProviderReliability(provider) {
const history = this.providerHistory.get(provider);
if (!history || history.calls === 0) {
return {
provider,
historicalAccuracy: 0.5 // Unknown provider starts at 50%
};
}
return {
provider,
historicalAccuracy: history.successes / history.calls,
latency: history.successes > 0 ? history.totalLatency / history.successes : undefined,
lastFailure: history.lastFailure
};
}
getProviderReputation(provider) {
// Known provider reputations (could be loaded from config)
const reputations = {
'openai': 0.95,
'anthropic': 0.95,
'google': 0.93,
'weather.com': 0.85,
'openweathermap': 0.80,
'newsapi': 0.75
};
return reputations[provider.toLowerCase()] || 0.7;
}
aggregateFactors(factors) {
const weights = {
accuracy: 0.4,
latency: 0.2,
reliability: 0.25,
reputation: 0.15
};
let weighted = 0;
let totalWeight = 0;
for (const [factor, value] of Object.entries(factors)) {
const weight = weights[factor] || 0.25;
weighted += value * weight;
totalWeight += weight;
}
return totalWeight > 0 ? weighted / totalWeight : 0.5;
}
generateAPIExplanation(provider, factors, confidence) {
const factorStrings = Object.entries(factors)
.map(([name, value]) => `${name}: ${(value * 100).toFixed(0)}%`)
.join(', ');
return `API confidence for ${provider}: ${(confidence * 100).toFixed(1)}% based on ${factorStrings}`;
}
}
exports.APIConfidenceExtractor = APIConfidenceExtractor;
//# sourceMappingURL=sources.js.map