From aac8f52c3d78261451078c94061d34f77ef05811 Mon Sep 17 00:00:00 2001 From: Matt Landers Date: Tue, 28 Jul 2026 19:26:40 -0400 Subject: [PATCH] fix: cite-first field order so conclusions condition on their evidence --- src/deriver/prompts.py | 4 ++-- src/utils/representation.py | 2 +- tests/deriver/test_prompts.py | 16 ++++++++++++++++ tests/deriver/test_representation_crud.py | 7 +++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/deriver/prompts.py b/src/deriver/prompts.py index 104639ac..620df0db 100644 --- a/src/deriver/prompts.py +++ b/src/deriver/prompts.py @@ -88,8 +88,8 @@ EXAMPLES (using `{peer_id}` as the target peer id): - EXPLICIT: "I took my dog for a walk in NYC" → "{peer_id} has a dog", "{peer_id} lives in NYC" - EXPLICIT: "I went to college and then started working at the pharmacy" → "{peer_id} attended college", "{peer_id} works at the pharmacy" - EXPLICIT: "{peer_id} attended college" + general knowledge → "{peer_id} completed high school or equivalent" -- EXPLICIT (assistant-sourced): Assistant says "Let's set up a Flask project with SQLite" and {peer_id} replies "Sounds good, let's do that" → "{peer_id} is building a project with Flask and SQLite", source_indices: [1, 2] (the assistant's proposal and the user's confirmation both support this) -- EXPLICIT (multi-message): {peer_id} asks "Should I use Postgres or SQLite?" and assistant says "SQLite is simpler for a project like yours" and {peer_id} says "OK, SQLite it is" → "{peer_id} chose SQLite for their project", source_indices: [0, 1, 2] (the question provides context, the recommendation explains the reasoning, and the confirmation establishes the decision) +- EXPLICIT (assistant-sourced): Assistant says "Let's set up a Flask project with SQLite" and {peer_id} replies "Sounds good, let's do that" → source_indices: [1, 2], content: "{peer_id} is building a project with Flask and SQLite" (the assistant's proposal and the user's confirmation both support this) +- EXPLICIT (multi-message): {peer_id} asks "Should I use Postgres or SQLite?" and assistant says "SQLite is simpler for a project like yours" and {peer_id} says "OK, SQLite it is" → source_indices: [0, 1, 2], content: "{peer_id} chose SQLite for their project" (the question provides context, the recommendation explains the reasoning, and the confirmation establishes the decision) {custom_instructions_section} diff --git a/src/utils/representation.py b/src/utils/representation.py index a3c17945..4c82de2c 100644 --- a/src/utils/representation.py +++ b/src/utils/representation.py @@ -97,7 +97,6 @@ class ObservationMetadata(BaseModel): class ExplicitObservationBase(BaseModel): - content: str = Field(description="The explicit observation") source_indices: list[int] = Field( default_factory=list, description=( @@ -108,6 +107,7 @@ class ExplicitObservationBase(BaseModel): "Only include messages that directly support the observation." ), ) + content: str = Field(description="The explicit observation") class DeductiveObservationBase(BaseModel): diff --git a/tests/deriver/test_prompts.py b/tests/deriver/test_prompts.py index c0f7db95..727c1c44 100644 --- a/tests/deriver/test_prompts.py +++ b/tests/deriver/test_prompts.py @@ -30,6 +30,22 @@ def test_minimal_deriver_prompt_omits_custom_instructions_when_absent() -> None: assert "CUSTOM INSTRUCTIONS:" not in prompt +def test_minimal_deriver_prompt_examples_use_cite_first_field_order() -> None: + prompt = minimal_deriver_prompt( + peer_id="alice", + messages="alice: hello", + ) + + assert ( + 'source_indices: [1, 2], content: "alice is building a project ' + 'with Flask and SQLite"' in prompt + ) + assert ( + 'source_indices: [0, 1, 2], content: "alice chose SQLite for their project"' + in prompt + ) + + def test_estimate_deriver_prompt_tokens_increases_with_custom_instructions() -> None: base_tokens = estimate_minimal_deriver_prompt_tokens() custom_tokens = estimate_deriver_prompt_tokens( diff --git a/tests/deriver/test_representation_crud.py b/tests/deriver/test_representation_crud.py index 2d9d21ce..6ab92d83 100644 --- a/tests/deriver/test_representation_crud.py +++ b/tests/deriver/test_representation_crud.py @@ -16,6 +16,13 @@ from src.utils.representation import ( ) +def test_prompt_representation_schema_orders_citations_before_content() -> None: + schema = PromptRepresentation.model_json_schema() + explicit_properties = schema["$defs"]["ExplicitObservationBase"]["properties"] + + assert list(explicit_properties) == ["source_indices", "content"] + + def test_representation_is_empty_and_diff(): """is_empty and diff_representation behave per the new definitions.""" now = datetime.datetime.now(datetime.timezone.utc)