OllamaCLI icon
Script icon
Process icon
DiscordIncomingWebhook icon

Structured Data Extraction from Text with a Local Ollama Model

Extract structured JSON from unstructured text with a local Ollama model in Kestra. Parse the fields into typed outputs and post the verdict to Discord.

Categories
AI

The most useful LLM output is not prose, it is fields your systems can act on. This blueprint runs io.kestra.plugin.ollama.cli.OllamaCLI with Ollama's JSON mode to extract product, sentiment, and priority from a raw customer message, entirely on your own hardware. A Python task then does what pipelines should always do with model output: parse it, validate it, and emit clean scalars that downstream tasks and notifications can trust. Nothing in the message ever touches a cloud API.

How it works

  1. extract (io.kestra.plugin.ollama.cli.OllamaCLI) receives the customer message as an inline inputFiles entry and runs ollama run {{ inputs.model }} --format json with a prompt that names the exact keys and allowed values. The --format json flag constrains the model to emit valid JSON, and the answer is redirected to extracted.json, which outputFiles uploads to internal storage.
  2. enableModelCaching: true persists the pulled model between runs, so repeated triage executions skip the download.
  3. parse_fields (io.kestra.plugin.scripts.python.Script on the Process task runner) maps the JSON file in through inputFiles, parses it with the standard library, and prints the priority and sentiment through Kestra's ::{"outputs": {...}}:: protocol, turning model output into typed task outputs.
  4. notify interpolates only those validated scalars into the Discord payload, so a model that wraps its answer in prose or quotes can fail loudly in the parser instead of corrupting a message.
  5. The errors block alerts on any failure, including unparseable model output.

What you get

  • Structured output from unstructured text with zero API cost and zero data egress.
  • A validation seam between the model and everything downstream: the Python task is where you enforce schemas, defaults, and allowed values.
  • Extracted fields as first-class Kestra outputs, ready for If conditions, subflows, or database writes.
  • The raw extracted.json preserved as an execution artifact for auditing what the model actually said.

Who it's for

  • Support and operations teams triaging tickets, reviews, or form submissions without sending customer text to a third party.
  • Data engineers who want LLM extraction to behave like any other typed task in a pipeline.
  • Teams standardizing on local models for cost or compliance reasons who still need machine-readable results.

Why orchestrate this with Kestra

JSON mode gets you valid JSON, not correct JSON. The pipeline shape matters: Kestra passes the model's file to a parser through internal storage, the parser promotes fields to typed outputs, and the notification consumes only those outputs. Each seam is observable, each task retries independently, and the execution history keeps both the raw model answer and the parsed verdict for every message ever triaged.

Prerequisites

  • The default containerImage runs Ollama inside Docker, so the Kestra worker needs access to a Docker daemon. On self-hosted workers that already have Ollama installed locally, set the task's taskRunner to Process to use the local install directly.
  • Python available for the Process task runner on the worker, or switch the parse task to its default Docker runner.
  • A Discord incoming webhook.

Secrets

  • DISCORD_WEBHOOK_URL: Discord incoming webhook URL.

Quick start

  1. Add the DISCORD_WEBHOOK_URL secret to your Kestra namespace.
  2. Execute the flow; Discord should report a high priority, negative sentiment verdict for the sample message.
  3. Replace the inline ticket.txt with real text from your queue, or map it from a previous task's output.

How to extend

  • Enforce a schema in the Python task and raise on missing or invalid values, so bad extractions fail the execution instead of propagating.
  • Feed the message in from a webhook trigger, an email, or an S3 file instead of the inline sample.
  • Batch many messages per run with a shell loop, as shown in the Ollama batch classification blueprint.
  • Route on the extracted priority with an If task, paging on high and queueing the rest.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.