Skip to main content

5.5 Multi-Stage Generation Pattern

AI-Generated Content

AI-generated content may contain errors. Always verify against official sources.

5.5 Multi-Stage Generation Pattern

Key Concepts: Extract → Transform → Generate → Validate pipeline design

Official Docs: LangChain LCEL


The Pattern

The Extract → Transform → Generate → Validate (ETGV) pattern is a production-grade approach to reliable document generation.

┌──────────────────────────────────────────────┐
│ INPUT: Raw document / data │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│ STAGE 1: EXTRACT │
│ Pull structured facts from unstructured input │
│ Output: typed schema (Pydantic) │
└──────────────────────────────────────────────┘
↓ validate
┌──────────────────────────────────────────────┐
│ STAGE 2: TRANSFORM │
│ Enrich / normalise / augment the extracted data │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│ STAGE 3: GENERATE │
│ Produce the final document from clean inputs │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│ STAGE 4: VALIDATE │
│ Verify output quality before returning │
└──────────────────────────────────────────────┘

Complete Example: Performance Review Generator

from openai import OpenAI
from pydantic import BaseModel, Field
import json

client = OpenAI()

# ─── Stage 1: Extract ───
class EmployeeData(BaseModel):
name: str
role: str
achievements: list[str]
areas_for_improvement: list[str]
attendance_percent: float = Field(ge=0, le=100)

def stage1_extract(raw_notes: str) -> EmployeeData:
resp = client.beta.chat.completions.parse(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Extract employee review data as structured JSON."},
{"role": "user", "content": raw_notes},
],
response_format=EmployeeData,
temperature=0,
)
return resp.choices[0].message.parsed

# ─── Stage 2: Transform ───
def stage2_transform(emp: EmployeeData) -> dict:
"""Enrich with computed fields."""
return {
**emp.model_dump(),
"performance_score": len(emp.achievements) * 10 - len(emp.areas_for_improvement) * 5,
"rating": "Exceeds" if len(emp.achievements) >= 4 else "Meets" if len(emp.achievements) >= 2 else "Below",
}

# ─── Stage 3: Generate ───
def stage3_generate(enriched: dict) -> str:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Write a professional performance review paragraph. Be specific, balanced, and constructive."},
{"role": "user", "content": json.dumps(enriched)},
],
temperature=0.4,
max_tokens=300,
)
return resp.choices[0].message.content

# ─── Stage 4: Validate ───
def stage4_validate(review_text: str, emp_name: str) -> str:
if emp_name.split()[0].lower() not in review_text.lower():
raise ValueError(f"Review does not mention employee name: {emp_name}")
if len(review_text.split()) < 50:
raise ValueError("Review is too short (< 50 words)")
return review_text

# ─── Full Pipeline ───
def generate_review(raw_notes: str) -> str:
emp = stage1_extract(raw_notes)
enriched = stage2_transform(emp)
review = stage3_generate(enriched)
return stage4_validate(review, emp.name)

print(generate_review("""
Sarah Al-Ahmad, Product Manager. Delivered 3 product launches on time.
Won Customer Satisfaction Award Q2. Mentored 2 junior PMs.
Needs to improve data-driven decision making and stakeholder communication.
Attendance: 96%.
"""))

Common Mistakes

Common Mistakes
  1. Skipping Stage 1 validation — if extraction produces wrong data types, all downstream stages fail in unpredictable ways.
  2. Generating before transforming — always clean and normalise data before passing it to the generation step.
  3. No Stage 4 quality gate — without validation, silent quality failures reach the end user.
  4. Not logging intermediate outputs — in production, log each stage’s output to diagnose which step caused a regression.

Quick Quiz

Test Your Understanding

Q1. Why validate after extraction (Stage 1) rather than just before generation (Stage 3)?
A1. Catching schema errors early prevents bad data from propagating into enrichment and generation, making debugging much easier.

Q2. What is the purpose of the Transform stage?
A2. To clean, normalise, and enrich the extracted structured data before feeding it to the generator — separating data preparation from content generation.

Q3. What types of checks should Stage 4 validation perform?
A3. Format checks (length, structure), content checks (key entities mentioned), and business-rule checks (specific requirements unique to the domain).


Student Exercise

Exercise 5.5 — Report generator
Build a 4-stage ETGV pipeline that takes raw cricket scorecard data (e.g., player names, runs, wickets) and generates a structured match report including: (1) extract player stats, (2) compute derived metrics (strike rate, economy rate), (3) generate a narrative summary, (4) validate the summary mentions the top scorer and bowler by name.


Further Reading

Next Chapter → Chapter 6: Validation