entity-extraction
Published
Public
in @structured-extraction

Named-entity recognition: extract people, organizations, locations, dates, money, and more from text — each with a canonical normalized_value and a matched-text + occurrence-index span. Optionally restrict to a caller-supplied set of entity types.

entity-extraction

Named-entity recognition over free text. Pull out people, organizations, locations, dates, times, money, percentages, products, events — each with a canonical normalized_value and a robust span reference.

Entrypoints

EntrypointRendersInputs
systemPromptInstructions, the type taxonomy, optional type filter + embedded schemaoptional entityTypes
userPromptThe delimited text to scantext

Variables

  • text (string, required) — the text to extract entities from.
  • entityTypes (array of string, optional) — restrict extraction to these types only, e.g. ["person","organization"]. Omit to extract every type.

Output

{
  "reasoning": "Found one person, one organization, and one money amount; 'Apple' read as the company, not the fruit.",
  "entities": [
    { "text": "Tim Cook", "occurrence": 1, "type": "person", "normalized_value": "Tim Cook" },
    { "text": "Apple", "occurrence": 1, "type": "organization", "normalized_value": "Apple Inc." },
    { "text": "$3 trillion", "occurrence": 1, "type": "money", "normalized_value": "3000000000000 USD" }
  ]
}
  • reasoning is emitted first (house convention) — a one-line summary including any ambiguous calls.
  • normalized_value carries the canonical form (dates → ISO 8601, money → <amount> <ISO-4217>) or null when no normalization applies. The model is told to never guess a normalization.

Spans: matched-text + occurrence index (not offsets)

Each entity is located by its exact surface text plus a 1-based occurrence index (the Nth time that exact string appears). We deliberately avoid character offsets — LLMs count them unreliably. To map back to your document, find the Nth occurrence of text:

function nthIndex(haystack: string, needle: string, n: number) {
  let i = -1;
  while (n-- > 0) { i = haystack.indexOf(needle, i + 1); if (i < 0) break; }
  return i; // -1 if not found
}

This matched-text + occurrence-index convention is used consistently across the span-based prompts in this collection (see also pii-detection).

House conventions

  • Triple-mustache for text so special characters survive un-escaped.
  • No hallucinated entities — only what's present; empty array when nothing matches.
  • Closed enum on type; strict schema with additionalProperties: false.

Notes

Verified by local render with and without an entityTypes filter. Suggested default claude-sonnet-4-6 at temperature: 0.

@sufleur/