# How MoneyPrinterTurbo Generates Video Scripts with LLMs: Architecture and Implementation

> Discover how MoneyPrinterTurbo generates video scripts using LLMs, managing tasks, prompts, and APIs across multiple backends with robust error handling and sanitization.

- Repository: [Harry/MoneyPrinterTurbo](https://github.com/harry0703/MoneyPrinterTurbo)
- Tags: architecture
- Published: 2026-03-23

---

**MoneyPrinterTurbo generates video scripts by orchestrating task management, prompt engineering, and provider-agnostic API calls across 15+ LLM backends, followed by aggressive markdown sanitization and intelligent retry logic.**

MoneyPrinterTurbo is an open-source automated video creation platform that transforms text subjects into complete video scripts using Large Language Models. The system implements a clean separation of concerns between high-level task orchestration and low-level LLM interaction, enabling support for diverse providers like OpenAI, Azure, Ollama, and Gemini through a unified interface. Understanding how MoneyPrinterTurbo handles script generation with LLMs reveals a robust pipeline designed for reliability and extensibility.

## Task Orchestration and Entry Points

The script generation workflow begins in [`app/services/task.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/task.py), where the `start` function initiates the video creation pipeline. When processing a new request, the system checks whether a script already exists; if not, it delegates to the LLM service layer by invoking `generate_script` with the video subject, target language, and desired paragraph count.

This orchestration layer abstracts the complexity of LLM interaction, allowing the task manager to focus on coordinating subsequent steps like term extraction, audio generation, and video composition. The generated script is ultimately persisted to [`script.json`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/script.json) and optionally returned to callers such as the Streamlit web interface in [`webui/Main.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/webui/Main.py).

## Prompt Engineering and Provider Configuration

In [`app/services/llm.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/llm.py), the `generate_script` function constructs a deterministic system prompt that instructs the model to act as a **Video Script Generator**. The prompt explicitly demands raw text output without markdown formatting, titles, or meta-information, injecting the user's video subject, paragraph count, and optional language constraints.

Provider selection is driven by the `llm_provider` configuration key defined in [`config.example.toml`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/config.example.toml), defaulting to `openai` if unspecified. The architecture supports extensive provider diversity including OpenAI, Azure, Ollama, Moonshot, G4F, Pollinations, Gemini, Cloudflare, Ernie, Qwen, DeepSeek, and ModelScope, each configurable with distinct API keys, base URLs, and model parameters.

## LLM API Integration and Response Handling

The LLM service implements provider-specific request patterns while maintaining a unified response interface. For the default OpenAI path, the code initializes an `OpenAI` client with configured credentials and executes `chat.completions.create` to retrieve the script content.

Alternative providers follow adapted request flows; for instance, Pollinations uses raw `requests.post` calls to REST endpoints. Regardless of the provider, all branches funnel the model's response into a `content` variable for downstream processing, ensuring the task layer receives consistent string output regardless of backend implementation.

## Response Sanitization and Paragraph Structuring

Raw LLM outputs often contain unwanted formatting artifacts that disrupt video generation. The `format_response` function in [`app/services/llm.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/llm.py) implements aggressive text cleaning that strips asterisks, hash symbols, bracketed markdown links, and parenthesized URLs from the generated content.

After sanitization, the system splits the cleaned text on double line-breaks to segment the script into discrete paragraphs matching the requested count. This post-processing ensures the final script contains only plain text suitable for voice synthesis and subtitle generation, removing any structural noise introduced by the LLM.

## Retry Logic and Error Resilience

MoneyPrinterTurbo implements defensive retry mechanisms to handle transient LLM failures and provider-specific quota limitations. The generation loop attempts up to `_max_retries` (5 attempts by default) when encountering empty responses or specific error messages.

The system specifically detects quota exhaustion errors—identified by the Chinese string `"当日额度已消耗完"` (daily quota exhausted)—and treats these as retryable conditions. This resilience ensures script generation completes successfully even under provider instability or rate limiting, automatically cycling through retry attempts before surfacing failures to the user.

## Practical Implementation Examples

### Direct Script Generation via LLM Service

For standalone script generation without full video processing, import the LLM service directly:

```python
from app.services import llm

subject = "The impact of cryptocurrency on modern finance"
script = llm.generate_script(
    video_subject=subject,
    language="en",
    paragraph_number=3
)
print(script)

```

This invocation constructs the prompt, communicates with the configured provider (defaulting to OpenAI), and returns sanitized paragraph text ready for display or storage.

### Full Pipeline Orchestration with Early Termination

To execute the complete workflow while stopping after script generation:

```python
from app.services import task
from app.models.schema import VideoParams

params = VideoParams(
    video_subject="How money influences society",
    voice_name="en-US-AndrewNeural",
    video_language="en",
    paragraph_number=2,
)

result = task.start(task_id="my_task_001", params=params, stop_at="script")
print("Generated script:", result["script"])

```

The `stop_at="script"` parameter instructs `task.start` to halt execution after the LLM returns content, returning the same cleaned text available through the direct service call while demonstrating integration with the broader video creation architecture.

## Summary

- **Task orchestration** in [`app/services/task.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/task.py) coordinates script generation through the `start` function, checking for existing scripts before invoking LLM services.
- **Prompt construction** in [`app/services/llm.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/llm.py) generates deterministic system instructions that enforce raw text output without markdown artifacts.
- **Provider abstraction** supports 15+ backends including OpenAI, Azure, Gemini, and Ollama through configurable `llm_provider` settings in [`config.example.toml`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/config.example.toml).
- **Response sanitization** via `format_response` removes asterisks, hashes, links, and URLs, then segments text into paragraphs using double line-break delimiters.
- **Retry resilience** implements 5-attempt retry logic with specific handling for quota exhaustion errors (`"当日额度已消耗完"`).
- **Integration flexibility** allows both direct LLM service calls and full pipeline orchestration with early termination via `stop_at="script"`.

## Frequently Asked Questions

### What LLM providers does MoneyPrinterTurbo support?

MoneyPrinterTurbo supports over 15 LLM providers including OpenAI, Azure OpenAI, Ollama, Moonshot, G4F, Pollinations, Gemini, Cloudflare Workers AI, Baidu Ernie, Alibaba Qwen, DeepSeek, and ModelScope. Provider selection is controlled by the `llm_provider` configuration key in [`config.example.toml`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/config.example.toml), with each provider supporting distinct API endpoints, authentication methods, and model specifications.

### How does MoneyPrinterTurbo clean LLM responses for video use?

The system employs the `format_response` function in [`app/services/llm.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/llm.py) to strip markdown syntax including asterisks, hash symbols, bracketed links, and parenthesized URLs from raw LLM output. After cleaning, the function splits text on double line-breaks to isolate paragraphs, ensuring the final script contains only plain text compatible with text-to-speech engines and subtitle rendering.

### Can I customize the script generation prompt?

While the current implementation in [`app/services/llm.py`](https://github.com/harry0703/MoneyPrinterTurbo/blob/main/app/services/llm.py) uses a static system prompt defining the *Video Script Generator* role, advanced users can modify the prompt template directly in the source code. The prompt explicitly requests raw text without markdown and incorporates variables for video subject, paragraph count, and language constraints, allowing straightforward customization for specific tone or style requirements.

### What happens when an LLM provider fails or returns empty responses?

MoneyPrinterTurbo implements a retry mechanism that attempts script generation up to 5 times (`_max_retries`) when receiving empty responses or encountering provider errors. The system specifically recognizes quota exhaustion messages (e.g., `"当日额度已消耗完"`) as retryable conditions, automatically reattempting generation before propagating persistent failures to the calling task layer or web interface.