3.2.4. Statement Extraction
"Statement Extraction" refers to the process of splitting our semantic chunks into the smallest possible "atomic" facts. Within our Temporal Agent, this is achieved by:
<ol style="margin-left: 1em; line-height: 1.6; padding-left: 0.5em;"> <li style="margin-bottom: 1.2em;"> <strong>Finding every standalone, declarative claim</strong><br /> <p style="margin-top: 0.5em; margin-bottom: 0.5em;"> Extract statements that can stand on their own as complete subject-predicate-object expressions without relying on surrounding context. </p> </li>Break down complex or compound sentences into minimal, indivisible factual units, each expressing a single relationship.
Replace pronouns or abstract references (e.g., "he" or "The Company") with specific entities (e.g., "John Smith", "AMD") using the main subject for disambiguation.
Retain explicit dates, durations, and quantities to anchor each fact precisely in time and scale.
Temporal Types
The TemporalType enum provides a standardized set of temporal categories that make it easier to classify and work with statements extracted from earnings call transcripts.
Each category captures a different kind of temporal reference:
- Atemporal: Statements that are universally true and invariant over time (e.g., “The speed of light in a vacuum is ≈3×10⁸ m s⁻¹.”).
- Static: Statements that became true at a specific point in time and remain unchanged thereafter (e.g., “Person YY was CEO of Company XX on October 23rd, 2014.”).
- Dynamic: Statements that may change over time and require temporal context to interpret accurately (e.g., “Person YY is CEO of Company XX.”).
from enum import StrEnum
class TemporalType(StrEnum):
"""Enumeration of temporal types of statements."""
ATEMPORAL = "ATEMPORAL"
STATIC = "STATIC"
DYNAMIC = "DYNAMIC"Statement Types
Similarly, the StatementType enum classifies the nature of each extracted statement, capturing its epistemic characteristics.
- Fact: A statement that asserts a verifiable claim considered true at the time it was made. However, it may later be superseded or contradicted by other facts (e.g., updated information or corrections).
- Opinion: A subjective statement reflecting a speaker’s belief, sentiment, or judgment. By nature, opinions are considered temporally true at the moment they are expressed.
- Prediction: A forward-looking or hypothetical statement about a potential future event or outcome. Temporally, a prediction is assumed to hold true from the time of utterance until the conclusion of the inferred prediction window.
class StatementType(StrEnum):
"""Enumeration of statement types for statements."""
FACT = "FACT"
OPINION = "OPINION"
PREDICTION = "PREDICTION"Raw Statement
The RawStatement model represents an individual statement extracted by an LLM, annotated with both its semantic type (StatementType) and temporal classification (TemporalType). These raw statements serve as intermediate representations and are intended to be transformed into TemporalEvent objects in later processing stages.
Core fields:
statement: The textual content of the extracted statementstatement_type: The type of statement (Fact, Opinion, Prediction), based on theStatementTypeenumtemporal_type: The temporal classification of the statement (Static, Dynamic, Atemporal), drawn from theTemporalTypeenum
The model includes field-level validators to ensure that all type annotations conform to their respective enums, providing a layer of robustness against invalid input.
The companion model RawStatementList contains the output of the statement extraction step: a list of RawStatement instances.
from pydantic import field_validator
class RawStatement(BaseModel):
"""Model representing a raw statement with type and temporal information."""
statement: str
statement_type: StatementType
temporal_type: TemporalType
@field_validator("temporal_type", mode="before")
@classmethod
def _parse_temporal_label(cls, value: str | None) -> TemporalType:
if value is None:
return TemporalType.ATEMPORAL
cleaned_value = value.strip().upper()
try:
return TemporalType(cleaned_value)
except ValueError as e:
raise ValueError(f"Invalid temporal type: {value}. Must be one of {[t.value for t in TemporalType]}") from e
@field_validator("statement_type", mode="before")
@classmethod
def _parse_statement_label(cls, value: str | None = None) -> StatementType:
if value is None:
return StatementType.FACT
cleaned_value = value.strip().upper()
try:
return StatementType(cleaned_value)
except ValueError as e:
raise ValueError(f"Invalid temporal type: {value}. Must be one of {[t.value for t in StatementType]}") from e
class RawStatementList(BaseModel):
"""Model representing a list of raw statements."""
statements: list[RawStatement]Statement Extraction Prompt
This is the core prompt that powers our Temporal Agent's ability to extract and label atomic statements. It is written in Jinja allowing us to modularly compose dynamic inputs without rewriting the core logic.
Anatomy of the prompt
<ol style="margin-left: 1em; line-height: 1.6; padding-left: 0.5em;"> <li style="margin-bottom: 1.2em;"> <strong>Set up the extraction task</strong><br /> <p style="margin-top: 0.5em; margin-bottom: 0.5em;"> We instruct the assistant to behave like a domain expert in finance and clearly define the two subtasks: (i) extracting atomic, declarative statements, and (ii) labelling each with a <code>statement_type</code> and a <code>temporal_type</code>. </p> </li>The rules for extraction help to enforce consistency and clarity. Statements must:
- Be structured as clean subject-predicate-object triplets
- Be self-contained and context-independent
- Resolve co-references (e.g., "he" → "John Smith")
- Include temporal/quantitative qualifiers where present
- Be split when multiple events or temporalities are described
The \{% if definitions %\} block makes it easy to inject structured definitions such as statement categories, temporal types, and domain-specific terms.
statement_extraction_prompt = '''
{% macro tidy(name) -%}
{{ name.replace('_', ' ')}}
{%- endmacro %}
You are an expert finance professional and information-extraction assistant.
===Inputs===
{% if inputs %}
{% for key, val in inputs.items() %}
- {{ key }}: {{val}}
{% endfor %}
{% endif %}
===Tasks===
1. Identify and extract atomic declarative statements from the chunk given the extraction guidelines
2. Label these (1) as Fact, Opinion, or Prediction and (2) temporally as Static or Dynamic
===Extraction Guidelines===
- Structure statements to clearly show subject-predicate-object relationships
- Each statement should express a single, complete relationship (it is better to have multiple smaller statements to achieve this)
- Avoid complex or compound predicates that combine multiple relationships
- Must be understandable without requiring context of the entire document
- Should be minimally modified from the original text
- Must be understandable without requiring context of the entire document,
- resolve co-references and pronouns to extract complete statements, if in doubt use main_entity for example:
"your nearest competitor" -> "main_entity's nearest competitor"
- There should be no reference to abstract entities such as 'the company', resolve to the actual entity name.
- expand abbreviations and acronyms to their full form
- Statements are associated with a single temporal event or relationship
- Include any explicit dates, times, or quantitative qualifiers that make the fact precise
- If a statement refers to more than 1 temporal event, it should be broken into multiple statements describing the different temporalities of the event.
- If there is a static and dynamic version of a relationship described, both versions should be extracted
{%- if definitions %}
{%- for section_key, section_dict in definitions.items() %}
==== {{ tidy(section_key) | upper }} DEFINITIONS & GUIDANCE ====
{%- for category, details in section_dict.items() %}
{{ loop.index }}. {{ category }}
- Definition: {{ details.get("definition", "") }}
{% endfor -%}
{% endfor -%}
{% endif -%}
===Examples===
Example Chunk: """
TechNova Q1 Transcript (Edited Version)
Attendees:
* Matt Taylor
ABC Ltd - Analyst
* Taylor Morgan
BigBank Senior - Coordinator
----
On April 1st, 2024, John Smith was appointed CFO of TechNova Inc. He works alongside the current Senior VP Olivia Doe. He is currently overseeing the company’s global restructuring initiative, which began in May 2024 and is expected to continue into 2025.
Analysts believe this strategy may boost profitability, though others argue it risks employee morale. One investor stated, “I think Jane has the right vision.”
According to TechNova’s Q1 report, the company achieved a 10% increase in revenue compared to Q1 2023. It is expected that TechNova will launch its AI-driven product line in Q3 2025.
Since June 2024, TechNova Inc has been negotiating strategic partnerships in Asia. Meanwhile, it has also been expanding its presence in Europe, starting July 2024. As of September 2025, the company is piloting a remote-first work policy across all departments.
Competitor SkyTech announced last month they have developed a new AI chip and launched their cloud-based learning platform.
"""
Example Output: {
"statements": [
{
"statement": "Matt Taylor works at ABC Ltd.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "Matt Taylor is an Analyst.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "Taylor Morgan works at BigBank.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "Taylor Morgan is a Senior Coordinator.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "John Smith was appointed CFO of TechNova Inc on April 1st, 2024.",
"statement_type": "FACT",
"temporal_type": "STATIC"
},
{
"statement": "John Smith has held position CFO of TechNova Inc from April 1st, 2024.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "Olivia Doe is the Senior VP of TechNova Inc.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "John Smith works with Olivia Doe.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "John Smith is overseeing TechNova Inc's global restructuring initiative starting May 2024.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "Analysts believe TechNova Inc's strategy may boost profitability.",
"statement_type": "OPINION",
"temporal_type": "STATIC"
},
{
"statement": "Some argue that TechNova Inc's strategy risks employee morale.",
"statement_type": "OPINION",
"temporal_type": "STATIC"
},
{
"statement": "An investor stated 'I think John has the right vision' on an unspecified date.",
"statement_type": "OPINION",
"temporal_type": "STATIC"
},
{
"statement": "TechNova Inc achieved a 10% increase in revenue in Q1 2024 compared to Q1 2023.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "It is expected that TechNova Inc will launch its AI-driven product line in Q3 2025.",
"statement_type": "PREDICTION",
"temporal_type": "DYNAMIC"
},
{
"statement": "TechNova Inc started negotiating strategic partnerships in Asia in June 2024.",
"statement_type": "FACT",
"temporal_type": "STATIC"
},
{
"statement": "TechNova Inc has been negotiating strategic partnerships in Asia since June 2024.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "TechNova Inc has been expanding its presence in Europe since July 2024.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "TechNova Inc started expanding its presence in Europe in July 2024.",
"statement_type": "FACT",
"temporal_type": "STATIC"
},
{
"statement": "TechNova Inc is going to pilot a remote-first work policy across all departments as of September 2025.",
"statement_type": "FACT",
"temporal_type": "STATIC"
},
{
"statement": "SkyTech is a competitor of TechNova.",
"statement_type": "FACT",
"temporal_type": "DYNAMIC"
},
{
"statement": "SkyTech developed new AI chip.",
"statement_type": "FACT",
"temporal_type": "STATIC"
},
{
"statement": "SkyTech launched cloud-based learning platform.",
"statement_type": "FACT",
"temporal_type": "STATIC"
}
]
}
===End of Examples===
**Output format**
Return only a list of extracted labelled statements in the JSON ARRAY of objects that match the schema below:
{{ json_schema }}
'''