Xilin Zhu
ContactAvailable for work
← All work

Personal project · Independent full-stack project

AI Digital Twin

Built end to end, from API contract to production operations

2026.07 — PresentLive siteSource

A first-person AI twin whose only source of truth is material I reviewed and approved myself — with its safety and cost boundaries written as hard gates that refuse to start the service rather than as warnings.

Backend regression tests passing
72
Frontend component (lines)
2054
Frontend runtime dependencies
0
Supported languages
3

LiveWaking up

A first-person AI twin whose only source of truth is material I reviewed and approved myself.

Answers are generated by a language model from public material I approved. It can get things wrong — the CV and I are the authority.

Problem

A CV is static; a recruiter finishes reading it and has to guess the rest. But letting a language model speak on your behalf raises three real problems: it invents experience, it leaks things it should not, and it burns budget while nobody is watching.

Effectively all the engineering in this project answers those three.

Approach

  • Backend — FastAPI serving three APIs: profile, JSON chat, and SSE streaming; an adapter layer handles cancellation, retries, and rate limiting
  • Frontend — a native custom element with Shadow DOM, zero runtime dependencies, embeddable in any page with one script tag and one element
  • Two personas — professional and casual, each with its own isolated session; switching never bleeds history across
  • Three languages — Chinese, English, German, with per-tab session isolation, anonymous UUIDs, and no long-term cross-device memory
  • Security — XSS protection, safe rendering, strict production CORS
  • Deployment — Docker image running as non-root, dynamic port, health checks, graceful SIGTERM shutdown

Three engineering decisions worth explaining

1. Gates fail the boot, they do not warn

Production CORS accepts exactly two origins. A wildcard, a localhost origin, a missing entry, or an extra one all refuse to start. A missing approved profile refuses to start too.

Writing this kind of boundary as a warning is the same as not writing it — nobody reads yellow text in a log.

2. Observable, not nosy

The chat path emits one anonymous structured metric per request: allow-listed metadata, latency, failure class, and token usage. It records no questions, no answers, no conversation history, no identity, and no credentials. Raw conversation logging is forced off in production by a config gate, and a failure inside the metrics code is swallowed so it can never break the chat path.

Knowing whether the system works does not require reading what people said to it.

3. Zero-cost operations

A fixed output-token ceiling, a concurrency ceiling, a per-minute rate limit, a per-IP daily turn limit, and a per-session daily limit together hold the cost down. Free-tier sleep and cold starts are an accepted constraint; no paid resource is added just for monitoring.

In progress

A self-hosted inference path using llama.cpp with a quantised Qwen3-4B is already working locally. I am now training a small decoder-only GPT from scratch — not to replace a general-purpose model, but to walk the entire engineering chain from training through quantised export to serving behind the same OpenAI-compatible interface.

Production still defaults to the hosted API; no experiment switches it automatically.