fix: accept text alias in fact extraction (#2969)

This commit is contained in:
Jay Stothard
2026-07-27 11:04:37 +01:00
committed by GitHub
parent 1fa2de3327
commit e5cd239401
2 changed files with 50 additions and 0 deletions
@@ -1484,6 +1484,8 @@ async def _extract_facts_from_chunk(
# Fallback to old format if new fields not present
if not what:
what = get_value("factual_core")
if not what:
what = get_value("text")
if not what:
# In verbatim mode, 'what' is intentionally absent — text is backfilled from chunk
if extraction_mode != "verbatim":
@@ -2246,6 +2248,8 @@ async def extract_facts_from_contents_batch_api(
what = get_value("what")
if not what:
what = get_value("factual_core")
if not what:
what = get_value("text")
if not what:
continue
@@ -203,6 +203,52 @@ async def test_top_level_fact_list_is_accepted_without_retry():
assert "Alice visited Paris" in facts[0].fact
@pytest.mark.asyncio
@pytest.mark.parametrize(
("fact_fields", "expected_count", "expected_text"),
[
({"text": "Alice visited Paris"}, 1, "Alice visited Paris"),
({"what": "Alice visited Paris"}, 1, "Alice visited Paris"),
({}, 0, None),
],
)
async def test_fact_text_alias_is_recovered_without_accepting_empty_facts(
fact_fields, expected_count, expected_text
):
"""Recover schema-drifted ``text`` facts while still skipping empty facts."""
from hindsight_api.engine.retain.fact_extraction import _extract_facts_from_chunk
config = _make_config(llm_max_retries=0, retain_llm_max_retries=None)
llm_config = _make_llm_config(
mock_response=[
{
**fact_fields,
"fact_type": "world",
"fact_kind": "conversation",
}
]
)
with patch(
"hindsight_api.engine.retain.fact_extraction._build_extraction_prompt_and_schema",
return_value=("system prompt", MagicMock()),
):
facts, _usage = await _extract_facts_from_chunk(
chunk="Alice visited Paris.",
chunk_index=0,
total_chunks=1,
event_date=datetime(2023, 1, 1, tzinfo=timezone.utc),
context="travel notes",
llm_config=llm_config,
config=config,
agent_name="test-agent",
)
assert len(facts) == expected_count
if expected_text:
assert expected_text in facts[0].fact
@pytest.mark.asyncio
async def test_non_dict_json_with_default_max_retries_raises():
"""