Pre-release. Until the official launch, content may change, including published files.
Skip to content

Source: https://datamodels.jp/en/guide/ai-extraction · Text CC BY 4.0

Extracting data with AI ​

Most entity model pages have structured output for AI in the Download row: a JSON Schema that the structured outputs of AI models accept, with descriptions in English. Send it to an AI model together with a document, such as an e-mail or a PDF, and the model answers with the attributes of the model. This page extracts a designated emergency evacuation site (EvacuationSite) from a short notice, with the OpenAI API or the Claude API.

Document and AI schemaan e-mail or a PDF, and EvacuationSite.ai.json① send to the APIAI modelanswers in the shape of the schema② JSON answersite.jsonthe attributes only: no id or type③ add id and type, checkNGSI-LD entityin the key-values form

1. The schema and the text ​

bash
curl -sSfO https://datamodels.jp/adapters/ai/disaster/EvacuationSite.ai.json

The file is { name, description, strict, schema }. id and type are not in it: your application sets them. The text is in notice.txt, for example:

text
都立一橋高校(東京都千代田区東神田1-12-13)を、地震、高潮、内水氾濫の指定緊急避難場所に指定しました。区の番号は 13101-0012 です。指定避難所も兼ねます。

Both APIs also take a PDF file as input; their documentation shows how.

2. Ask the model ​

The requests are built with jq, which puts the schema and the text into the body. The model names are examples: any model with structured outputs or tools works.

bash
jq -n --slurpfile s EvacuationSite.ai.json --rawfile text notice.txt '{
  model: "gpt-6-astra",
  messages: [
    {role: "system", content: "Extract the evacuation site from the text."},
    {role: "user", content: $text}
  ],
  response_format: {type: "json_schema", json_schema: $s[0]}
}' > request.json
curl -sS https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" --data @request.json \
  | jq '.choices[0].message.content | fromjson' > site.json
bash
jq -n --slurpfile s EvacuationSite.ai.json --rawfile text notice.txt '{
  model: "claude-opus-5-5",
  max_tokens: 16000,
  system: "Extract the evacuation site from the text with the tool.",
  tools: [{name: $s[0].name, description: $s[0].description,
    input_schema: $s[0].schema}],
  messages: [{role: "user", content: $text}]
}' > request.json
curl -sS https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" --data @request.json \
  | jq -e 'first(.content[] | select(.type == "tool_use") | .input)' > site.json
  • OpenAI API: the file is the json_schema of response_format as it is, with strict: true. The answer has every attribute, with null where the text says nothing.
  • Claude API: the schema is the input_schema of a tool, and the answer is the tool's input. The model in the example does not accept a forced tool_choice, so the system prompt asks for the tool; when the answer has no tool call, jq -e stops with an error, and you send the request again. Claude's strict mode ("strict": true on the tool) takes at most 16 properties that may be null per request. EvacuationSite has more, so the example leaves strict out; the answer then usually follows the schema, and step 3 checks it. For a smaller model, or after you remove the attributes you do not need, add "strict": true.
  • To get several sites from one text, put the schema into a list: {"type": "object", "properties": {"sites": {"type": "array", "items": …}}}, with required and additionalProperties: false as in the file.

Read the providers' notes on structured outputs before you rely on them: OpenAI, Claude.

3. Check the answer and make an entity ​

The answer has the attributes only. Remove the empty ones, drop any id or type the AI added, and add your own:

bash
jq 'walk(if type == "object" then with_entries(select(.value != null)) else . end)
  | del(.id, .type)
  | {id: "urn:ngsi-ld:EvacuationSite:0012", type: "EvacuationSite"} + .' \
  site.json > entity.json

Then check entity.json against the model's JSON Schema, as in Validating JSON. Strict mode keeps the shape of the answer, but the AI schema leaves some rules (minimums, rules on several attributes) to its descriptions, and without strict mode nothing is guaranteed. The JSON Schema checks them all. It cannot check the facts: a model can still misread a code or a number, so compare the values with the document before you store them.

entity.json is now a key-values entity. To send it to an NGSI-LD broker, put it into the normalized form with the @context (Sending to an NGSI-LD broker).

Your own models ​

For the models of a site of your own, make the same file with datamodels export --to ai. A model with an attribute that has no strict form has no AI file (Exporting to other tools).