00

Ray Chang

AI/ML software engineer, 7 years across LLM agents, distributed systems, ETL and MLOps.

Selected projects · 2019–present

xiong7238@gmail.com

Skills and the projects that demonstrate them

01

Solo Dev, 0 to 1: Engineering to Marketing

An AI note-taking product. I build and run all of it.

Video poster: Product demo
Yes, I have long hair now 😂
LLM agent harness
an orchestrator routes each request to the right skill
Grounded Q&A
every citation checked word for word against its source
Payments
estimated before the job runs, reconciled against actual
Analytics
a durable event pipeline, activation instrumented
AI-UGC marketing
30 ads around one identity-consistent persona
Infrastructure
Cloudflare Workers, D1, R2, AWS Batch, Terraform

AI-UGC Ad Factory

One consistent persona. Automated VLM quality gate on stills.

  • 30 ads shipped
02

Founding a 500-Person Deep-Learning Community

9 core members, 9 lectures, ~140 attendees, 500 members

Lecture 09

Video poster: Lecture 09

In seven months the club grew to 9 core members, 500 Facebook group members, and 9 lectures with around 140 attendees. The team reached the final stage of the IEEE MMSP embedded deep-learning object detection competition, taking top 10 honours for a 0.42 mAP algorithm.

03

Learning Without Training

Unsupervised online learning. No registration, no retraining.

Everyone in this diagram is wearing a mask. It plots 24 synthetic face-detection events from a 2019 order-pickup system — 4 sightings of each of 6 recurring visitors — grouped into 6 shaded regions by embedding similarity alone, with no labels. A point the model files under the wrong visitor is drawn three times over: as a filled accent dot inside the region it was wrongly placed in, as a hollow accent ring in the empty place it should have occupied, and as a line joining the two. The field drawn here is the original 2019 model, which misplaces 12 of 24 points (50%), exactly 2 of the 4 sightings of every visitor. A later mask-aware model, on these same masked points, misplaces 1 of 24 (4%); each point it recovers returns along its own line to the ring it left behind.

Illustrative diagram — synthetic points, not real faces or embeddings.

Face-embedding cluster field under masks, 2019 model
Video poster: The system in public use
The Mayor of Taipei used our facial recognition system.

Before the LLM/RAG era: a real-time, insert-as-you-go vector search that classified people on the fly. The first time it ever saw a face, it already knew which order belonged to it.

ArcFace trained in PyTorch over 5M images with no usable implementation to start from — the data cleaning, the visualization frontend, the bad-data detection and the ONNX inference path all written for it. Accuracy through masks went from about 50% to over 95%, with under 0.01% false IDs.

04

17k to 50k Emails a Minute

A two-week email throughput rebuild.

Email throughput: 17k to 50k emails a minute under a service limit that never moves A dashed rule crosses the whole frame at the AWS service limit that capped the old pipeline. One square column, the pipeline before the rebuild, stops exactly at it: 17,000 emails a minute. On the right, three stacked cells of that same height, each still topping out at the same unchanged limit, reach roughly three times as high. A short accent rule marks where they end, 50,000 emails a minute: the only mark in the frame above the limit. The space between the two levels is the headroom parallelism bought. EMAIL SEND PIPELINE BLACK FRIDAY / CYBER MONDAY 18M+ EMAILS · NO DOWNTIME SERVICE LIMIT — UNCHANGED 17k / min BEFORE THE REBUILD 17k 17k 17k AFTER · SAME LIMIT, IN PARALLEL ~ 3 × 50k / min +33k / min Two weeks of re-architecture, designed around the AWS service limits that capped parallelism, not against them.
  • 17k → 50k emails/min (~3x)
  • 18M+ emails
  • Black Friday–Cyber Monday peak
  • Zero downtime
05

System Design Playbook

Deriving each system from one Postgres.

The bottleneck now is reading: reviewing other people's code, at human comprehension speed. Each chapter takes a system a team would usually just buy — Kafka, Kubernetes, Temporal, adaptive inference serving, a point-in-time feature store — and derives it in one vocabulary, so a review agent can explain unfamiliar code in it. The bet underneath: most new technology is new terms over the same old logic.

  • Kafka, Kubernetes, Temporal
  • Adaptive inference serving
  • Point-in-time feature store
06

Skill-Conditioned Argmax Aggregation

A master's thesis alpha pipeline.

SCAA: an alpha pipeline, and the eight out-of-sample windows it closed at 3.03 Across the top, the pipeline in four named steps: branch-level broker order flow, SCAA features built in Polars, the model, and returns taken after full transaction costs. Ablation and SHAP hang below the features card, which is where they attribute the edge. Underneath, eight rows step down and to the right. In each, a soft training region runs off the left edge of the frame, then a literal hole - the three-month embargo - and then a bounded test window. An accent bracket spans exactly the eight test windows. To its right: mean period Sharpe 3.03, against a 1.15 benchmark. SCAA ALPHA PIPELINE 76M BRANCH-LEVEL BROKER ORDER-FLOW RECORDS ORDER FLOW BRANCH LEVEL SCAA FEATURES BUILT IN POLARS MODEL TRAINED PER PERIOD NET RETURNS AFTER FULL COSTS ABLATION + SHAP 8-PERIOD PURGED WALK-FORWARD 3-MONTH EMBARGO 01 02 03 04 05 06 07 08 TRAIN TEST EIGHT WINDOWS, WALKED FORWARD, OUT OF SAMPLE TRAIN EXTENT NOT SHOWN MEAN PERIOD SHARPE 3.03 AGAINST 1.15 BENCHMARK NET OF FULL TRANSACTION COSTS Ablation and SHAP put the edge in the SCAA features themselves, not in the model.

An end-to-end alpha pipeline over 76M branch-level broker order-flow records. Backtested across an 8-period purged walk-forward with a 3-month embargo, net of full transaction costs: mean period Sharpe 3.03 against a 1.15 benchmark, with ablation and SHAP tracing the edge to the SCAA features.

  • 76M order-flow records
  • Sharpe 3.03 vs 1.15 benchmark
  • 8-period walk-forward, 3-mo embargo

Other workshown in brief

Email marketing agent: the instant a generated email is cleared to send On the left, a plain-language conversation feeds a LangGraph agent that generates three parts of an email: the HTML template, the hero image and the copy. Each outgoing edge carries a stepwise check. The three converge into one assembled email. An accent vertical stands across the frame as the guardrail before sending, and it is open at exactly one place: the height of the assembled email, which is crossing it. To the right of that gap the single email fans out into many personalised sends. A return path runs back from the gate into the agent: output that fails a check is regenerated, not dropped. EMAIL MARKETING AGENT PLAIN LANGUAGE CAMPAIGNS, PRODUCTS, AUDIENCES CONVERSATION NON-TECHNICAL USER LANGGRAPH AGENT HTML TEMPLATE HERO IMAGE COPY ALL THREE LLM-GENERATED STEPWISE CHECKS ONE EMAIL ASSEMBLED send-safe EVERY PART CHECKED BEFORE THE SEND PERSONALISED SENDS, AT SCALE ON FAIL, REGENERATE Non-technical users describe a campaign in plain language. Stepwise checks hold every generated part to something that will render, and send.

Email marketing agent

LLM-personalised emails at scale, behind guardrails on everything generated.

Factor semantic search: a typed phrase lands among its nearest factors On the left, a tree view runs off the top and bottom of the frame: too long to fit, which is the point. An arrow marks what replaced it, a single text box holding a typed description. A curve carries that phrase into the field on the right, where the factors sit as a scatter of dots. The accent marks where the phrase landed and the ring around it holds the factors nearest to it. The scatter is a two-dimensional projection and is illustrative; the positions are not measured. FACTOR SEMANTIC SEARCH A FACTOR RECOMMENDER A VERY LONG TREE VIEW REPLACED BY a factor, described in words ONE TEXT BOX TYPED TEXT · ILLUSTRATIVE FACTOR EMBEDDINGS 2-D PROJECTION, ILLUSTRATIVE NEAREST NEIGHBOURS A typed phrase lands in the same space as the factors themselves. What sits nearest it is the recommendation.

Factor semantic search

A factor recommender: semantic search over factor embeddings.

Shopify product sync: three triggers, one path, one store On the left, the three ways a catalogue arrives: a full sync of the whole catalogue, a partial sync of a subset, and real-time events as they happen. The first two are pulled and the third is pushed, and each is tagged with which. Nine lines leave them and funnel into a single throat, marked with the accent: from there on there is one stream. Product rows travel it as cells carrying the store they came from, through one normalise step and one upsert, and down into one store, where the interleaved keys show rows from different tenants sitting in the same table. Relative volumes are not drawn, and the tenant keys are illustrative. SHOPIFY PRODUCT SYNC THREE TRIGGERS · ONE NORMALISE AND UPSERT PATH · ONE STORE FROM SHOPIFY · ANY TENANT STORE PULL FULL WHOLE CATALOGUE PULL PARTIAL A SUBSET OF IT PUSH REAL TIME AS IT HAPPENS ONE STREAM 01 03 02 04 01 NORMALISE UPSERT KEY ONE STORE 01 03 02 04 TRIGGER DIFFERS, DESTINATION DOES NOT RELATIVE VOLUMES NOT SHOWN · TENANT KEYS ILLUSTRATIVE EVERY ROW KEYED TO THE TENANT IT CAME FROM A full pull, a subset, or a push from Shopify as it happens: past the throat they are one stream, and one store.

Shopify product sync

Data ingestion for Shopify product catalogues across a multi-tenant platform.

Model serving: every machine swaps to the new index in memory, and no request drops Along the top, several embedding builds are produced; one is evaluated on within-group versus cross-group similarity, then promoted through stage and prod in a versioned store on S3. From prod, one line runs down and splits into every serving machine: the new version is loaded into the process itself, not queried from a central store. Inside each machine the live index vN-1 runs as a solid bar and the new index vN loads beside it as a dashed outline. An accent vertical marks the instant all three swap, and the row of request ticks along the bottom runs straight through that line without a gap. Three machines are shown; the count is illustrative. MODEL SERVING VERSIONED EMBEDDING BUILDS · STAGE PROD hot reload BUILD vN EMBEDDING INDEX ONE BUILD PER REBUILD OF THE INDEX EVALUATE WITHIN-GROUP CROSS-GROUP S3 · VERSIONED STAGE PROD PROMOTE LOADED INTO EACH MACHINE MACHINE 01 MACHINE 02 MACHINE 03 INDEX vN-1 · SERVING LOADING INDEX vN · SERVING THREE SHOWN · ILLUSTRATIVE REQUESTS TO THE SERVING API SERVED BY vN-1 SERVED BY vN HOT RELOAD Each machine holds its own copy of the index in memory. Nothing is queried from a central store.

Embedding model serving

Every embedding build versioned through stage and prod, hot-reloaded without a restart.

The model that decides is the model being trained, one tick behind Four equal-width stages run left to right inside one 250 ms tick, measured end to end by the dimension line beneath them: data acquisition, model computation, online learning, and the order placement decision. The four are equal width because the source states their order and not the split of the budget between them. Hanging below model computation is the embedding it just produced, named but tagged with a price that has not resolved yet: the market has not moved. The accent traces that same embedding forward into online learning, landing there one tick later, once the price is known and it can finally be labelled. Online learning updates the same model computation calls next tick, in place - no retraining job sits outside this loop. TRADING SYSTEM MID-TO-HIGH FREQUENCY · NO OFFLINE RETRAINING JOB 01 DATA ACQUISITION 02 MODEL COMPUTATION 03 ONLINE LEARNING FROM LAST TICK 04 ORDER PLACEMENT DECISION EMBEDDING PRICE UNRESOLVED ONE TICK LATER 250 ms

Middle-to-high frequency trading system

All within 250 ms: data acquisition, model computation, and the order placement decision.

Factor ETL: a lightweight Airflow controller, and the AWS Batch compute it dispatches 460 jobs to Two tiers. Across the upper two thirds, ten soft regions of very different sizes and shapes, from a nine-by-nine block down to a single row of thirteen. Each is one DAG, and between them they hold 460 small round marks, one for every job. Thin lines run from region to region, several of them crossing: the dependencies that leave one DAG and land in another. This tier holds order and timing only. Along the bottom runs a second tier of a different kind - a long, evenly spaced row of identical square compute slots, marked AWS Batch, with no order to it at all - and between the two, a row of short parallel arrows drops straight down from the underside of the graph onto single slots: the controller dispatching one job at a time. The accent crosses both. It runs most of the width of the frame as one cross-DAG dependency, is ringed at the job it releases, and then turns straight down onto the slot where that job actually runs. From the end of the compute row an arrow reaches the factors database. The count of marks is exact; which jobs sit in which DAG is not, and the number of slots drawn is not a fleet size. FACTOR ETL LINEAGE GRAPH · CROSS-DAG DEPENDENCY, TIMEZONE-AWARE ONE DAG, ONE SCHEDULE 460 AIRFLOW JOBS AWS BATCH FACTORS DB CROSS-DAG DEPENDENCY

Factor ETL and data lineage

460 jobs with cross-DAG, timezone-aware dependencies, and a lineage graph on every run.