I build data and AI-automation pipelines with a verification layer built in: confidence scores, checks against source, and a human-review queue for anything uncertain. Anyone can get a model to emit JSON; what a team pays for is output it can trust and sign off on.
Recent work: a WNBA player-prop model end to end (scraping, projections, live board) and a Supabase migration for a US sports-analytics site, now on a third consecutive contract. I also audit inherited pipelines. On that project I found a scoring column silently returning 0 for every row because one line selected a DataFrame column by position and landed on the wrong one after an upstream change; nothing raised an error and the dashboard displayed 0 as a valid score.
Korean is my first language, so Korean documents, forms and OCR output are things I audit natively rather than guess at.
I work fully async, in writing. Public code and case studies: jigonyoo.com
Experience Level
Work Experience
Education
Qualifications
Industry Experience
My public work hub: 44 runnable demos across ETL, web scraping, document AI, RAG, analytics, machine learning, developer tooling and robot data.
Every demo ships the output its own code produced, so the numbers on each page are numbers you can reproduce rather than claims you have to take on trust. Each one is MIT-licensed and public on GitHub.
How I work. Verification is part of the build rather than an afterthought: confidence scores, checks against source, and a human-review queue for anything uncertain. Anyone can get a model to emit JSON; what a team pays for is output it can trust and sign off on.
What ships with a project. Tests, and a plain-English handover document, so the client never has to touch the code to understand what it does or why it stopped.
How I work with clients. Fully async, in writing - no live calls. Fixed price by scope where possible, so the cost is known before the work starts.
Browse everything: jigonyoo.com
Raw form submissions become normalized, scored, CRM-ready leads - while uncertain or unreachable cases stop in a human-review queue instead of being auto-routed.
The problem. A high lead score is useless if nobody can reach the lead. Automated intake often stops after classification, so an urgent inquiry with a broken email is silently dropped or misfiled.
Committed run: 10 synthetic leads - 6 auto-routed, 4 held for review.
One warm lead scoring 53/100 with clearly urgent intent was held back because its email was malformed and no phone number was given. Overall confidence 0.568, below the auto-route trust threshold. The promising lead is surfaced for contact repair rather than discarded.
Contact validity, ambiguity and review routing are made explicit, so the queue is a feature rather than an exception path.
Runnable demo: jigonyoo.com/showcase/ai-intake-qualifier.html
Production work for a US sports-analytics client, now on a third consecutive contract.
What it is. Python ETL and scraping pipelines feeding a live WNBA player-prop model, plus a full PostgreSQL/Supabase migration with row-level security and a scheduled job that refreshes the board every morning. The front end is a dark, sortable prop board with per-player sparklines, book line versus projection colouring and a click-through player detail panel, deployed as a standalone page that updates on every push.
The bug worth telling you about. I found a scoring column silently returning 0 for every single row. One line selected a DataFrame column by position, and after an upstream schema change it landed on the wrong one. Nothing errored. The dashboard had looked fine the whole time.
That is the reason every pipeline I build ships with a verification layer rather than just tests that pass. A pipeline that fails loudly is a good day; a pipeline that is quietly wrong costs a client months.
Live board and code: jigonyoo.com
- Spacing around particles and bound nouns, where a wrong space changes the meaning of a field rather than just its formatting
- NFC/NFD normalisation of Hangul jamo, where two visually identical strings compare as unequal and quietly break joins, deduplication and lookups
- Mixed Korean-English strings that split incorrectly under naive tokenisers
- Korean/English bilingual QA, where the two versions of a record have to agree
Korean documents, forms and OCR output audited natively rather than guessed at - the failure modes an English-first pipeline cannot see.
Why this is a distinct skill. Korean is my first language, so I catch things a general-purpose extraction pipeline silently gets wrong:
How it fits the rest of my work. The same verification layer applies: field-level confidence scores, checks against the source document, and a human-review queue for anything uncertain. An OCR pipeline that cannot tell you which fields it is unsure about is not finished.
Document AI demo with the trust layer: jigonyoo.com/showcase/invoice-to-structured.html
A reproducible fictional retail pipeline that ranks cross-sell rules by lift and turns Recency, Frequency and Monetary behaviour into explainable customer segments.
The problem. Popular items can make weak pairings look strong. Confidence alone rewards common products; lift asks whether two items co-occur more often than chance would predict. RFM separates valuable but quiet customers from generic top spenders.
Input: 3,000 transactions, 300 customers, 16 items - with patterns deliberately planted (milk + sugar to coffee, butter + eggs to bread) that the pipeline has to rediscover on its own rather than being told about.
All 300 customers are assigned to exactly one segment - Loyal, Champions, Lost, Needs attention, At-risk, or New/Promising - so the output is actionable rather than decorative. Rules are ranked by excess co-occurrence over chance, not by raw support.
Runnable demo: jigonyoo.com/showcase/data-mining-retail.html
Synthetic site photos become annotated evidence and checklist verdicts, with uncertain detections routed to a person rather than resolved automatically.
The problem. Bounding boxes are not a signed-off inspection. An inspection team needs required items checked, hazards stated in plain language, and borderline calls isolated for review - not a detector’s raw box dump.
Committed run: 6 fictional safety scenes - 2 PASS, 1 REVIEW, 3 FAIL - surfacing 2 hazard violations and 1 defect.
Required items: hardhat, safety vest, fire extinguisher, safety cone. Forbidden: spill or hazard. Confidence gate at 0.55 - anything below it becomes a REVIEW rather than a verdict, so the checklist never asserts something the detector was unsure about.
Runnable demo: jigonyoo.com/showcase/field-inspection-report.html
Raw form submissions become normalized, scored, CRM-ready leads - while uncertain or unreachable cases stop in a human-review queue instead of being auto-routed.
The problem. A high lead score is useless if nobody can reach the lead. Automated intake often stops after classification, so an urgent inquiry with a broken email is silently dropped or misfiled.
Committed run: 10 synthetic leads - 6 auto-routed, 4 held for review.
One warm lead scoring 53/100 with clearly urgent intent was held back because its email was malformed and no phone number was given. Overall confidence 0.568, below the auto-route trust threshold. The promising lead is surfaced for contact repair rather than discarded.
Contact validity, ambiguity and review routing are made explicit, so the queue is a feature rather than an exception path.
Runnable demo: jigonyoo.com/showcase/ai-intake-qualifier.html
An offline, dated static scan for the model IDs and API surfaces scattered across source, configuration, environment defaults and documentation - with days remaining and blast radius attached.
The problem. The vendor publishes a date. The codebase forgets where the dependency lives. A production app can wake up broken on shutdown day because model references hide in settings, test fixtures, old modules and runtime routers.
This builds the inventory. It does not perform the migration, and it does not pretend to.
Evidence stays in its lane: 6 confirmed references, 2 likely, 2 unverified hypotheses, 1 needing runtime data. Static analysis cannot resolve dynamically constructed model names, so the report says so rather than guessing.
Every registry entry carries a vendor source URL and a snapshot date, so each deadline is auditable rather than asserted. Standard library only, no network calls at scan time.
Runnable demo: jigonyoo.com/showcase/llm-deprecation-radar.html
A churn classifier evaluated the way a client should ask for it: split before scaling, a baseline to beat, cross-validation, and explicit limits.
The problem. One lucky accuracy score is not evidence. Churn demos often leak test information into training, ignore the majority baseline, and omit uncertainty entirely.
Committed result: held-out ROC-AUC 0.7982 against a 0.5000 majority baseline; 5-fold cross-validated ROC-AUC 0.819 +/- 0.0298.
1,500 fictional customers are split first into 1,125 training and 375 held-out test rows, and the scaler is fit on training rows only - so the test set never informs the transform.
Against the majority baseline: accuracy 0.7067 vs 0.5893, precision 0.6571 vs 0.0, recall 0.5974 vs 0.0, F1 0.6259 vs 0.0. The model card states what the model does not know as clearly as what it does.
Runnable demo: jigonyoo.com/showcase/ml-churn-pipeline.html
A deliberately messy fictional sales CSV becomes a repeatable KPI report, with every cleaning action and anomaly surfaced for review.
The problem. A polished chart can still be confidently wrong. Duplicates, invalid quantities, missing values and fat-fingered revenue silently distort dashboards. The useful deliverable is not the number - it is the number together with the reasons a human should question it.
Committed output: $120,691.08 total revenue across 397 clean orders, $304.01 average order value, 113 unique customers - plus the list of rows that were dropped or flagged and why.
Raw input included exact duplicates, missing regions, non-positive quantities, mixed date formats and missing revenue. None of it was quietly averaged away.
Runnable demo: jigonyoo.com/showcase/analytics-pipeline.html
Question answering over fictional company policies that cites its evidence, refuses unsupported questions, and measures both behaviours.
The problem. A fluent answer without evidence is an expensive guess. Naive document Q&A answers even when retrieval found nothing relevant. A trustworthy system needs a citable source, a refusal threshold, and a labelled evaluation set that catches regressions before deployment.
Committed evaluation result: retrieval recall@3 1.0 across 11 answerable questions, refusal accuracy 1.0 across 14 total questions, grounded rate 1.0 - every answer cites a source.
In-scope questions get an answer with a citation attached. Out-of-scope questions get ‘I do not have enough information in the provided documents to answer that’ instead of an invention.
Runnable demo: jigonyoo.com/showcase/rag-grounded-qa.html
Invoices, purchase orders and bank statements become structured records only after deterministic math and reconciliation checks.
The problem. Extraction is easy; trusting the extracted numbers is not. A model can copy a printed total into JSON even when the document arithmetic is wrong. Posting that output without a gate turns a parsing success into a payment or reconciliation error.
What the trust layer catches. On the demo purchase order the line total reads 900 while 2 x 480 = 960, so the record is routed to needs_review rather than accepted. On the bank statement, opening + credits - debits = 2975 against a printed closing balance of 2875 - again needs_review.
Nothing is silently corrected. The mismatch is stated in plain language and a person decides.
Runnable demo: jigonyoo.com/showcase/invoice-to-structured.html
Hire a Data Engineer
We have the best data engineer experts on Twine. Hire a data engineer in Seoul today.