intelligence-radar/intelligence_radar/advisor.py

295 lines
16 KiB
Python
Raw Normal View History

"""Deterministic task-fit ranking with explicit gaps and empirical outcome bounds."""
from datetime import date, datetime
import hashlib
import json
import math
from pathlib import Path
from .store import all_records, canonical, get, put
def number(value, name, low=0, high=None):
if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value):
raise ValueError(f'{name} must be a finite number')
if value < low or (high is not None and value > high):
raise ValueError(f'{name} outside allowed range')
return value
def unique(items, label):
ids = [x['id'] for x in items]
if len(ids) != len(set(ids)):
raise ValueError(f'duplicate {label} IDs')
def task_key(task):
# Includes acceptance, constraints, environment, workload and capability requirements.
return hashlib.sha256(canonical(task)).hexdigest()
def wilson(successes, total, z):
p = successes / total
center = p + z*z / (2*total)
delta = z * math.sqrt(p*(1-p)/total + z*z/(4*total*total))
denominator = 1 + z*z/total
return [max(0, (center-delta)/denominator), min(1, (center+delta)/denominator)]
def select(task, benchmarks, policy):
capabilities = task['capabilities']
if not capabilities or sum(capabilities.values()) <= 0:
raise ValueError('task requires positive capability weights')
for k, v in capabilities.items():
number(v, k, high=1)
weights = policy['selection_weights']
if not math.isclose(sum(weights.values()), 1):
raise ValueError('selection policy weights must sum to one')
candidates = []
for b in benchmarks:
if b.get('aggregate', False):
continue
if not b.get('version') or not b.get('limitations'):
raise ValueError('benchmarks require version and limitations')
relevance = sum(v for k, v in capabilities.items() if k in b['constructs']) / sum(capabilities.values())
health = b['health']
base = weights['task_relevance'] * relevance
for key, weight in weights.items():
if key != 'task_relevance':
base += weight * number(health[key], key, high=1)
base -= number(b.get('known_task_bias', 0), 'known_task_bias', high=1)
candidates.append(dict(b, relevance=relevance, selection_score=base))
chosen = []
while candidates and len(chosen) < policy['selection_count']:
def marginal(b):
overlap = max(len(set(b['constructs']) & set(s['constructs'])) /
max(1, len(set(b['constructs']) | set(s['constructs']))) for s in chosen) if chosen else 0
return b['selection_score'] - policy['redundancy_penalty'] * overlap
candidates.sort(key=lambda b: (-marginal(b), b['id']))
picked = candidates.pop(0)
picked['marginal_score'] = marginal(picked)
chosen.append(picked)
total = sum(b['relevance'] for b in chosen)
for b in chosen:
b['weight'] = b['relevance'] / total if total else 0
return chosen
def evidence_ok(root, item, cutoff, max_age, synthetic):
observed = datetime.fromisoformat(item['observed_at'].replace('Z', '+00:00'))
if observed.tzinfo is None:
raise ValueError('evidence timestamps require timezone')
age = (cutoff - observed.date()).days
if age < 0 or age > max_age:
return False
if synthetic:
return item.get('evidence_kind') == 'synthetic'
if not item.get('capture_id'):
return False
capture = get(root, 'captures', item['capture_id'])
if not datetime.fromisoformat(capture['retrieved_at']).date() <= observed.date() <= cutoff:
return False
artifact = Path(root) / 'data/artifacts' / capture['content_sha256']
if hashlib.sha256(artifact.read_bytes()).hexdigest() != capture['content_sha256']:
raise ValueError('capture artifact integrity mismatch')
return item.get('review_status') == 'reviewed' and bool(item.get('reviewer'))
def estimate_cost(task, price):
if price is None:
return None
workload = task['workload']
rates = price['usd_per_million']
cost = 0
for key in ('input', 'cached_input', 'cache_write', 'output'):
tokens = number(workload.get(key, 0), key)
if tokens and key not in rates:
return None
cost += tokens * number(rates.get(key, 0), key + ' rate') / 1_000_000
# Output includes billable reasoning; uncached/cache buckets are disjoint.
cost += number(workload['tool_usd'], 'tool_usd')
cost *= number(workload['attempts'], 'attempts', low=1)
cost += number(workload['verification_usd'], 'verification_usd')
return {'scenario_usd': cost, 'basis': 'declared workload; not a probability-derived estimate',
'price_observed_at': price['observed_at']}
def advise(root, task, catalog, policy, as_of, synthetic=False, saved_outcomes=None):
task, catalog, policy = (json.loads(canonical(x)) for x in (task, catalog, policy))
cutoff = date.fromisoformat(as_of)
number(policy['topnotch_ratio'], 'topnotch ratio', high=1)
number(policy['redundancy_penalty'], 'redundancy penalty', high=1)
number(policy['minimum_outcomes'], 'minimum outcomes', low=1)
number(policy['max_evidence_age_days'], 'maximum evidence age')
number(policy['wilson_z'], 'Wilson z', low=0.01)
for v in policy['thresholds'].values():
number(v, 'sufficiency threshold', high=1)
if date.fromisoformat(policy['effective_from']) > cutoff:
raise ValueError('policy not effective at evidence cutoff')
if synthetic != bool(catalog.get('synthetic', False)):
raise ValueError('synthetic catalogs require --synthetic and cannot mix with live catalogs')
if policy['selection_count'] != 5:
raise ValueError('advisor requires five measurement candidates')
for key in ('objective', 'acceptance', 'environment'):
if not isinstance(task[key], str) or not task[key].strip():
raise ValueError(f'task {key} required')
if task['risk'] not in policy['thresholds']:
raise ValueError('unknown task risk')
for collection in ('benchmarks', 'profiles'):
unique(catalog[collection], collection)
selected = select(task, catalog['benchmarks'], policy)
complete_selection = len(selected) == 5 and all(b['relevance'] > 0 and b['version'] != 'pending-verification' for b in selected)
gaps = [] if complete_selection else ['Fewer than five relevant distinct measurements; ranking withheld.']
max_age = policy['max_evidence_age_days']
rows = []
outcomes = [r for _, r in (all_records(root, 'outcomes') if saved_outcomes is None else saved_outcomes)]
for profile in catalog['profiles']:
for field in ('model', 'harness', 'effort', 'provider', 'deployment'):
if not profile.get(field):
raise ValueError(f'profile {field} required')
reasons = []
available = profile.get('availability')
if not available or not evidence_ok(root, available, cutoff, max_age, synthetic) or available['available'] is not True:
reasons.append('availability unknown, stale, or unavailable')
for key, required in task['constraints'].items():
actual = profile.get('attributes', {}).get(key)
if key.startswith('min_'):
if actual is None or number(actual, key) < number(required, key):
reasons.append(f'constraint {key} not satisfied')
elif actual != required:
reasons.append(f'constraint {key} not satisfied')
scores = []
for b in selected:
matches = [r for r in catalog['results'] if r['profile_id'] == profile['id'] and
r['benchmark_id'] == b['id'] and r['benchmark_version'] == b['version'] and
evidence_ok(root, r, cutoff, max_age, synthetic)]
if len(matches) != 1:
scores.append(None)
continue
scale = b['scale']
lower = number(scale['minimum'], 'scale minimum')
upper = number(scale['maximum'], 'scale maximum')
if upper <= lower:
raise ValueError('benchmark scale maximum must exceed minimum')
raw = number(matches[0]['raw_score'], 'raw score', low=lower, high=upper)
scores.append((raw-lower)/(upper-lower))
fit = sum(b['weight'] * score for b, score in zip(selected, scores)) if complete_selection and all(s is not None for s in scores) else None
prices = [p for p in catalog['prices'] if p['profile_id'] == profile['id'] and
p['currency'] == 'USD' and p['valid_from'] <= as_of <= p['valid_until'] and
evidence_ok(root, p, cutoff, max_age, synthetic)]
price = prices[0] if len(prices) == 1 else None
cost = estimate_cost(task, price)
eligible_outcomes = [o for o in outcomes if o['task_key'] == task_key(task) and
o['profile_hash'] == hashlib.sha256(canonical(profile)).hexdigest() and
o['completed_at'][:10] <= as_of and o['synthetic'] == synthetic]
n = len(eligible_outcomes)
interval = wilson(sum(o['accepted'] for o in eligible_outcomes), n, policy['wilson_z']) if n else None
sufficient = n >= policy['minimum_outcomes'] and interval[0] >= policy['thresholds'][task['risk']]
if task['risk'] == 'high_assurance':
sufficient = sufficient and all(o['independent_verification'] for o in eligible_outcomes)
rows.append({'id': profile['id'], 'eligible': not reasons, 'excluded_reasons': reasons,
'fitness_proxy': fit, 'missing_measurements': [b['id'] for b, s in zip(selected, scores) if s is None],
'cost': cost, 'price_status': 'usable' if price else 'missing_stale_or_conflicting',
'calibration': {'trials': n, 'success_interval_95': interval},
'sufficient': bool(sufficient and not reasons)})
ranked = sorted([r for r in rows if r['eligible'] and r['fitness_proxy'] is not None],
key=lambda r: (-r['fitness_proxy'], r['id']))
frontier = ranked[0]['id'] if ranked else None
topnotch = [r for r in ranked if r['fitness_proxy'] >= ranked[0]['fitness_proxy'] * policy['topnotch_ratio']]
sufficient = [r for r in rows if r['sufficient']]
def cheapest(items):
# Missing prices prevent a defensible claim of cheapest in the eligible set.
if not items or any(r['cost'] is None for r in items):
return None
return min(items, key=lambda r: (r['cost']['scenario_usd'], r['id']))['id']
if not ranked:
gaps.append('No eligible profile has complete benchmark evidence.')
if not sufficient:
gaps.append('no_evidenced_sufficient_model')
return {'schema_version': 1, 'algorithm_version': 'advisor-0.2', 'as_of': as_of, 'synthetic': synthetic,
'task_key': task_key(task), 'policy_id': policy['id'], 'selected_benchmarks': selected,
'profiles': rows, 'frontier': frontier, 'topnotch': [r['id'] for r in topnotch],
'efficient': cheapest(topnotch), 'sufficient': [r['id'] for r in sufficient],
'budget': cheapest(sufficient), 'evidence_gaps': gaps,
'ranking_scope': 'eligible profiles with complete selected evidence; unknown competitors are not proven inferior',
'confidence': 'curator-assigned benchmark health; empirical bounds only for exactly matching task and profile; fitness is a proxy'}
def recommend(root, task, catalog, policy, as_of, synthetic=False):
saved = all_records(root, 'outcomes')
report = advise(root, task, catalog, policy, as_of, synthetic, saved)
snapshot = {'task': task, 'catalog': catalog, 'policy': policy,
'outcomes': saved, 'report': report}
return put(root, 'recommendations', snapshot), report
def _outcome(root, value):
recommendation = get(root, 'recommendations', value['recommendation_id'])
task = recommendation['task']
profiles = [p for p in recommendation['catalog']['profiles'] if p['id'] == value['profile_id']]
if len(profiles) != 1:
raise ValueError('outcome profile absent from recommendation')
for key in ('accepted', 'independent_verification'):
if type(value[key]) is not bool:
raise ValueError(f'{key} must be boolean')
for key in ('actual_usd', 'runtime_seconds'):
number(value[key], key)
completed = datetime.fromisoformat(value['completed_at'].replace('Z', '+00:00'))
if not completed.tzinfo or completed.date() < date.fromisoformat(recommendation['report']['as_of']):
raise ValueError('invalid outcome timestamp')
if not value.get('run_id') or not value.get('verifier_evidence'):
raise ValueError('run_id and verifier_evidence required')
result = dict(value, task_key=task_key(task), synthetic=recommendation['report']['synthetic'],
profile_hash=hashlib.sha256(canonical(profiles[0])).hexdigest())
for ident, existing in all_records(root, 'outcomes'):
if existing['run_id'] == value['run_id']:
if existing != result:
raise ValueError('run_id already recorded with different outcome')
return ident
return put(root, 'outcomes', result)
def replay(root, ident):
snapshot = get(root, 'recommendations', ident)
report = snapshot['report']
if report.get('algorithm_version') != 'advisor-0.2':
raise ValueError('unsupported historical advisor version')
rebuilt = advise(root, snapshot['task'], snapshot['catalog'], snapshot['policy'],
report['as_of'], report['synthetic'], snapshot['outcomes'])
if rebuilt != report:
raise ValueError('recommendation replay mismatch')
return rebuilt
def outcome(root, value):
import fcntl
lockpath = Path(root) / '.runtime/outcomes.lock'
lockpath.parent.mkdir(parents=True, exist_ok=True)
with lockpath.open('a') as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
return _outcome(root, value)
def render_report(root, ident):
report = get(root, 'recommendations', ident)['report']
lines = [f"# Capability comparison — {report['as_of']}", '',
'Synthetic demonstration.' if report['synthetic'] else 'Source-backed comparison; evidence gaps remain explicit.', '',
f"Recommendation: `{ident}`", f"Policy: `{report['policy_id']}`", '',
'| Profile | Eligible | Fitness proxy | Scenario USD | Outcome trials |',
'| --- | --- | --- | --- | --- |']
for row in report['profiles']:
cost = f"{row['cost']['scenario_usd']:.4f}" if row['cost'] else 'unknown'
fit = f"{row['fitness_proxy']:.4f}" if row['fitness_proxy'] is not None else 'unknown'
lines.append(f"| {row['id']} | {row['eligible']} | {fit} | {cost} | {row['calibration']['trials']} |")
lines += ['', f"Frontier: {report['frontier'] or 'undetermined'}",
f"Efficient: {report['efficient'] or 'undetermined'}",
f"Budget: {report['budget'] or 'undetermined'}", '', '## Evidence gaps', '']
lines.extend('- '+gap for gap in report['evidence_gaps'])
for row in report['profiles']:
if row['excluded_reasons']:
lines.append(f"- {row['id']}: " + '; '.join(row['excluded_reasons']))
if row['missing_measurements']:
lines.append(f"- {row['id']}: missing " + ', '.join(row['missing_measurements']))
lines += ['', 'Cost is a declared token/tool/retry/verification scenario, not a measured success-cost distribution.',
'Source review does not prove requester access or task success. See saved inputs for capture references.', '']
return '\n'.join(lines)