Skip to content

Terrorist Organizations - Technical Reference

This page documents the technical implementation of the terrorist organizations use case.

Architecture

use_cases/terrorist_orgs/
├── __init__.py                    # Use case registration
├── data/                          # FTM JSON Lines files
│   ├── us_state_terrorist_orgs.ftm.json
│   ├── gb_proscribed_orgs.ftm.json
│   └── au_listed_terrorist_orgs.ftm.json
├── ontology/
│   ├── followthemoney.ttl         # FTM ontology
│   └── extensions/
│       └── custom_relations.ttl   # HAS_ALIAS extension
├── evaluation_questions.json      # Full evaluation set (70q)
└── evaluation_questions_curated.json  # Curated set (40q)

Components

Parser

The terrorist_orgs use case reuses the FTM parser from the anticorruption use case:

# use_cases/terrorist_orgs/__init__.py
from use_cases.anticorruption.parser import FTMParser, FTMEntity

Parser = FTMParser

FTM Parser Features

The FTMParser class handles FollowTheMoney JSON Lines format:

class FTMParser(BaseParser):
    """Parser for FollowTheMoney JSON Lines files."""

    def parse_all(self) -> Iterator[FTMEntity]:
        """Parse all .ftm.json files in data directory."""
        for file in self.data_dir.glob("*.ftm.json"):
            with open(file) as f:
                for line in f:
                    entity = json.loads(line)
                    yield FTMEntity.from_dict(entity)

FTM Entity Structure

Each FTM entity has this structure:

{
  "id": "NK-c6rsgFRyrcFxF2xZdx4uq4",
  "schema": "Organization",
  "properties": {
    "name": ["Hamas"],
    "alias": ["Islamic Resistance Movement", "Harakat al-Muqawama al-Islamiya"],
    "topics": ["sanction", "crime.terror"],
    "programId": ["US-FTO219"]
  },
  "referents": []
}

ID Resolution

FTM entities reference each other by ID. The parser resolves these to human-readable names:

# Without resolution:
"entity": "NK-c6rsgFRyrcFxF2xZdx4uq4"

# With resolution (default):
"entity": "Hamas"

Properties resolved: - entity (Sanction target) - owner, asset (Ownership) - director, organization (Directorship) - holder, person, relative, associate

Episode Builder

The episode builder converts FTM entities to markdown for Graphiti:

# use_cases/anticorruption/episode_builder.py
def build_ftm_episode_content(entity: FTMEntity) -> str:
    """Build markdown episode from FTM entity."""
    lines = [
        f"# FollowTheMoney Entity: {entity.get_name()}",
        "",
        "## Entity Metadata",
        f"- **Schema Type**: {entity.schema}",
        f"- **Status**: Target of investigation",
        "",
        "## Properties",
    ]

    for prop, values in entity.properties.items():
        if values:
            value_str = ", ".join(str(v) for v in values)
            lines.append(f"- **{prop.title()}**: {value_str}")

    return "\n".join(lines)

Episode Output Example

# FollowTheMoney Entity: Hamas

## Entity Metadata
- **Schema Type**: Organization
- **Status**: Target of investigation

## Properties
- **Name**: Hamas
- **Alias**: Islamic Resistance Movement, Harakat al-Muqawama al-Islamiya
- **Topics**: sanction, crime.terror
- **Program Id**: US-FTO219

## Entity Context
This is an organization entity representing Hamas.

Ontology

The use case uses the FollowTheMoney ontology with extensions:

Base Ontology

followthemoney.ttl defines:

  • Entity classes: Person, Organization, Company, LegalEntity, etc.
  • Relationship classes: Ownership, Directorship, Membership, Sanction
  • Properties: name, alias, jurisdiction, incorporationDate, etc.

HAS_ALIAS Extension

# ontology/extensions/custom_relations.ttl
@prefix ftm: <https://followthemoney.tech/ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

ftm:HAS_ALIAS a owl:ObjectProperty ;
    rdfs:label "HAS_ALIAS" ;
    rdfs:comment "Links an entity to an alternative name or identifier" ;
    rdfs:domain ftm:Thing ;
    rdfs:range ftm:Thing .

Registration

The use case is registered in __init__.py:

# use_cases/terrorist_orgs/__init__.py
from use_cases.anticorruption.parser import FTMParser, FTMEntity
from aletheia.core.ontology import GenericOntologyLoader
from aletheia.core.episodes import register_episode_builder
from use_cases.anticorruption.episode_builder import build_ftm_episode_content

Parser = FTMParser
Ontology = GenericOntologyLoader

DATA_DIR = "use_cases/terrorist_orgs/data"
ONTOLOGY_DIR = "use_cases/terrorist_orgs/ontology"

register_episode_builder(
    "terrorist_orgs",
    build_ftm_episode_content,
    source_description="Multi-Authority Terrorist Organizations (US, UK, Australia)",
)

Data Pipeline

OpenSanctions (.ftm.json)
         ▼ [FTMParser]
    FTMEntity objects
         ▼ [Episode Builder]
    Markdown episodes
         ▼ [Graphiti]
    Knowledge Graph
         ├──► Nodes: Organization, Sanction, PublicBody, Person
         └──► Edges: SANCTION, HAS_ALIAS, RELATES_TO, MENTIONS

Graph Schema

Node Types

Type Count Description
Organization ~285 Terrorist organizations
Sanction ~181 Designation records
PublicBody 4 Designating authorities
Person ~5 Named individuals
Address ~7 Associated locations
Episodic ~427 Source episodes

Edge Types

Type Count Description
MENTIONS ~1162 Episode → Entity
RELATES_TO ~306 General relationships
SANCTION ~161 Authority → Organization
HAS_ALIAS ~155 Organization → Alias

Designating Authorities

Authority Program ID Jurisdiction
US State Department US-FTO219 United States
UK Home Office UK-PROSCRIBED United Kingdom
Attorney-General of Australia AU-TERROR Australia
Australia Home Affairs AU-TERROR Australia

Evaluation Questions

Question Format

{
  "questions": [
    {
      "id": "q1",
      "question": "What alias is used for al-Shabaab?",
      "answer": "al-Hijra",
      "answer_aliases": ["Al-Hijra", "al Hijra"],
      "type": "alias_lookup"
    }
  ]
}

Question Type Distribution (Curated)

Type Count %
entity_existence 9 22.5%
alias_lookup 8 20%
entity_description 8 20%
authority_specific 6 15%
multi_hop 4 10%
cross_jurisdiction 3 7.5%
historical_name 2 5%

Configuration

Environment Variables

# Database
FALKORDB_HOST=localhost
FALKORDB_PORT=6379

# LLM
OPENAI_API_KEY=sk-...

# Embeddings (optional)
EMBEDDING_PROVIDER=local
EMBEDDING_MODEL=BAAI/bge-small-en-v1.5

Search Configuration

For optimal retrieval:

from graphiti_core.search.search_config import (
    SearchConfig,
    NodeSearchConfig,
    EdgeSearchConfig,
)

config = SearchConfig(
    node_config=NodeSearchConfig(
        search_methods=[NodeSearchMethod.cosine_similarity, NodeSearchMethod.bfs],
        reranker=NodeReranker.rrf,
        bfs_max_depth=2,
    ),
    edge_config=EdgeSearchConfig(
        search_methods=[EdgeSearchMethod.cosine_similarity, EdgeSearchMethod.bfs],
        reranker=EdgeReranker.rrf,
    ),
    limit=15,
)

Extending the Use Case

Adding New Data Sources

  1. Download FTM data from OpenSanctions
  2. Place .ftm.json file in data/ directory
  3. Rebuild graph with --reset

Adding Custom Relationships

  1. Create extension TTL file in ontology/extensions/
  2. Define new ObjectProperty
  3. Rebuild ontology graph
  4. Rebuild knowledge graph

Adding Evaluation Questions

Add questions to JSON file:

{
  "id": "q_new",
  "question": "Your question?",
  "answer": "Expected answer",
  "type": "question_type"
}

Run evaluation to validate.