Files
motia-iii/services/graphiti_schema.py
bsiggel b4ff370823 feat(graphiti): Integrate Langfuse Tracer for enhanced monitoring and tracing of Graphiti operations
feat(graphiti): Define entity and edge types in new graphiti_schema for structured data extraction
feat(graphiti): Enhance ingest_episode_event_step with schema integration for improved episode processing
2026-03-30 22:00:53 +00:00

1096 lines
38 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Graphiti Knowledge Graph Zivilrechtliches Kanzlei-Schema (Graphiti-first).
Definiert Pydantic-Modelle für Entity- und Edge-Typen, die Graphiti beim
Extrahieren aus zivilrechtlichen Kanzleidokumenten verwenden soll.
Ziel des Schemas:
- praxisnah für deutsche Zivilrechtskanzleien
- Graphiti-first: wenige, klare, textnah extrahierbare Typen
- saubere Trennung zwischen:
* Tatsachenbehauptungen
* Rechtsbehauptungen / Rechtspositionen
* Auslegungen / Interpretationen
* Beweismitteln
* rechtlichen Autoritäten
* Interessen / Emotionen / internen Bewertungen
Verwendung in add_episode():
from services.graphiti_schema import (
ENTITY_TYPES,
EDGE_TYPES,
EDGE_TYPE_MAP,
EXTRACTION_INSTRUCTIONS,
)
await graphiti.add_episode(
...,
entity_types=ENTITY_TYPES,
edge_types=EDGE_TYPES,
edge_type_map=EDGE_TYPE_MAP,
custom_extraction_instructions=EXTRACTION_INSTRUCTIONS,
)
"""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# Entity-Typen
# ---------------------------------------------------------------------------
class Actor(BaseModel):
"""A person or organization relevant to a legal matter, such as a party,
lawyer, witness, court, insurer, authority, expert, or company."""
actor_kind: Optional[str] = Field(
default=None,
description=(
"Kind of actor: person, organization, court, authority, insurer, "
"expert, lawyer, judge, notary, unknown"
),
)
legal_form: Optional[str] = Field(
default=None,
description="Legal form if applicable, e.g. GmbH, AG, e.V., GbR",
)
function_title: Optional[str] = Field(
default=None,
description=(
"Official or practical function, e.g. Geschäftsführer, Richterin, "
"Sachverständiger, Rechtsanwalt"
),
)
domicile: Optional[str] = Field(
default=None,
description="Residence, seat, registered office, or principal place of business",
)
class Matter(BaseModel):
"""A legal matter, mandate, dispute, proceeding, or case container."""
matter_type: Optional[str] = Field(
default=None,
description=(
"Type of matter: civil_litigation, advisory, pre_litigation, "
"appeal, enforcement, settlement, contract_review, other"
),
)
file_reference: Optional[str] = Field(
default=None,
description="Internal law-firm matter reference or internal file number",
)
court_reference: Optional[str] = Field(
default=None,
description="Court case number or external file number if available",
)
instance_level: Optional[str] = Field(
default=None,
description=(
"Procedural level: pre_litigation, first_instance, appeal, revision, "
"enforcement, post_judgment, non_contentious"
),
)
status: Optional[str] = Field(
default=None,
description="Current status of the matter",
)
subject_area: Optional[str] = Field(
default=None,
description=(
"Area of law, e.g. contract, tort, lease, employment, corporate, "
"commercial, inheritance"
),
)
class Document(BaseModel):
"""A document or communication artifact in or around the legal matter."""
document_type: Optional[str] = Field(
default=None,
description=(
"Type of document: pleading, brief, statement_of_claim, defense_brief, "
"judgment, order, protocol, contract, addendum, email, letter, invoice, "
"expert_report, note, attachment, chat, settlement_draft, other"
),
)
document_date: Optional[datetime] = Field(
default=None,
description="Date the document was created, signed, or issued",
)
source_kind: Optional[str] = Field(
default=None,
description=(
"Source category: client, opponent, court, internal, third_party, "
"authority, insurer, expert, unknown"
),
)
version_label: Optional[str] = Field(
default=None,
description="Version label such as draft, final, executed, amended, signed",
)
authenticity_status: Optional[str] = Field(
default=None,
description="Authenticity status: original, copy, disputed, verified, unknown",
)
class Event(BaseModel):
"""A real-world or procedural event relevant to the matter."""
event_type: Optional[str] = Field(
default=None,
description=(
"Type of event: contract_signing, delivery, payment, damage, defect_notice, "
"termination, negotiation, hearing, filing, service, judgment, settlement_talk, other"
),
)
event_layer: Optional[str] = Field(
default=None,
description="Layer of event: real_world or procedural",
)
event_date: Optional[datetime] = Field(
default=None,
description="Date or start date of the event",
)
end_date: Optional[datetime] = Field(
default=None,
description="End date if the event spans a period",
)
location: Optional[str] = Field(
default=None,
description="Relevant location of the event if stated",
)
certainty_level: Optional[str] = Field(
default=None,
description="Occurrence certainty: certain, likely, disputed, unclear",
)
class Issue(BaseModel):
"""A factual, legal, interpretive, procedural, damages-related, or strategic issue."""
issue_type: Optional[str] = Field(
default=None,
description=(
"Type of issue: factual, legal, interpretive, procedural, evidentiary, "
"damages, limitation, settlement, strategic"
),
)
issue_status: Optional[str] = Field(
default=None,
description="Status of the issue: open, disputed, clarified, partially_resolved, decided",
)
importance: Optional[str] = Field(
default=None,
description="Importance level: low, medium, high, critical",
)
description: Optional[str] = Field(
default=None,
description="Short issue description",
)
class FactAssertion(BaseModel):
"""A factual assertion about what happened, existed, was paid, signed, delivered,
said, known, caused, or otherwise factually occurred."""
assertion_text: Optional[str] = Field(
default=None,
description="Atomic factual assertion in natural language",
)
fact_type: Optional[str] = Field(
default=None,
description=(
"Type of factual assertion: event, state, causation, payment, communication, "
"authorship, authenticity, chronology, amount, identity, knowledge, possession, other"
),
)
status: Optional[str] = Field(
default=None,
description=(
"Status in the matter: asserted, disputed, undisputed, admitted, contradicted, "
"established, unclear"
),
)
assertion_date: Optional[datetime] = Field(
default=None,
description="Date on which the assertion was made or first recorded",
)
certainty_level: Optional[str] = Field(
default=None,
description="Confidence in the factual content: certain, likely, uncertain, disputed",
)
class LegalAssertion(BaseModel):
"""A legal assertion, legal position, or legal conclusion about rights,
obligations, validity, liability, admissibility, limitation, or legal effect."""
assertion_text: Optional[str] = Field(
default=None,
description="Atomic legal assertion in natural language",
)
legal_type: Optional[str] = Field(
default=None,
description=(
"Type of legal assertion: validity, invalidity, liability, no_liability, "
"admissibility, inadmissibility, limitation, enforceability, jurisdiction, "
"burden, interpretation_result, other"
),
)
status: Optional[str] = Field(
default=None,
description="Status of the legal position: asserted, contested, accepted, court_indicated, decided, unclear",
)
certainty_level: Optional[str] = Field(
default=None,
description="Strength or confidence: strong, moderate, weak, uncertain",
)
class Interpretation(BaseModel):
"""An interpretation of a contract, clause, statute, statement, conduct,
communication, or procedural act."""
interpretation_text: Optional[str] = Field(
default=None,
description="Natural language statement of the interpretation",
)
interpretation_type: Optional[str] = Field(
default=None,
description=(
"Type of interpretation: contract, clause, statute, statement, conduct, "
"procedural_act, communication"
),
)
method: Optional[str] = Field(
default=None,
description=(
"Interpretive method: wording, systematics, purpose, context, "
"party_intent, case_law_based, mixed"
),
)
status: Optional[str] = Field(
default=None,
description="Status: proposed, contested, plausible, preferred, court_adopted, rejected",
)
certainty_level: Optional[str] = Field(
default=None,
description="Confidence of the interpretation: strong, moderate, weak, uncertain",
)
class Evidence(BaseModel):
"""Evidence offered, available, produced, or evaluated in support of factual content."""
evidence_type: Optional[str] = Field(
default=None,
description=(
"Type of evidence: document, witness, expert_report, photo, video, audio, "
"log, invoice, chat, email, inspection, party_hearing, other"
),
)
evidence_date: Optional[datetime] = Field(
default=None,
description="Date of the evidence item or date it was generated",
)
origin: Optional[str] = Field(
default=None,
description="Origin of evidence: client, opponent, court, third_party, expert, authority, unknown",
)
authenticity_status: Optional[str] = Field(
default=None,
description="Authenticity or integrity status: verified, disputed, unknown, partial",
)
evidentiary_weight: Optional[str] = Field(
default=None,
description="Indicative evidentiary weight: weak, medium, strong, unclear",
)
evaluation_status: Optional[str] = Field(
default=None,
description="Evaluation state: offered, produced, admitted, examined, evaluated, rejected, not_used",
)
class Authority(BaseModel):
"""A legal authority such as a statute, court decision, contract clause,
contract text, or other normative/legal source used in reasoning."""
authority_type: Optional[str] = Field(
default=None,
description="Type of authority: statute, case_law, contract_clause, contract, regulation, procedural_rule, other",
)
citation: Optional[str] = Field(
default=None,
description=(
"Citation or identifier, e.g. § 280 Abs. 1 BGB, § 307 BGB, "
"BGH NJW 2021, 1234, clause 5.2"
),
)
authority_date: Optional[datetime] = Field(
default=None,
description="Date of the decision, version, or relevant authority text if available",
)
court_or_source: Optional[str] = Field(
default=None,
description="Issuing court or source if applicable",
)
version_label: Optional[str] = Field(
default=None,
description="Version or temporal qualifier if relevant",
)
class Claim(BaseModel):
"""A claim, defense, objection, set-off, counterclaim, or procedural application."""
claim_type: Optional[str] = Field(
default=None,
description=(
"Type: payment, damages, injunction, declaratory_relief, rescission, "
"setoff, limitation_defense, objection, counterclaim, procedural_application, other"
),
)
legal_basis: Optional[str] = Field(
default=None,
description="Stated legal basis, e.g. § 280 BGB, § 823 BGB, contract clause",
)
amount: Optional[float] = Field(
default=None,
description="Monetary amount if applicable",
)
currency: Optional[str] = Field(
default=None,
description="Currency code, e.g. EUR",
)
status: Optional[str] = Field(
default=None,
description="Status: asserted, disputed, pending, partially_granted, granted, rejected, settled, unclear",
)
limitation_status: Optional[str] = Field(
default=None,
description="Limitation status if relevant: not_raised, raised, disputed, expired, not_expired, unclear",
)
class FinancialItem(BaseModel):
"""A financial item such as payment, invoice, receivable, damage item,
fee, interest, or cost item."""
item_type: Optional[str] = Field(
default=None,
description="Type: payment, invoice, receivable, damage_item, fee, cost, interest, settlement_amount, other",
)
amount: Optional[float] = Field(
default=None,
description="Amount of the financial item",
)
currency: Optional[str] = Field(
default=None,
description="Currency code, e.g. EUR",
)
booking_date: Optional[datetime] = Field(
default=None,
description="Booking, invoice, payment, or valuation date",
)
due_date: Optional[datetime] = Field(
default=None,
description="Due date if applicable",
)
status: Optional[str] = Field(
default=None,
description="Status: claimed, paid, overdue, disputed, offset, partially_paid, written_off, unclear",
)
class Interest(BaseModel):
"""A substantive, economic, personal, reputational, relational, or strategic interest."""
interest_type: Optional[str] = Field(
default=None,
description="Type of interest: economic, personal, reputational, strategic, relational, procedural",
)
description: Optional[str] = Field(
default=None,
description="Description of the interest pursued or protected",
)
priority: Optional[str] = Field(
default=None,
description="Priority level: low, medium, high, critical",
)
explicitness: Optional[str] = Field(
default=None,
description="How explicit the interest is: explicit, inferred, assumed",
)
time_relevance: Optional[str] = Field(
default=None,
description="Temporal relevance: immediate, ongoing, long_term",
)
class Emotion(BaseModel):
"""An emotional state or emotional stance relevant to conflict dynamics,
credibility, escalation, negotiation, or settlement."""
emotion_type: Optional[str] = Field(
default=None,
description="Type: anger, fear, distrust, urgency, willingness, hostility, frustration, relief, uncertainty, other",
)
intensity: Optional[str] = Field(
default=None,
description="Intensity: low, medium, high",
)
polarity: Optional[str] = Field(
default=None,
description="Polarity: positive, negative, mixed, neutral",
)
inferred_from: Optional[str] = Field(
default=None,
description="Short explanation of what the emotional inference is based on",
)
temporal_scope: Optional[str] = Field(
default=None,
description="Temporal scope: momentary, ongoing, recurring, unclear",
)
class Assessment(BaseModel):
"""An internal assessment of risk, opportunity, strategy, weakness, strength,
evidentiary posture, legal strength, or settlement option."""
assessment_type: Optional[str] = Field(
default=None,
description=(
"Type: risk, opportunity, strategy, weakness, strength, settlement_option, "
"evidentiary_assessment, legal_assessment, procedural_assessment"
),
)
assessment_text: Optional[str] = Field(
default=None,
description="Text of the internal assessment",
)
severity: Optional[str] = Field(
default=None,
description="Severity or importance: low, medium, high, critical",
)
likelihood: Optional[str] = Field(
default=None,
description="Likelihood if relevant: low, medium, high, unclear",
)
assessment_date: Optional[datetime] = Field(
default=None,
description="Date of the assessment",
)
class Deadline(BaseModel):
"""A legal, procedural, contractual, or internal deadline or due date."""
deadline_type: Optional[str] = Field(
default=None,
description=(
"Type: court_deadline, limitation, reply_deadline, hearing_date, "
"payment_due_date, internal_deadline, appeal_deadline, enforcement_deadline"
),
)
due_date: Optional[datetime] = Field(
default=None,
description="Due date or scheduled time",
)
status: Optional[str] = Field(
default=None,
description="Status: upcoming, met, missed, extended, unclear",
)
consequence: Optional[str] = Field(
default=None,
description="Potential or actual consequence of meeting or missing the deadline",
)
class InformationGap(BaseModel):
"""A missing document, fact, evidence item, clarification, timeline element,
authority, or calculation needed for the matter."""
gap_type: Optional[str] = Field(
default=None,
description=(
"Type: missing_document, missing_fact, missing_evidence, missing_calculation, "
"missing_authority, missing_instruction, missing_timeline, other"
),
)
description: Optional[str] = Field(
default=None,
description="Description of what is missing",
)
relevance_level: Optional[str] = Field(
default=None,
description="Relevance: low, medium, high, critical",
)
requested_from: Optional[str] = Field(
default=None,
description="Who is expected to provide or clarify the missing information",
)
resolution_status: Optional[str] = Field(
default=None,
description="Status: open, requested, partially_resolved, resolved, unobtainable",
)
# ---------------------------------------------------------------------------
# Edge-Typen
# ---------------------------------------------------------------------------
class HasRole(BaseModel):
"""Role of an actor in a matter."""
role_type: Optional[str] = Field(
default=None,
description=(
"Role in the matter: client, plaintiff, defendant, witness, expert, judge, "
"lawyer, opposing_lawyer, insurer, third_party, debtor, creditor, other"
),
)
side: Optional[str] = Field(
default=None,
description="Side in the matter: own_side, opposing_side, neutral, court_side, unclear",
)
start_date: Optional[datetime] = Field(
default=None,
description="Date the role began",
)
end_date: Optional[datetime] = Field(
default=None,
description="Date the role ended",
)
class OccursInMatter(BaseModel):
"""Connects an entity to the legal matter it belongs to."""
relevance: Optional[str] = Field(
default=None,
description="Relevance to the matter: peripheral, relevant, central",
)
class InvolvesActor(BaseModel):
"""Indicates involvement of an actor in another entity."""
involvement_type: Optional[str] = Field(
default=None,
description=(
"Type of involvement: author, sender, recipient, signatory, participant, "
"subject, holder, affected_party, beneficiary, target, issuer, addressee, other"
),
)
class ContainsFactAssertion(BaseModel):
"""A document contains a factual assertion."""
section_reference: Optional[str] = Field(
default=None,
description="Section, page, paragraph, sentence, or exhibit reference if available",
)
class ContainsLegalAssertion(BaseModel):
"""A document contains a legal assertion."""
section_reference: Optional[str] = Field(
default=None,
description="Section, page, paragraph, sentence, or exhibit reference if available",
)
class ContainsInterpretation(BaseModel):
"""A document contains an interpretation."""
section_reference: Optional[str] = Field(
default=None,
description="Section, page, paragraph, sentence, or exhibit reference if available",
)
class AssertsFact(BaseModel):
"""An actor asserts, denies, admits, reports, or disputes a factual assertion."""
modality: Optional[str] = Field(
default=None,
description="Modality: asserts, denies, admits, reports, suspects, recalls, disputes",
)
assertion_date: Optional[datetime] = Field(
default=None,
description="Date of the assertion if known",
)
class AssertsLegalPosition(BaseModel):
"""An actor advances, contests, accepts, or rejects a legal assertion."""
modality: Optional[str] = Field(
default=None,
description="Modality: asserts, contests, accepts, proposes, adopts, rejects",
)
assertion_date: Optional[datetime] = Field(
default=None,
description="Date the legal position was asserted",
)
class ProposesInterpretation(BaseModel):
"""An actor proposes, contests, adopts, prefers, or rejects an interpretation."""
modality: Optional[str] = Field(
default=None,
description="Modality: proposes, contests, adopts, rejects, prefers",
)
assertion_date: Optional[datetime] = Field(
default=None,
description="Date the interpretation was proposed or discussed",
)
class SupportsFact(BaseModel):
"""Evidence supports or tends to support a factual assertion."""
strength: Optional[str] = Field(
default=None,
description="Support strength: weak, medium, strong",
)
directness: Optional[str] = Field(
default=None,
description="Directness: direct, indirect, circumstantial",
)
class SupportsLegalPosition(BaseModel):
"""A legal authority supports or limits a legal assertion."""
support_type: Optional[str] = Field(
default=None,
description="Support type: direct, analogous, persuasive, conflicting, limiting",
)
strength: Optional[str] = Field(
default=None,
description="Support strength: weak, medium, strong",
)
class SupportsInterpretation(BaseModel):
"""An authority or factual context supports an interpretation."""
support_type: Optional[str] = Field(
default=None,
description="Support type: wording, context, purpose, case_law, factual_context, mixed",
)
strength: Optional[str] = Field(
default=None,
description="Support strength: weak, medium, strong",
)
class ConcernsIssue(BaseModel):
"""Connects an entity to an issue it concerns."""
relevance: Optional[str] = Field(
default=None,
description="Relevance to the issue: low, medium, high, critical",
)
class RelatesToClaim(BaseModel):
"""Connects an entity to a claim, defense, objection, or application."""
relation_type: Optional[str] = Field(
default=None,
description=(
"Relation type: supports, weakens, required_for, contests, quantifies, "
"limits, defeats, substantiates"
),
)
class Contradicts(BaseModel):
"""A contradiction or inconsistency between two elements."""
conflict_kind: Optional[str] = Field(
default=None,
description=(
"Kind of conflict: factual, legal, interpretive, evidentiary, chronology, "
"amount, authenticity"
),
)
severity: Optional[str] = Field(
default=None,
description="Severity: low, medium, high, critical",
)
explanation: Optional[str] = Field(
default=None,
description="Short explanation of the contradiction",
)
class Interprets(BaseModel):
"""An interpretation interprets a legal authority, document, clause, or legal proposition."""
target_aspect: Optional[str] = Field(
default=None,
description="Aspect interpreted: wording, clause_scope, intent, legal_effect, procedural_meaning, other",
)
class TriggersDeadline(BaseModel):
"""A document or event triggers a deadline."""
trigger_type: Optional[str] = Field(
default=None,
description="Type of trigger: service, filing, judgment, notice, contract_event, invoice, limitation_start, other",
)
class ConcernsFinancialItem(BaseModel):
"""Connects a document, event, or claim to a financial item."""
relation_type: Optional[str] = Field(
default=None,
description="Relation type: creates, evidences, claims, pays, reduces, offsets, calculates, disputes",
)
class HoldsInterest(BaseModel):
"""An actor holds or pursues an interest."""
basis: Optional[str] = Field(
default=None,
description="Basis: explicit_statement, negotiation_behavior, correspondence, internal_note, inferred, assumed",
)
class ExperiencesEmotion(BaseModel):
"""An actor experiences or displays an emotion or emotional stance."""
basis: Optional[str] = Field(
default=None,
description="Basis: explicit_statement, observed_behavior, tone, negotiation, internal_note, inferred",
)
class Influences(BaseModel):
"""A strategic, emotional, or analytical factor influences another element."""
influence_type: Optional[str] = Field(
default=None,
description=(
"Influence type: strengthens, weakens, delays, escalates, enables_settlement, "
"blocks_settlement, changes_priority, increases_risk"
),
)
strength: Optional[str] = Field(
default=None,
description="Influence strength: low, medium, high",
)
class IdentifiesGap(BaseModel):
"""An issue, claim, or assessment identifies a missing piece of information."""
urgency: Optional[str] = Field(
default=None,
description="Urgency: low, medium, high, critical",
)
class AddressesGap(BaseModel):
"""An entity helps resolve an information gap."""
resolution_quality: Optional[str] = Field(
default=None,
description="Quality of resolution: partial, substantial, complete",
)
class Assesses(BaseModel):
"""An internal assessment evaluates another entity."""
assessment_aspect: Optional[str] = Field(
default=None,
description=(
"Aspect evaluated: credibility, legal_strength, evidentiary_strength, "
"settlement_value, procedural_risk, economic_impact, strategic_value"
),
)
# ---------------------------------------------------------------------------
# Zusammengefasste Exports
# ---------------------------------------------------------------------------
ENTITY_TYPES: dict[str, type[BaseModel]] = {
"Actor": Actor,
"Matter": Matter,
"Document": Document,
"Event": Event,
"Issue": Issue,
"FactAssertion": FactAssertion,
"LegalAssertion": LegalAssertion,
"Interpretation": Interpretation,
"Evidence": Evidence,
"Authority": Authority,
"Claim": Claim,
"FinancialItem": FinancialItem,
"Interest": Interest,
"Emotion": Emotion,
"Assessment": Assessment,
"Deadline": Deadline,
"InformationGap": InformationGap,
}
EDGE_TYPES: dict[str, type[BaseModel]] = {
"HasRole": HasRole,
"OccursInMatter": OccursInMatter,
"InvolvesActor": InvolvesActor,
"ContainsFactAssertion": ContainsFactAssertion,
"ContainsLegalAssertion": ContainsLegalAssertion,
"ContainsInterpretation": ContainsInterpretation,
"AssertsFact": AssertsFact,
"AssertsLegalPosition": AssertsLegalPosition,
"ProposesInterpretation": ProposesInterpretation,
"SupportsFact": SupportsFact,
"SupportsLegalPosition": SupportsLegalPosition,
"SupportsInterpretation": SupportsInterpretation,
"ConcernsIssue": ConcernsIssue,
"RelatesToClaim": RelatesToClaim,
"Contradicts": Contradicts,
"Interprets": Interprets,
"TriggersDeadline": TriggersDeadline,
"ConcernsFinancialItem": ConcernsFinancialItem,
"HoldsInterest": HoldsInterest,
"ExperiencesEmotion": ExperiencesEmotion,
"Influences": Influences,
"IdentifiesGap": IdentifiesGap,
"AddressesGap": AddressesGap,
"Assesses": Assesses,
}
# Erlaubte Kanten pro Entity-Paar: (Quell-Typ, Ziel-Typ) -> [erlaubte Edge-Typen]
EDGE_TYPE_MAP: dict[tuple[str, str], list[str]] = {
("Actor", "Matter"): ["HasRole"],
("Document", "Matter"): ["OccursInMatter"],
("Event", "Matter"): ["OccursInMatter"],
("Issue", "Matter"): ["OccursInMatter"],
("Claim", "Matter"): ["OccursInMatter"],
("Deadline", "Matter"): ["OccursInMatter"],
("Assessment", "Matter"): ["OccursInMatter"],
("Interest", "Matter"): ["OccursInMatter"],
("Emotion", "Matter"): ["OccursInMatter"],
("InformationGap", "Matter"): ["OccursInMatter"],
("FinancialItem", "Matter"): ["OccursInMatter"],
("Authority", "Matter"): ["OccursInMatter"],
("Evidence", "Matter"): ["OccursInMatter"],
("FactAssertion", "Matter"): ["OccursInMatter"],
("LegalAssertion", "Matter"): ["OccursInMatter"],
("Interpretation", "Matter"): ["OccursInMatter"],
("Document", "Actor"): ["InvolvesActor"],
("Event", "Actor"): ["InvolvesActor"],
("Claim", "Actor"): ["InvolvesActor"],
("Interest", "Actor"): ["InvolvesActor"],
("Emotion", "Actor"): ["InvolvesActor"],
("FinancialItem", "Actor"): ["InvolvesActor"],
("Document", "FactAssertion"): ["ContainsFactAssertion"],
("Document", "LegalAssertion"): ["ContainsLegalAssertion"],
("Document", "Interpretation"): ["ContainsInterpretation"],
("Actor", "FactAssertion"): ["AssertsFact"],
("Actor", "LegalAssertion"): ["AssertsLegalPosition"],
("Actor", "Interpretation"): ["ProposesInterpretation"],
("Evidence", "FactAssertion"): ["SupportsFact"],
("Authority", "LegalAssertion"): ["SupportsLegalPosition"],
("Authority", "Interpretation"): ["SupportsInterpretation"],
("FactAssertion", "Interpretation"): ["SupportsInterpretation"],
("FactAssertion", "Issue"): ["ConcernsIssue"],
("LegalAssertion", "Issue"): ["ConcernsIssue"],
("Interpretation", "Issue"): ["ConcernsIssue"],
("Evidence", "Issue"): ["ConcernsIssue"],
("Authority", "Issue"): ["ConcernsIssue"],
("Claim", "Issue"): ["ConcernsIssue"],
("FinancialItem", "Issue"): ["ConcernsIssue"],
("Assessment", "Issue"): ["ConcernsIssue"],
("Interest", "Issue"): ["ConcernsIssue"],
("Emotion", "Issue"): ["ConcernsIssue"],
("Deadline", "Issue"): ["ConcernsIssue"],
("InformationGap", "Issue"): ["ConcernsIssue"],
("FactAssertion", "Claim"): ["RelatesToClaim"],
("LegalAssertion", "Claim"): ["RelatesToClaim"],
("Interpretation", "Claim"): ["RelatesToClaim"],
("Evidence", "Claim"): ["RelatesToClaim"],
("Authority", "Claim"): ["RelatesToClaim"],
("FinancialItem", "Claim"): ["RelatesToClaim"],
("Assessment", "Claim"): ["RelatesToClaim"],
("Interest", "Claim"): ["RelatesToClaim"],
("FactAssertion", "FactAssertion"): ["Contradicts"],
("LegalAssertion", "LegalAssertion"): ["Contradicts"],
("Interpretation", "Interpretation"): ["Contradicts"],
("Evidence", "FactAssertion"): ["Contradicts"],
("FactAssertion", "Interpretation"): ["Contradicts"],
("LegalAssertion", "Interpretation"): ["Contradicts"],
("Interpretation", "Authority"): ["Interprets"],
("Interpretation", "Document"): ["Interprets"],
("Interpretation", "LegalAssertion"): ["Interprets"],
("Document", "Deadline"): ["TriggersDeadline"],
("Event", "Deadline"): ["TriggersDeadline"],
("Document", "FinancialItem"): ["ConcernsFinancialItem"],
("Event", "FinancialItem"): ["ConcernsFinancialItem"],
("Claim", "FinancialItem"): ["ConcernsFinancialItem"],
("Actor", "Interest"): ["HoldsInterest"],
("Actor", "Emotion"): ["ExperiencesEmotion"],
("Interest", "Claim"): ["Influences"],
("Interest", "Issue"): ["Influences"],
("Interest", "Assessment"): ["Influences"],
("Emotion", "Issue"): ["Influences"],
("Emotion", "Assessment"): ["Influences"],
("Assessment", "Claim"): ["Influences"],
("Assessment", "Issue"): ["Influences"],
("Assessment", "Matter"): ["Influences"],
("Assessment", "InformationGap"): ["IdentifiesGap"],
("Issue", "InformationGap"): ["IdentifiesGap"],
("Claim", "InformationGap"): ["IdentifiesGap"],
("Document", "InformationGap"): ["AddressesGap"],
("Evidence", "InformationGap"): ["AddressesGap"],
("FactAssertion", "InformationGap"): ["AddressesGap"],
("Authority", "InformationGap"): ["AddressesGap"],
("Assessment", "FactAssertion"): ["Assesses"],
("Assessment", "LegalAssertion"): ["Assesses"],
("Assessment", "Interpretation"): ["Assesses"],
("Assessment", "Evidence"): ["Assesses"],
("Assessment", "Claim"): ["Assesses"],
("Assessment", "FinancialItem"): ["Assesses"],
("Entity", "Entity"): ["RELATES_TO"],
}
# ---------------------------------------------------------------------------
# Freitextanweisung für das LLM beim Extrahieren
# ---------------------------------------------------------------------------
EXTRACTION_INSTRUCTIONS = """
Du analysierst Dokumente einer deutschen Rechtsanwaltskanzlei im Zivilrecht.
Extrahiere nur Informationen, die für anwaltliche Arbeit sinnvoll sind, insbesondere
für Sachverhaltsaufklärung, Schriftsatzarbeit, Beweisführung, Anspruchsprüfung,
Vergleichsstrategie, Fristenkontrolle und Fallbewertung.
Wichtige Grundregeln:
1. Trenne strikt zwischen Tatsachen, Rechtspositionen und Auslegungen.
- FactAssertion:
Tatsachenbehauptungen über reale oder prozessuale Tatsachen.
Beispiele:
* "X unterzeichnete am 15.11.2020 den Dienstvertrag."
* "Die Rechnung über 12.500 EUR wurde am 04.02.2023 bezahlt."
* "Die Gegenseite erhielt das Schreiben am 18.01.2024."
- LegalAssertion:
Rechtsbehauptungen oder rechtliche Schlussfolgerungen.
Beispiele:
* "Der Vertrag ist wirksam."
* "Die Forderung ist verjährt."
* "Die Kündigung war unwirksam."
- Interpretation:
Auslegung von Vertrag, Klausel, Norm, Erklärung, Verhalten oder Kommunikation.
Beispiele:
* "§ 5 des Vertrags ist als Haftungsbegrenzung auszulegen."
* "Die E-Mail vom 12.03. ist als Kündigungserklärung zu verstehen."
2. Trenne strikt zwischen Evidence und Authority.
- Evidence:
Beweismittel für Tatsachen, z.B. Urkunden, E-Mails, Zeugen, Gutachten, Rechnungen, Fotos, Logs.
- Authority:
Rechtliche Autoritäten, z.B. Gesetze, Gerichtsentscheidungen, Vertragsklauseln, Vertragsbestimmungen.
3. Extrahiere Interests und Emotions nur, wenn sie im Text ausdrücklich erkennbar
oder aus dem Kontext mit hoher Plausibilität ableitbar sind.
- Interest:
wirtschaftliche, persönliche, strategische oder reputationsbezogene Interessen.
Beispiele:
* "Mandant will schnelle außergerichtliche Einigung."
* "Gegenseite will Präzedenzfall vermeiden."
- Emotion:
emotional relevante Lage oder Haltung.
Beispiele:
* "Mandant ist verärgert."
* "Gegenseite wirkt nicht vergleichsbereit."
Wenn unklar, lieber nicht extrahieren.
4. Extrahiere Issue-Knoten für zentrale Streitfragen oder Problemfelder.
Beispiele:
- "Zugang der Kündigung"
- "Wirksamkeit der AGB-Klausel"
- "Schadenshöhe"
- "Verjährung"
- "Aktivlegitimation"
5. Extrahiere Claim-Knoten für Ansprüche, Einreden, Einwendungen, Gegenansprüche
oder prozessuale Anträge.
Beispiele:
- Kaufpreisforderung
- Schadensersatzanspruch
- Einrede der Verjährung
- Aufrechnung
- Feststellungsantrag
6. Extrahiere FinancialItem-Knoten für Zahlungen, Rechnungen, Schadenspositionen,
Zinsen, Kosten oder sonstige Geldpositionen, soweit konkret erkennbar.
7. Extrahiere Deadlines nur, wenn eine Frist oder ein konkreter Termin deutlich genannt ist.
Beispiele:
- Berufungsfrist
- gerichtliche Erwiderungsfrist
- Zahlung fällig zum 31.03.2024
- Termin zur mündlichen Verhandlung
8. Extrahiere InformationGap nur, wenn im Text ausdrücklich oder sinngemäß erkennbar ist,
dass etwas fehlt oder noch beschafft/geklärt werden muss.
Beispiele:
- fehlende Originalvollmacht
- fehlender Zahlungsnachweis
- unklare Zustellung
- fehlende Schadensberechnung
Beachte bei der Extraktion:
- Nutze klare, atomare Informationen statt zusammengesetzter Sätze.
- Verwende für assertion_text und ähnliche Textfelder möglichst knappe, präzise Formulierungen.
- Datumsangaben nach Möglichkeit als ISO-Datum oder ISO-Zeitpunkt extrahieren.
- Extrahiere keine strafrechtsspezifischen Rollen oder Konzepte, wenn sie im zivilrechtlichen Kontext nicht relevant sind.
- Vermeide Dubletten; identische oder offensichtlich gleiche Entitäten möglichst zusammenführen.
- Wenn eine Information nur behauptet, aber bestritten ist, extrahiere sie trotzdem, aber mit passendem Status.
- Widersprüche zwischen Tatsachenbehauptungen, Rechtspositionen oder Auslegungen sollen möglichst als Contradicts-Beziehungen erfasst werden.
- Wenn eine Tatsachenbehauptung durch ein Beweismittel gestützt wird, nutze SupportsFact.
- Wenn eine Rechtsbehauptung durch Normen, Rechtsprechung oder Vertragsklauseln gestützt wird, nutze SupportsLegalPosition.
- Wenn eine Auslegung durch Wortlaut, Kontext, Parteiwillen oder Rechtsprechung gestützt wird, nutze SupportsInterpretation.
- Verknüpfe relevante Elemente mit Issues und Claims, wenn der Zusammenhang aus dem Text erkennbar ist.
- Verknüpfe Actors mit Matters über HasRole, wenn die Rolle im Mandat oder Verfahren erkennbar ist.
Nutze dieses Schema streng und bevorzuge juristisch brauchbare Präzision vor Vollständigkeit.
""".strip()