# Understanding the Two-Stage Generation Pipeline in OpenMAIC: From Raw Material to Interactive Lessons

> Explore OpenMAIC's two-stage generation pipeline. Learn how LLM planning transforms documents into interactive lessons with quizzes, simulations, and voice-overs.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: internals
- Published: 2026-09-12

---

**OpenMAIC converts PDFs, Word documents, and multimedia files into structured lessons using a two-stage generation pipeline that first creates a pedagogical outline via LLM planning, then renders each section into interactive scenes with quizzes, simulations, and voice-overs.**

The OpenMAIC platform transforms static learning materials into dynamic, AI-generated courses through a sophisticated two-stage generation pipeline. This architecture cleanly separates high-level instructional planning from low-level content production, enabling modular customization and scalable lesson creation. By leveraging large language models for both pedagogical structure and scene composition, the pipeline delivers complete interactive lessons according to the THU-MAIC/OpenMAIC source code.

## How the Two-Stage Generation Pipeline Works

The pipeline processes raw educational content through five distinct phases, orchestrated by the `@openmaic/sdk` package and executed asynchronously.

1. **Input Extraction** – The `@openmaic/storage` package handles file ingestion, using specialized extractors to convert PDFs, PowerPoints, Word documents, images, and audio/video into plain text or structured data for downstream processing.

2. **Outline Generation** – An LLM-driven planner analyzes the extracted content and produces a hierarchical teaching flow (chapters → sections → topics) stored as a structured lesson outline.

3. **Scene Generation** – Each node in the outline expands into a concrete "scene"—whether a slide, quiz, interactive simulation, or project-based-learning (PBL) activity—complete with UI assets and narration scripts.

4. **Asset Rendering** – Generated media (images, audio, video) are stored via `@openmaic/storage` HTTP contracts and linked to their respective scenes.

5. **Async Job & Polling** – The entire process runs as a background job. Clients poll the job status until the complete lesson (outline + scenes) becomes available.

The high-level description of this workflow appears in [`README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/README.md) at lines 708-715.

## Stage 1: Outline Generation

The first stage focuses on **pedagogical planning**. The system feeds extracted text into a planner prompt defined in `packages/@openmaic/generation/prompts-pbl/planner-system.md`. This LLM prompt instructs the model to analyze the source material, identify logical teaching progressions, and output a hierarchical outline.

The outline serves as the architectural blueprint for the lesson, determining chapter boundaries, section ordering, and topic depth. By isolating planning from production, developers can swap planner models or fine-tune the system prompt in [`planner-system.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/planner-system.md) without affecting scene rendering logic.

## Stage 2: Scene Generation

The second stage handles **UI material creation**. For every node in the outline generated during Stage 1, the pipeline invokes specialized scene prompts (e.g., `slide-content`, `quiz-content`, `simulation-content`) located in `packages/@openmaic/generation/templates/`.

For example, the template at `packages/@openmaic/generation/templates/slide-content/user.md` drives the expansion of outline topics into concrete slide decks, including markdown content, whiteboard drawings, and voice-over narration scripts. This stage produces the interactive elements students actually see, from multiple-choice quizzes to hands-on PBL simulations.

## Implementation: Using the OpenMAIC SDK

You can trigger both stages programmatically via the TypeScript SDK or CLI. The `generateLesson` method in `packages/@openmaic/sdk/src/client.ts` orchestrates the full two-stage pipeline asynchronously.

```typescript
// 1️⃣ Load the SDK
import { OpenMAIC } from '@openmaic/sdk';

// 2️⃣ Create a client
const client = new OpenMAIC({
  baseURL: 'http://localhost:3000', // self-hosted server
  apiKey: 'sk-YourAccessToken',      // Store in .env.local
});

// 3️⃣ Submit a generation job (runs both stages)
const job = await client.generateLesson({
  files: ['./materials/physics.pdf'],
  // Optional: force only outline or only scenes
  // stage: 'outline' | 'scenes'
});

// 4️⃣ Poll until completion
while (!job.done) {
  await new Promise(r => setTimeout(r, 2000));
  await job.refresh();
}

// 5️⃣ Access results
console.log('Outline:', job.result.outline);
console.log('Scenes:', job.result.scenes);

```

For command-line usage, the `@openmaic/sdk` package provides a CLI wrapper that handles authentication, file upload, and job polling automatically:

```bash

# Using the CLI

npx openmaic generate \
  --files ./materials/biology.docx \
  --output lesson.json

```

Both interfaces abstract the underlying asynchronous job mechanics, returning finalized lesson structures containing both the pedagogical outline and rendered scene assets.

## Architecture Benefits of the Two-Stage Design

Separating outline planning from scene generation delivers specific engineering advantages:

- **Modular LLM Integration** – Developers can replace the planner model or scene generators independently by modifying [`planner-system.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/planner-system.md) or scene templates without cross-stage dependencies.

- **Custom Extractor Support** – The `@openmaic/storage` package accepts plugins for new file formats, allowing the pipeline to ingest proprietary content types without altering generation logic.

- **Granular Caching** – Because outlines and scenes are distinct artifacts, the system can cache generated outlines and re-render only specific scenes when UI templates update.

- **Async Scalability** – The job-based execution model supports long-running generation tasks (video rendering, complex simulations) without blocking client requests.

## Summary

- The **two-stage generation pipeline in OpenMAIC** separates pedagogical planning from content production through distinct Outline and Scene stages.
- **Stage 1** uses the planner prompt at `packages/@openmaic/generation/prompts-pbl/planner-system.md` to generate hierarchical lesson structures from extracted text.
- **Stage 2** expands each outline node into interactive scenes using templates like `packages/@openmaic/generation/templates/slide-content/user.md`.
- The `generateLesson` method in `packages/@openmaic/sdk/src/client.ts` orchestrates both stages as an async job, while `@openmaic/storage` handles file extraction and asset persistence.
- This architecture enables independent customization of planners, scene types, and extractors while maintaining clean separation of concerns.

## Frequently Asked Questions

### What file formats does the OpenMAIC two-stage generation pipeline support?

The pipeline accepts PDFs, Word documents (DOCX), PowerPoint presentations (PPTX), images, audio, and video files. The `@openmaic/storage` package converts these into structured text via specialized extractors before feeding them into the outline generation stage.

### How does the Outline stage differ from the Scene stage?

The **Outline stage** performs high-level pedagogical planning using the planner prompt in `packages/@openmaic/generation/prompts-pbl/planner-system.md` to create chapter and section hierarchies. The **Scene stage** handles low-level UI material creation, transforming each outline node into concrete interactive elements like slides or quizzes using scene-specific templates.

### Can I customize the LLM prompts used in the generation pipeline?

Yes. Developers can modify the system prompts located in `packages/@openmaic/generation/prompts-pbl/` for the outline stage or templates in `packages/@openmaic/generation/templates/` for scene generation. This allows fine-tuning of teaching style, output format, and interaction types without changing the underlying SDK code.

### Is the two-stage pipeline synchronous or asynchronous?

The pipeline runs **asynchronously**. When you invoke `client.generateLesson()`, the SDK returns a job object that you poll until completion. This design accommodates long-running operations like video generation and complex simulation rendering without blocking the client application.