Engineering case study / Public project

NodeFlow AIStructured extraction.
Visible execution.

A five-stage Python pipeline that turns text into a structured result and streams progress to a browser.

Built by Arafaat Shaikh · AI Automation | System Engineer · London

The problem

Make the steps around an AI call visible.

A final model response alone does not show whether input was accepted, which stage is running, or what happened when the model failed. NodeFlow demonstrates a small extraction workflow with explicit stage status, event payloads, and timings.

This is a public demonstration of AI workflow orchestration. Its current implementation runs a fixed sequence, rather than scheduling an arbitrary graph of dependent tasks.

What I built

A FastAPI service serves the browser interface and accepts text at POST /api/pipeline/run. An asynchronous generator sends Server-Sent Events as each stage runs. The application is containerised with Docker and deployed on GCP Cloud Run.

  1. Ingress

    Trim the input, reject empty text, and enforce a 4,000-character limit.

  2. Parser

    Estimate token count using character count divided by four. This is an approximation, not model-specific tokenisation.

  3. Extraction

    Call Gemini with a Pydantic response schema requesting a topic, entities, sentiment, and summary.

  4. Guardrail

    Check that the four required output keys are present before passing the result to the final stage.

  5. Output

    Stream the aggregated result and pipeline status to the browser.

Engineering decisions

Stream progress over the execution request

Server-Sent Events carry node identifiers, status, payload, latency, and timestamps. The browser can show individual stage transitions while the request is still running.

Keep model work off the asynchronous event loop

The pipeline uses asyncio.to_thread for the synchronous model call, allowing the coroutine to await the result without running that call directly on its event loop.

Request structured data and check the boundary

A Pydantic model describes the response requested from Gemini. The later guardrail checks required keys. It does not independently prove the factual accuracy of a summary or enforce every field value.

Failure handling and demo limits

The current source allows two model attempts. A first-attempt 503 error triggers a 1.5-second wait before retrying. Other caught model errors, or an unsuccessful retry, produce a preset fallback result.

The fallback is demonstration data, not a successful extraction from the submitted text. Visitors should inspect the telemetry to distinguish that path from a model response.

Several local stages also include deliberate sleeps so their transitions are visible. Displayed timings include those delays and should not be treated as production performance benchmarks.

What the project demonstrates

The project provides a concrete example of connecting Python, a model API, schema-guided output, browser streaming, and container deployment. Its source makes the execution path and its limits inspectable.

A production extension would need stronger output validation, explicit fallback provenance in the result, and controls for traffic, cost, and operational monitoring. These are follow-on improvements, not capabilities claimed for this demo.