Separate destination evidence from agent causality
This commit is contained in:
parent
2534737296
commit
c757e5a09d
2 changed files with 75 additions and 9 deletions
|
|
@ -39,6 +39,9 @@ impl std::fmt::Display for ModelAgentFailure {
|
|||
impl std::error::Error for ModelAgentFailure {}
|
||||
|
||||
pub struct ModelAgentToolContext {
|
||||
/// Causal model/tool receipt ancestry for this action. These IDs prove how
|
||||
/// the action was produced; they are not source evidence for canonical
|
||||
/// world facts or profiles.
|
||||
pub source_receipt_ids: Vec<String>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -789,6 +789,7 @@ struct DestinationReconciliationAgentTool<'a> {
|
|||
expansion_origin_location_id: &'a str,
|
||||
existing_destination_id: Option<&'a str>,
|
||||
snapshot: &'a str,
|
||||
admission_evidence_receipt_ids: &'a [String],
|
||||
}
|
||||
|
||||
enum CivicSystemVerificationOutcome {
|
||||
|
|
@ -2048,7 +2049,15 @@ impl WorldCompiler {
|
|||
constrain_destination_expansion_schema(&mut schema, &source_population_ids).map_err(
|
||||
|error| destination_compilation_failure(error, completed_model_receipts(&[])),
|
||||
)?;
|
||||
let sources = receipt_ids(&receipts);
|
||||
let admission_evidence_receipt_ids = receipt_ids(&receipts);
|
||||
let model_causal_source_receipt_ids = identity_receipts
|
||||
.iter()
|
||||
.chain(std::iter::once(&retrieval_receipt))
|
||||
.map(|receipt| receipt.storage_key().to_owned())
|
||||
.chain(admission_evidence_receipt_ids.iter().cloned())
|
||||
.collect::<BTreeSet<_>>()
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
let destination_evidence = evidence_text(&receipts);
|
||||
let mut compiler_receipts: Vec<ModelStageReceipt> = Vec::new();
|
||||
let mut correction = String::new();
|
||||
|
|
@ -2060,7 +2069,7 @@ impl WorldCompiler {
|
|||
&snapshot,
|
||||
&format!("{base_prompt}{correction}"),
|
||||
schema.clone(),
|
||||
sources.clone(),
|
||||
model_causal_source_receipt_ids.clone(),
|
||||
)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
|
|
@ -2108,7 +2117,7 @@ impl WorldCompiler {
|
|||
let mut expansion = match lower_compiled_destination(
|
||||
campaign,
|
||||
&seed,
|
||||
&sources,
|
||||
&admission_evidence_receipt_ids,
|
||||
expansion_origin_location_id,
|
||||
) {
|
||||
Ok(expansion) => Some(expansion),
|
||||
|
|
@ -2160,7 +2169,7 @@ impl WorldCompiler {
|
|||
);
|
||||
}
|
||||
Ok(()) => {
|
||||
let verification_sources = sources
|
||||
let verification_sources = model_causal_source_receipt_ids
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(
|
||||
|
|
@ -2249,7 +2258,7 @@ impl WorldCompiler {
|
|||
}
|
||||
}
|
||||
let finding = repair_finding.expect("repairable civic candidate has one finding");
|
||||
let reconciliation_sources = sources
|
||||
let reconciliation_sources = model_causal_source_receipt_ids
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(
|
||||
|
|
@ -2271,6 +2280,7 @@ impl WorldCompiler {
|
|||
expansion_origin_location_id,
|
||||
existing_destination_id.as_deref(),
|
||||
&snapshot,
|
||||
&admission_evidence_receipt_ids,
|
||||
&reconciliation_sources,
|
||||
)
|
||||
.await
|
||||
|
|
@ -2288,7 +2298,7 @@ impl WorldCompiler {
|
|||
}
|
||||
}
|
||||
};
|
||||
let evidence_ids = receipt_ids(&receipts);
|
||||
let evidence_ids = admission_evidence_receipt_ids;
|
||||
let affected_sources: Vec<String> = receipts
|
||||
.iter()
|
||||
.flat_map(|r| r.witnesses.iter().map(|w| w.source_id.clone()))
|
||||
|
|
@ -2877,7 +2887,8 @@ impl WorldCompiler {
|
|||
expansion_origin_location_id: &str,
|
||||
existing_destination_id: Option<&str>,
|
||||
snapshot: &str,
|
||||
sources: &[String],
|
||||
admission_evidence_receipt_ids: &[String],
|
||||
causal_source_receipt_ids: &[String],
|
||||
) -> std::result::Result<
|
||||
crate::agent::ModelAgentRun<AcceptedDestinationReconciliation>,
|
||||
crate::agent::ModelAgentFailure,
|
||||
|
|
@ -2951,7 +2962,7 @@ impl WorldCompiler {
|
|||
snapshot_binding: binding,
|
||||
instructions,
|
||||
action_schema: schema,
|
||||
source_receipt_ids: sources.to_vec(),
|
||||
source_receipt_ids: causal_source_receipt_ids.to_vec(),
|
||||
temperature: Some(0.0),
|
||||
max_output_tokens: Some(3_500),
|
||||
max_steps: MAX_DESTINATION_RECONCILIATION_AGENT_STEPS,
|
||||
|
|
@ -2966,6 +2977,7 @@ impl WorldCompiler {
|
|||
expansion_origin_location_id,
|
||||
existing_destination_id,
|
||||
snapshot,
|
||||
admission_evidence_receipt_ids,
|
||||
};
|
||||
run_model_agent(self.model.as_ref(), &spec, &mut tool).await
|
||||
}
|
||||
|
|
@ -3163,7 +3175,7 @@ impl ModelAgentTool for DestinationReconciliationAgentTool<'_> {
|
|||
let mut expansion = match lower_compiled_destination(
|
||||
self.campaign,
|
||||
&corrected,
|
||||
&context.source_receipt_ids,
|
||||
self.admission_evidence_receipt_ids,
|
||||
self.expansion_origin_location_id,
|
||||
) {
|
||||
Ok(expansion) => expansion,
|
||||
|
|
@ -9415,11 +9427,34 @@ mod tests {
|
|||
.iter()
|
||||
.filter(|receipt| receipt.stage == "destination_civic_verification")
|
||||
.collect::<Vec<_>>();
|
||||
let preparation_receipt_ids = receipts
|
||||
.iter()
|
||||
.filter(|receipt| {
|
||||
matches!(
|
||||
receipt.stage.as_str(),
|
||||
"destination_identity_resolution" | "destination_retrieval_plan"
|
||||
)
|
||||
})
|
||||
.map(|receipt| receipt.storage_key())
|
||||
.collect::<BTreeSet<_>>();
|
||||
|
||||
assert_eq!(model.reconciliation_calls.load(Ordering::SeqCst), 2);
|
||||
assert!(model.saw_reconciliation_correction.load(Ordering::SeqCst));
|
||||
assert_eq!(preparation_receipt_ids.len(), 2);
|
||||
assert_eq!(compile_receipts.len(), 1);
|
||||
assert!(preparation_receipt_ids.iter().all(|receipt_id| {
|
||||
compile_receipts[0]
|
||||
.source_receipt_ids
|
||||
.iter()
|
||||
.any(|source| source == *receipt_id)
|
||||
}));
|
||||
assert_eq!(reconciliation_receipts.len(), 2);
|
||||
assert!(preparation_receipt_ids.iter().all(|receipt_id| {
|
||||
reconciliation_receipts[0]
|
||||
.source_receipt_ids
|
||||
.iter()
|
||||
.any(|source| source == *receipt_id)
|
||||
}));
|
||||
assert_eq!(
|
||||
reconciliation_receipts[0].validation_result,
|
||||
"semantic_invalid"
|
||||
|
|
@ -9442,6 +9477,34 @@ mod tests {
|
|||
let DestinationCompilationPreview::RegionExpansion(preview) = preview else {
|
||||
panic!("new destination must produce a region expansion preview")
|
||||
};
|
||||
let admission_evidence_ids = preview
|
||||
.evidence_receipts
|
||||
.iter()
|
||||
.map(|receipt| receipt.id.as_str())
|
||||
.collect::<BTreeSet<_>>();
|
||||
assert!(!admission_evidence_ids.is_empty());
|
||||
let reconciliation_receipt_ids = reconciliation_receipts
|
||||
.iter()
|
||||
.map(|receipt| receipt.storage_key())
|
||||
.collect::<BTreeSet<_>>();
|
||||
for evidence_receipt_id in preview
|
||||
.expansion
|
||||
.population_profiles
|
||||
.iter()
|
||||
.chain(preview.expansion.institution_profiles.iter())
|
||||
.flat_map(|profile| profile.evidence_receipt_ids.iter())
|
||||
.chain(
|
||||
preview
|
||||
.expansion
|
||||
.migration_relations
|
||||
.iter()
|
||||
.chain(preview.expansion.local_relations.iter())
|
||||
.flat_map(|relation| relation.evidence_receipt_ids.iter()),
|
||||
)
|
||||
{
|
||||
assert!(admission_evidence_ids.contains(evidence_receipt_id.as_str()));
|
||||
assert!(!reconciliation_receipt_ids.contains(evidence_receipt_id.as_str()));
|
||||
}
|
||||
let duty = preview
|
||||
.expansion
|
||||
.institutions
|
||||
|
|
|
|||
Loading…
Reference in a new issue