Zstem

LLM Training & Context Engineering Pipeline

by Zstem · published 2026-07-23 · 0 forks

EventsArchitectureDocsSequenceWorkflowaimicroservices

End-to-end pipeline covering data ingestion, context engineering (RAG, prompt/system-prompt management), model training/fine-tuning, and inference/serving.

Open & fork this on Zstem →
Data Ingestion & PrepContext EngineeringTraining & Fine-TuningInference & ServingObservability & Feedb…Raw Corpus (S3)ETL / Clean & DedupCurated Dataset (S3)Embedding ModelVector StoreRAG PipelinePrompt & System Promp…Context AssemblerTraining / Fine-Tune …Model RegistryEval HarnessAPI GatewayInference OrchestratorLLM EndpointGuardrailsMetrics & LogsFeedback StreamClient AppLLM Training & Context Engineering Pipeli…zstem.design

Architecture

Workflow

Event flow

Sequence

Participants: Request Queue, Inference Orchestrator, Context Assembler, RAG / Vector Store, Guardrails, LLM Endpoint, Tool / Action Layer, Session Memory, Metrics & Feedback

Observability, Prompt Versioning, Quality & Fault Tolerance

Observability, Prompt Versioning, Quality & Fault Tolerance

Cross-cutting design for the inference path. Pairs with the event-flow diagram (telemetry producers → channels → consumers) and the sequence diagram (agentic loop).

LLM Observability

Every request carries a traceId (correlation ID assigned at the API Gateway) propagated through orchestrator → assembler → RAG → model → tools, so a single trace reconstructs the full agentic loop.

Capture per span:

Latency — end-to-end and per hop (retrieval, each model call, each tool call).

Tokens — input/output counts per call, aggregated per request and per tenant.

Retrieval quality signals — chunks retrieved, rerank scores, hit rate.

Agentic shape — number of reasoning iterations, tool calls per request, loop-termination reason.

Model & prompt identity — modelId + promptVersion on every span, so metrics slice by version.

Emitted as inference.trace to the telemetry stream, fanning out to the observability platform (dashboards, distributed tracing) and cost/latency analytics (token spend + SLO tracking per tenant/model). Use OpenTelemetry semantics so traces, metrics, and logs share the same IDs.

Prompt & System-Prompt Versioning

Every prompt and system prompt is content-addressed: store a systemPromptHash and a human-readable promptVersion (e.g. semver or name@rev).

The Prompt Version Registry holds each version plus its aggregated quality scores. Versions are immutable once published; a change is a new version, never an in-place edit.

Every inference.trace and llm.completion.logged event stamps the promptVersion used, so quality and cost are always attributable to an exact prompt revision.

Promotion is eval-gated: a new version must beat the incumbent on the eval suite before it can be marked production. Rollout can be staged (canary %). Rollback = re-point the alias to the previous version — instant, no redeploy.

LLM Call Quality

Two loops:

Online — sampled llm.completion.logged pairs scored in near-real-time by the Quality Eval Service (LLM-as-judge + heuristics: groundedness against retrieved context, relevance, format compliance, toxicity/safety). User up/down feedback is joined on traceId to correlate automated scores with real satisfaction.

Offline — a curated eval set is run against each candidate prompt/model version in CI before promotion (the eval harness in the architecture diagram).

Drift detection — response and embedding distributions compared against a baseline; statistically significant drift raises a signal even when individual completions look fine.

Regression or drift signals route to alerting/on-call and feed back into the retrain/curation loop.

Fault Tolerance for External API Calls

External dependencies (LLM endpoint, vector store, embedding model, third-party tools) fail independently. Each call site applies a layered strategy; every failure emits external.call.failed for observability.

Per-call resilience

Timeouts — aggressive, tuned per dependency (a slow tool must not stall the whole request). Always bounded; never an unbounded await.

Retries — only on transient/idempotent failures (timeout, 5xx, rate_limit), with exponential backoff + jitter and a hard attempt cap. No retries on 4xx validation errors.

Circuit breaker — per dependency. After a failure-rate threshold the breaker opens, fails fast for a cool-down window, then half-opens to probe recovery. Prevents retry storms and cascading failure.

Bulkheads — separate connection/concurrency pools per dependency so a saturated tool API can't exhaust capacity needed for model calls.

Rate-limit handling — honor Retry-After; token-bucket client-side throttling to stay under provider quotas.

Graceful degradation (fallback ladder)

LLM endpoint — fail over to a secondary model / region / provider; degrade to a smaller/cheaper model under load.

Vector store — on retrieval failure, proceed with reduced context (model answers from parametric knowledge) rather than failing the request; flag lower-confidence in the trace.

Tools — a failed tool returns a structured error observation into the agent loop so the model can adapt or answer without it, instead of aborting.

Guardrails — fail closed (block) on the safety path; never fail open.

Request integrity

Idempotency keys on inbound requests so client retries don't double-charge tokens or duplicate side effects.

Loop bounds — max reasoning iterations and a total wall-clock budget on the agentic loop to prevent runaway cost/latency; exceeding the budget returns the best answer so far or a graceful timeout.

Dead-letter queue — requests that exhaust retries land in a DLQ for inspection/replay rather than being silently dropped.

Design decisions to revisit

LLM-as-judge adds cost/latency — decide sample rate (e.g. 100% offline, 1–5% online).

Multi-provider failover implies prompt portability — keep prompts model-agnostic or maintain per-model variants.

Circuit-breaker thresholds and timeout budgets are workload-specific; start conservative and tune from external.call.failed data.

Open & fork this on Zstem →