GrowEasyGrowEasy

GrowEasy

Docs

How the extraction pipeline works

Upload any lead CSV — a Facebook or Google Ads export, a real-estate CRM dump, a hand-made sheet. The preview parses in the browser; the moment you confirm, the file is handed to a server-side, two-phase AI pipeline whose output is re-validated in code before a single record is trusted.

01

Two-phase extraction

Phase 1 — Schema inference. One cheap model call reads the header plus a representative sample and returns a typed mapping plan: each source column resolved to a CRM field with a confidence score, plus the detected date format and default country code. That plan is injected into every extraction batch as global context.

Phase 2 — Batched extraction. Rows are chunked (25/batch), run 4 at a time under a concurrency limit at temperature 0, each batch carrying the Phase-1 plan and few-shot examples. Decoding is constrained by a schema, so the model physically cannot emit a value outside the CRM shape or the crm_status / data_source whitelists.

02

The model is never trusted

Constrained decoding guarantees a structurally valid record; it cannot guarantee a truthful one. So every record is re-validated server-side: extracted emails and phone numbers must actually appear in the source row — invented values are moved to crm_note, never kept; created_at must survive new Date(); enums are re-checked against the whitelist; the first email/mobile wins with the rest appended to the note; and a row with neither email nor phone is skipped with a reason rather than silently dropped.
03

Resilience

Per-batch retry with exponential backoff — a malformed response is re-prompted with the exact parse error. A response that overflows the token budget first asks for more room, then recursively halves the batch. Row-count reconciliation re-extracts any rows the model quietly omitted. A batch that still fails after 3 attempts turns its rows into skipped records: one poisoned batch can never fail the whole import.
04

Cost & providers

The pipeline talks to a vendor-agnostic LlmProviderinterface — an OpenAI adapter ships, and adding another is one file. The static system prompt is a cacheable prefix, so the first batch is dispatched alone to warm the cache before the rest fan out. Columns proven empty in every row are pruned deterministically (never on the model's opinion), and batch size and concurrency are env-tunable.
05

API

POST/api/v1/imports

Multipart upload. Validates .csv, 5 MB cap, non-empty, then parses server-side. No AI runs — returns an import id, header list, and row count.

POST/api/v1/imports/:id/process

Opens a Server-Sent Events stream: mapping_plan, then progress and batch_complete as batches land, then a final done — or error. Disconnecting aborts the run so a closed tab stops spending tokens.

About

GrowEasy CSV Importer

Engineered for Predictable Scale.

This workbench was designed to bridge the gap between complex data transformation pipelines and clean, accessible user experiences. Built with a strict focus on visual predictability, high-fidelity micro-interactions, and resilient state synchronization, it demonstrates how frontend topology can turn heavy multi-step data manipulation into a deterministic, seamless flow.

GitHub repo Portfolio

React 19 • TypeScript 5 • Tailwind CSS Engine • React Flow Core