Foresight.Prompts.Retain.V1 (Foresight v0.1.0)

Copy Markdown View Source

Retain-time atomic fact extraction prompt.

Faithful port of Hindsight's engine/retain/fact_extraction.py (_BASE_FACT_EXTRACTION_PROMPT + _CONCISE_GUIDELINES + _CONCISE_EXAMPLES) and the ExtractedFact schema. The LLM reads a single input (a chat session, document, or paragraph) plus its Event Date and emits a LIST of atomic facts — one input to N discrete memory units — which is the mechanism by which cross-session counts, totals, and temporal ordering become answerable at reflect time. Without it, retain stores whole-session blobs and reflect has nothing structured to aggregate over.

build_fact_text/1 mirrors Hindsight's LIVE inline assembler in _extract_facts_from_chunk (what + optional When: when + Involving: who + why, joined by |) — NOT the dead ExtractedFact.build_fact_text Pydantic method, which omits when and is never called by the real pipeline.

Summary

Functions

Combine an extracted fact's dimensions into one stored fact string.

The default extraction mode when a mode is enabled without a specific value.

Entity types offered to the typed-extraction schema/prompt (B3).

Build the system + user messages for one extraction call.

Known extraction modes. nil/"none" disables extraction (passthrough).

JSON schema for the facts list response contract (mirrors FactExtractionResponse).

Functions

build_fact_text(fact)

@spec build_fact_text(map()) :: String.t()

Combine an extracted fact's dimensions into one stored fact string.

Faithful to Hindsight's LIVE assembler in _extract_facts_from_chunk (fact_extraction.py ~L1107-1118): what, then When: <when>, then Involving: <who>, then why — each appended only when present and not "N/A", joined by |.

NOTE: this deliberately does NOT mirror the Pydantic ExtractedFact.build_fact_text method (py ~L166-181), which omits when. That method is DEAD CODE in Hindsight — the real retain pipeline never calls it and assembles combined_text inline WITH the When: clause. Porting the method dropped the temporal marker from every stored fact, starving semantic recall and reflect of dates on temporal/multi-session questions. Keep When: here.

default_mode()

@spec default_mode() :: String.t()

The default extraction mode when a mode is enabled without a specific value.

entity_types()

@spec entity_types() :: [String.t()]

Entity types offered to the typed-extraction schema/prompt (B3).

messages(input, event_date, opts \\ [])

@spec messages(String.t(), String.t() | nil, keyword()) :: [map()]

Build the system + user messages for one extraction call.

input is the raw content to atomize. event_date is the ISO/string date the input was mentioned (used to resolve relative temporal expressions). mission steers what is worth extracting (nil → none). mode selects the guideline block; custom_instructions supplies the guidelines for "custom" mode.

modes()

@spec modes() :: [String.t()]

Known extraction modes. nil/"none" disables extraction (passthrough).

schema(opts \\ [])

@spec schema(keyword()) :: map()

JSON schema for the facts list response contract (mirrors FactExtractionResponse).

Opts:

  • :typed_entities — when true, entities items are {name, type} objects with a type enum (B3 exceed) instead of bare strings. Default false (parity).