Tag: training

From Data Factories to Dynamic Systems: The Evolution of LLM Orchestration

For a few years, the recipe for a capable language model resembled manufacturing: gather or synthesize large volumes of training rows, run gradient descent, ship the weights. Magpie is a clean example of that philosophy. By feeding an aligned model nothing but its own pre-query template, researchers got it to generate millions of plausible user instructions, then answer them — an assembly line that produced alignment data at scale with no human in the loop. The model was both the factory and the raw material.

That approach worked, and it still matters. But the center of gravity in LLM systems has moved. Capability is no longer something you bake entirely into weights at training time; it is increasingly assembled at runtime, through typed message formats, function schemas, and interoperability standards like the Model Context Protocol. This post traces that shift — from static data production to dynamic composition — and maps out what it means for anyone building software on top of these models. It picks up where my earlier piece on Harmony and training formats left off: if channels are the interface layer between weights and runtime, the question here is how that interface came to carry more of the system’s intelligence than the training corpus itself.

The Data Factory Era and Its Ceiling

Static dataset generation solved a real bottleneck. Human-written instruction data was scarce, expensive, and legally fraught, and techniques like Magpie, Self-Instruct, and Evol-Instruct showed that models could manufacture their own curriculum. The Magpie method — exploiting the autoregressive template so the model completes the “user” side of a conversation it was never given — raises a question worth sitting with: how much conversational structure do post-trained weights already contain, waiting to be extracted?

The ceiling, however, is built into the method. A synthesized corpus is a snapshot: its distribution is frozen the moment training ends. Every new API, coding convention, or enterprise system the model should interact with would require fresh rows and fresh gradient steps. Facts and behaviors also get entangled — teach a model about a specific weather API by memorization, and the knowledge rots the day the API changes. The factory could produce volume; it could not produce currency or context.

The Escape Route, Stage by Stage

The escape route emerged in stages, and the sequence is easier to follow if each stage is read as an answer to the previous one’s open problem.

Stage one: act by prompting. ReAct interleaved reasoning traces with actions expressed as plain text — the model wrote “Action: search[…]” and a wrapper script parsed it, ran the query, and pasted the result back into the prompt. This proved a base model could operate external systems with no special training at all.

The open problem: everything hinged on heuristic parsing of free-form text, which broke whenever the model phrased an action differently.

Stage two: learn the habit from synthesized data. Toolformer had the model annotate its own training text with candidate API calls, kept the insertions that measurably improved next-token prediction, and fine-tuned on the result. It is a transitional artifact — a data-factory technique in service of a dynamic behavior — and it made tool invocation a learned reflex rather than a prompting trick.

The open problem: the tool set was fixed at training time, so every new capability meant another training run.

Stage three: pass the tools in at runtime. Native function calling moved the schemas into the request itself. The model reads JSON descriptions of available functions in context and emits arguments that validate against them. What the weights retain is a structural pattern — read schema, select function, construct arguments — which is why a model fine-tuned on a few thousand examples can call APIs it has never seen.

The open problem: output still arrived as one undifferentiated stream, leaving the runtime to guess whether a given blob of JSON was a call, a draft, or an answer.

Stage four: type the conversation itself. ChatML gave messages explicit roles and boundaries; Harmony extended this with output channels — analysis for internal reasoning, commentary for actions bound to the runtime, final for the user-facing answer. Ambiguity that stage three left to heuristics became a typed contract the serving stack can rely on.

The open problem: every model vendor and every capability provider still wired their integrations one-off.

Stage five: standardize the boundary. MCP defines how a client discovers tools, resources, and prompt templates from independent servers at connection time. Nothing about a specific database, ticketing system, or search index needs to live in the weights; the capability arrives with the connection, described in text the model already knows how to read. Integration stops being a training problem and becomes a configuration problem.

What LSP Taught MCP

Stage five has a precedent in developer tooling. Before the Language Server Protocol, every editor needed a bespoke integration with every programming language — an M×N growth in glue code. LSP collapsed it to M+N with one contract: any editor speaking the protocol gets completions, diagnostics, and refactoring from any compliant language server.

MCP applies the same compression to models and capabilities, and the analogy runs deeper than architecture. LSP succeeded because it let editors and compilers evolve on separate schedules; the protocol boundary is what made independent progress possible. The same decoupling is what lets a tool server built today work with a model released next year.

The Breakdown of Monolithic Training

Seen through this lens, training itself has decomposed into layers with distinct jobs. Pretraining supplies linguistic and world priors. Instruction tuning teaches the conventions of roles and turns. A further fine-tuning pass teaches the grammar of action — when to act, how to construct arguments, how to integrate returned results. Channelized formats teach the model to separate deliberation from invocation from presentation.

None of these layers tries to be the whole system anymore. The monolith — one corpus meant to instill every fact and behavior — has given way to a division of labor: weights learn transferable patterns, while the runtime supplies the specifics of the moment. One way to compress this: training provides the grammar, the environment provides the vocabulary. Synthetic data generation still has a role, but its target changed. You generate examples to sharpen the pattern — schema reading, argument construction, result integration — not to enumerate the world.

A Conceptual Map: How Models Actually Write Code

Code generation makes the dynamic view concrete, because correctness is externally checkable. Picture the system as four concentric layers. At the core sit the weights, trained on mixed text-and-code corpora — they contribute priors about syntax, idiom, and likely program structure. Around them sits the format layer: channels and schemas that let planning, action, and presentation travel as distinct, machine-readable streams. Around that sits the runtime loop: compilers, test runners, linters, static analyzers, and protocol-connected services the model can invoke. The outermost layer is feedback — execution results flowing back into context, reshaping the next generation step.

A coding agent drafts a plan in its reasoning lane, requests a test run through the action lane, receives a traceback, and revises. Functional correctness emerges from this circulation between model and environment, not from a hidden verification oracle inside the parameters. The training corpus made the first draft plausible; the loop makes the final artifact correct. That distinction is the argument of this post in miniature: a model that writes working software is not reciting its dataset — it is participating in a feedback system whose most important components live outside the network.

Actionable Insights for Developers

First, treat schemas as prompts. The descriptions in your function and server definitions are read by the model at inference time; an afternoon spent on precise parameter docs often beats a week of fine-tuning. Second, keep one model on the hot path. Channels exist so that a single inference stream can serve the UI, the executor, and the logger — add model hops only when a validator or router earns its latency.

Third, log per lane. When reasoning, actions, and answers are typed separately, you can evaluate structural validity — did the arguments parse and validate? — independently from answer quality, and you can mask or weight lanes differently if you later train on your own traces. Fourth, aim synthetic generation at patterns rather than facts: Magpie-style pipelines work well for teaching argument construction and result integration, and poorly for anything that changes monthly. Finally, build against open contracts rather than vendor endpoints — a capability exposed through a standard protocol survives model swaps; a bespoke integration does not.

Toward Circular, Modular — and Legible — Systems

The endpoint of this evolution is not the death of the data factory but its relocation. Agent deployments now generate the artifact that factories once had to fabricate: complete, structured traces of plans, invocations, results, and outcomes. Filter those traces by success, and they become training rows; fine-tune on them, and the improved weights produce better traces. The pipeline has bent into a circle, with the production environment as its own curriculum generator. Typed lanes, schema-described capabilities, and protocol boundaries make each component of that circle — weights, runtime, servers, evaluators — replaceable on its own schedule, the way LSP let editors and compilers evolve independently.

There is a newer force reshaping the training side of this loop: research into what happens inside the network, at the level of activations. Sparse autoencoders showed that the hidden states of a transformer can be decomposed into thousands of individually interpretable features — concepts, personas, syntactic roles — as demonstrated in early dictionary-learning work and scaled to production models in Anthropic’s monosemanticity research. In parallel, representation engineering and activation addition showed that behavior can be shifted by adding directions in that feature space at inference time — no gradient steps required. Read against the arc of this post, that is a familiar move: yet another capability migrating from the weights to the runtime.

This line of work is starting to change how training decisions get made. OpenAI’s study of persona features and emergent misalignment traced a fine-tuning failure — narrow training on insecure code producing broadly misaligned behavior — to identifiable directions in the model’s internal representations, then used that diagnosis to design a small corrective fine-tune. Anthropic’s attribution graphs trace multi-step computations through a model, offering a way to check whether a fine-tune changed the mechanism or merely the surface behavior. The practical pattern emerging from both: inspect the feature space before and after training, and let what you find decide what to retrain, what to steer, and what to leave alone.

The field is still early here, and the open questions are the interesting part. Do features stay stable across fine-tunes, so that a monitor built today survives next quarter’s training run? Can feature-level checks run cheaply enough to sit inside the agent loop itself, alongside the compilers and test runners? And if conversation formats gave us typed channels for text, will some future contract expose internal state the same way? The trajectory of the last few years suggests a consistent direction: systems built from parts that are separately trainable, separately swappable, and — increasingly — separately inspectable. The teams that internalize this will spend less time manufacturing static corpora and more time designing the contracts and feedback loops through which their systems teach themselves.

Sizing an LLM for GPU memory

When choosing the EC2 instance for a Large Language Model, one of the first constraints is whether the model will fit in the GPU memory of an instance.

Given a choice of a model, the decisions roughly follow this path –

Model -> Training/Inferencing -> Technique (choice of optimization) -> Memory requirement -> Instance requirement -> Instance availability -> smaller instance or more optimization or distributed training.

Some extreme optimizations are possible such as QLora for Inferencing . See the blog How to fit a layer in memory at a time https://huggingface.co/blog/lyogavin/airllm . However many use cases do not want any sacrifices in accuracy.

Distributed training by splitting the model against smaller instances is another possibility. A discussion is here – https://siboehm.com/articles/22/pipeline-parallel-training

Here’s a listing of different GPU instance types with a column for GPU Memory (GiB) on one page to facilitate instance comparisons.

EC2 G3 Instance Details
NameGPUsvCPUMemory (GiB)GPU Memory (GiB)Price/hr* (Linux)Price/hr* (Windows)1-yr Reserved Instance Effective Hourly* (Linux)3-yr Reserved Instance Effective Hourly* (Linux)
g3s.xlarge1430.58$0.75
$0.93
$0.525$0.405
g3.4xlarge1161228$1.14$1.876$0.741$0.538
g3.8xlarge23224416$2.28$3.752$1.482$1.076
g3.16xlarge46448832$4.56$7.504$2.964$2.152
EC2 G4 Instance details
 Instance SizeGPUvCPUsMemory (GiB)Instance Storage (GB)Network Bandwidth (Gbps)EBS Bandwidth (Gbps)On-Demand Price/hr*1-yr Reserved Instance Effective Hourly* (Linux)3-yr Reserved Instance Effective Hourly* (Linux)

G4dn

Single GPU VMsg4dn.xlarge14161 x 125 NVMe SSDUp to 25Up to 3.5$0.526$0.316$0.210
g4dn.2xlarge18321 x 225 NVMe SSDUp to 25Up to 3.5$0.752$0.452$0.300
g4dn.4xlarge116641 x 225 NVMe SSDUp to 254.75$1.204$0.722$0.482
g4dn.8xlarge1321281 x 900 NVMe SSD509.5$2.176$1.306$0.870
g4dn.16xlarge1642561 x 900 NVMe SSD509.5$4.352$2.612$1.740
           
Multi GPU VMsg4dn.12xlarge4481921 x 900 NVMe SSD509.5$3.912$2.348$1.564
g4dn.metal8963842 x 900 NVMe SSD10019$7.824$4.694$3.130

G4ad

Single GPU VMsg4ad.xlarge14161 x 150 NVMe SSDUp to 10Up to 3$0.379$0.227$0.178
g4ad.2xlarge18321 x 300 NVMe SSDUp to 10Up to 3$0.541$0.325$0.254
g4ad.4xlarge116641 x 600 NVMe SSDUp to 10Up to 3$0.867$0.520$0.405
           
Multi GPU VMsg4ad.8xlarge2321281 x 1200 NVMe SSD153$1.734$1.040$0.810
g4ad.16xlarge4642561 x 2400 NVMe SSD256$3.468$2.081$1.619
EC2 G5 instance details
 Instance SizeGPUGPU Memory (GiB)vCPUsMemory (GiB)Storage (GB)Network Bandwidth (Gbps)EBS Bandwidth (Gbps)On Demand Price/hr*1-yr ISP Effective Hourly (Linux)3-yr ISP Effective Hourly (Linux)
Single GPU VMsg5.xlarge1244161×250Up to 10Up to 3.5$1.006$0.604$0.402
g5.2xlarge1248321×450Up to 10Up to 3.5$1.212$0.727$0.485
g5.4xlarge12416641×600Up to 258$1.624$0.974$0.650
g5.8xlarge124321281×9002516$2.448$1.469$0.979
g5.16xlarge124642561×19002516$4.096$2.458$1.638
            
Multi GPU VMsg5.12xlarge496481921×38004016$5.672$3.403$2.269
g5.24xlarge496963841×38005019$8.144$4.886$3.258
g5.48xlarge81921927682×380010019$16.288$9.773$6.515
EC2 G6 instance details
 Instance SizeGPUGPU Memory (GB)vCPUsMemory (GiB)Storage (GB)Network Bandwidth (Gbps)EBS Bandwidth (Gbps)On Demand Price/hr*1-yr ISP Effective Hourly (Linux)3-yr ISP Effective Hourly (Linux)
Single GPU VMs          g6.xlarge1244161×250Up to 10Up to 5$0.805$0.499$0.342
g6.2xlarge1248321×450Up to 10Up to 5$0.978$0.606$0.416
g6.4xlarge12416641×600Up to 258$1.323$0.820$0.562
g6.8xlarge124321282×4502516$2.014$1.249$0.856
g6.16xlarge124642562×9402520$3.397$2.106$1.443
Gr6 instances with 1:8 vCPU:RAM ratio
gr6.4xlarge124161281×600Up to 258$1.539$0.954$0.654
gr6.8xlarge124322562×4502516$2.446$1.517$1.040
            
Multi GPU VMsg6.12xlarge496481924×9404020$4.602$2.853$1.955
g6.24xlarge496963844×9405030$6.675$4.139$2.837
g6.48xlarge81921927688×94010060$13.35$8.277$5.674
EC2 G6e instances
Instance SizeGPUGPU Memory (GiB)  vCPUsMemory(GiB)Storage (GB)  Network Bandwidth (Gbps)  EBS Bandwidth (Gbps)
g6e.xlarge148432250Up to 20Up to 5
g6e.2xlarge148864450Up to 20Up to 5
g6e.4xlarge14816128600208
g6e.8xlarge148322569002516
g6e.16xlarge1486451219003520
g6e.12xlarge419248384380010020
g6e.24xlarge419296768380020030
g6e.48xlarge83841921536760040060
EC2 P3 instance details
Instance SizeGPUs – Tesla V100GPU Peer to PeerGPU Memory (GB)vCPUsMemory (GB)Network BandwidthEBS BandwidthOn-Demand Price/hr*1-yr Reserved Instance Effective Hourly*3-yr Reserved Instance Effective Hourly*
p3.2xlarge1N/A16861Up to 10 Gbps1.5 Gbps$3.06$1.99$1.05
p3.8xlarge4
NVLink643224410 Gbps7 Gbps$12.24$7.96$4.19
p3.16xlarge8NVLink1286448825 Gbps14 Gbps$24.48$15.91$8.39
p3dn.24xlarge8NVLink25696768100 Gbps19 Gbps$31.218$18.30$9.64
EC2 P4 instance details
Instance SizevCPUsInstance Memory (GiB)GPU – A100GPU memoryNetwork Bandwidth (Gbps)GPUDirect RDMAGPU Peer to PeerInstance Storage (GB)EBS Bandwidth (Gbps)On-demand Price/hr1-yr Reserved Instance Effective Hourly *3-yr Reserved Instance Effective Hourly *
p4d.24xlarge9611528320 GB
HBM2
400 ENA and EFAYes600 GB/s NVSwitch8 x 1000 NVMe SSD19$32.77$19.22$11.57
p4de.24xlarge (preview)9611528640 GB
HBM2e
400 ENA and EFAYes600 GB/s NVSwitch8 x 1000 NVMe SSD19$40.96$24.01$14.46
EC2 P5 instance details
Instance SizevCPUInstance Memory (TiB)GPU – H100GPU  MemoryNetwork BandwidthGPUDirectRDMAGPU Peer to PeerInstance Storage (TB)EBS Bandwidth (Gbps)
p5.48xlarge1928640 GB HBM33200 Gbps EFAv2Yes900 GB/s NVSwitch8 x 3.84 NVMe SSD80 
EC2 P5e instance details
Instance SizevCPUsInstance Memory (TiB)GPUGPU memoryNetwork Bandwidth (Gbps)GPUDirect RDMAGPU Peer to PeerInstance Storage (TB)EBS Bandwidth (Gbps)
p5e.48xlarge19228 x NVIDIA H2001128 GB
HBM3e
3200 Gbps EFAYes900 GB/s NVSwitch8 x 3.84 NVMe SSD80

Relevant links

P5e and P5en announcement (update Sep’24). https://aws.amazon.com/blogs/machine-learning/amazon-ec2-p5e-instances-are-generally-available/

https://en.wikipedia.org/wiki/List_of_Nvidia_graphics_processing_units

Use of Triton and NIM to make use of GPU memory across multiple GPUs on an instance –

https://github.com/aws-samples/amazon-eks-machine-learning-with-terraform-and-kubeflow

https://aws.amazon.com/blogs/hpc/deploying-generative-ai-applications-with-nvidia-nims-on-amazon-eks

FP4 and four bit integer quantization, and QLoRA

Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA at https://huggingface.co/blog/4bit-transformers-bitsandbytes

[2305.14152] Memory-Efficient Fine-Tuning of Compressed Large Language Models via sub-4-bit Integer Quantization

Note: Performance is not just about GPU memory but also network bandwidth which is needed to load the large models especially for a platform serving multiple models.

When comparing the importance of high memory bandwidth between training and inference for Large Language Models (LLMs), it is generally more critical for training. Here’s why:

1. Training LLMs

  • Data Movement: Training LLMs involves frequent data movement between the GPU memory and the processing units. Each training iteration requires loading large batches of data, performing extensive matrix multiplications, and updating weights, all of which are memory-intensive operations.
  • Backward Pass: During the training phase, the backward pass (gradient computation and backpropagation) is highly memory bandwidth-intensive. The gradients of each layer are computed and propagated back through the network, requiring significant memory access.
  • Parameter Updates: High memory bandwidth is essential to handle the large volume of data being read and written during the parameter updates across multiple layers, especially in very deep models.
  • Larger Models and Datasets: Training large models like GPT-3 or GPT-4 involves massive datasets and millions (or even billions) of parameters, leading to a substantial demand for memory bandwidth.

2. Inferencing of LLMs:

  • Data Movement: During inference, the primary task is to process input data and generate outputs, which involves reading the model parameters and performing computations. While this still requires good memory bandwidth, the demands are generally lower compared to training.
  • No Backpropagation: Inference does not involve the backward pass or parameter updates, significantly reducing the need for continuous memory writes. The absence of gradient computations and updates reduces the overall memory bandwidth requirements.
  • Smaller Batch Sizes: Inference typically operates on smaller batch sizes compared to training, further reducing the demand for memory bandwidth.
  • Optimizations: Techniques such as model quantization and optimized inference runtimes (like TensorRT) can reduce the memory bandwidth required during inference by optimizing how data is accessed and processed.