Code LLM Training › Implementation: FIM Transformation
Language AI HandbookAll chapters Code LLM Training › Implementation: FIM TransformationOne section · Sections in this chapter8 / 13 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Now let's implement the fill-in-the-middle transformation. We'll apply it to a realistic code snippet and show the resulting training format for both the PSM and SPM variants.
# FIM special tokens
PRE_TOKEN = "<PRE>"
SUF_TOKEN = "<SUF>"
MID_TOKEN = "<MID>"
EOT_TOKEN = "<EOT>" # end of text
def fim_transform_psm(document: str, split_rate: float = 0.5) -> str:
"""
Apply PSM (Prefix-Suffix-Middle) FIM transformation.
With probability (1 - split_rate), return the document unchanged (causal LM format).
With probability split_rate, apply FIM transformation.
Returns the transformed document as a single string.
"""
if random.random() > split_rate:
return document # Standard causal LM training
lines = document.split("\n")
if len(lines) < 3:
return document # Too short to split meaningfully
# Choose random line boundaries for prefix/suffix split
split_line = random.randint(1, len(lines) - 2)
prefix = "\n".join(lines[:split_line])
middle = lines[split_line]
suffix = "\n".join(lines[split_line + 1 :])
# PSM format: PRE prefix SUF suffix MID middle EOT
return (
f"{PRE_TOKEN}{prefix}{SUF_TOKEN}{suffix}{MID_TOKEN}{middle}{EOT_TOKEN}"
)
def fim_transform_spm(document: str, split_rate: float = 0.5) -> str:
"""
Apply SPM (Suffix-Prefix-Middle) FIM transformation.
SPM puts the suffix before the prefix, which some research shows
improves infilling quality by conditioning generation on the suffix first.
"""
if random.random() > split_rate:
return document
lines = document.split("\n")
if len(lines) < 3:
return document
split_line = random.randint(1, len(lines) - 2)
prefix = "\n".join(lines[:split_line])
middle = lines[split_line]
suffix = "\n".join(lines[split_line + 1 :])
# SPM format: PRE SUF suffix MID prefix middle EOT
return f"{PRE_TOKEN}{SUF_TOKEN}{suffix}{MID_TOKEN}{prefix}\n{middle}{EOT_TOKEN}"# Apply FIM to a specific example to show the transformation
example_code = deduped_corpus[0]
# Force transformation for demonstration (override random)
random.seed(0)
transformed_psm = fim_transform_psm(example_code, split_rate=1.0)
random.seed(0)
transformed_spm = fim_transform_spm(example_code, split_rate=1.0)=== ORIGINAL CODE ===
import numpy as np
def compute_mean(values):
"""Compute the arithmetic mean of a list."""
return np.mean(values)
result = compute_mean([1, 2, 3, 4, 5])
print(result)
=== PSM TRANSFORMED ===
<PRE>
import numpy as np
def compute_mean(values):
"""Compute the arithmetic mean of a list."""
return np.mean(values)
<SUF>print(result)
<MID>result = compute_mean([1, 2, 3, 4, 5])<EOT>
...
=== SPM TRANSFORMED ===
<PRE><SUF>print(result)
<MID>
import numpy as np
def compute_mean(values):
"""Compute the arithmetic mean of a list."""
return np.mean(values)
result = compute_mean([1, 2, 3, 4, 5])<EOT>
...The PSM and SPM formats are both valid training examples. The model learns to recognize the <PRE>, <SUF>, and <MID> sentinel tokens as instructions for how to interpret the surrounding context.
# Build the final training batch with mixed FIM and causal LM examples
def build_training_batch(corpus: list[str], fim_rate: float = 0.5) -> list[str]:
"""
Transform each document with probability fim_rate using FIM.
The remaining documents are kept in standard causal LM order.
"""
batch = []
for doc in corpus:
if random.random() < fim_rate:
# Randomly choose PSM or SPM
if random.random() < 0.5:
batch.append(fim_transform_psm(doc, split_rate=1.0))
else:
batch.append(fim_transform_spm(doc, split_rate=1.0))
else:
batch.append(doc) # Standard causal LM
return batch
random.seed(42)
training_batch = build_training_batch(deduped_corpus, fim_rate=0.5)Training batch composition: FIM examples: 5 (71%) Causal LM examples: 2 (29%) Total: 7
The training batch is now a mix of FIM and standard causal LM examples. The model learns to handle both: standard left-to-right completion from prefix-only contexts, and infilling when prefix and suffix are both present.