Chapter 4: Text Generation Applications

In the previous chapters, you learned Generative AI fundamentals, OpenAI API fundamentals, prompt engineering, structured prompting, and production-oriented project architecture. Now we put all of that together to build real text-generation applications.

The approach used throughout this series is based on the Responses API, which accepts model input and returns generated output built specifically for application development.

4.1 What Is Text Generation?

Text generation means using an AI model to create new text based on instructions and input.

Input → Instructions → AI Model → Generated Text

Examples:

"Write a product description"
"Summarize this article"
"Translate this text"
"Write a professional email"

4.2 Common Text Generation Use Cases

We’ll focus on six major application types:

1. Content Generation — Topic → AI → Article / Blog / Description

2. Summarization — Long Text → AI → Short Summary

3. Translation — English Text → AI → Hindi / Spanish / Japanese

4. Information Extraction — Unstructured Text → AI → Structured Data

5. Classification — Customer Message → AI → Category

6. Email Generation — Situation → AI → Professional Email

4.3 Industry Project for This Chapter

Rather than building five disconnected scripts, we’ll build one reusable AI Text Processing Service:

┌─────────────────────┐
│  Application Layer   │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│  Text Service Layer  │
└──────────┬──────────┘
           │
   ┌───────┼───────┐
   ▼       ▼       ▼
Summarizer Translator Generator
   │       │       │
   └───────┼───────┘
           ▼
┌─────────────────────┐
│   OpenAI Client      │
└─────────────────────┘

Our application will support: summarization, content generation, translation, email generation, and information extraction.

4.4 Project Structure

ai-text-platform/
│
├── src/
│   └── ai_text_platform/
│       │
│       ├── main.py
│       │
│       ├── config/
│       │   ├── __init__.py
│       │   └── settings.py
│       │
│       ├── clients/
│       │   ├── __init__.py
│       │   └── openai_client.py
│       │
│       ├── services/
│       │   ├── __init__.py
│       │   ├── text_generation_service.py
│       │   ├── summarization_service.py
│       │   ├── translation_service.py
│       │   └── email_service.py
│       │
│       ├── prompts/
│       │   ├── __init__.py
│       │   ├── generation_prompts.py
│       │   ├── summarization_prompts.py
│       │   └── translation_prompts.py
│       │
│       ├── models/
│       │   ├── __init__.py
│       │   └── text_models.py
│       │
│       └── utils/
│           ├── __init__.py
│           └── logging_config.py
│
├── tests/
│   ├── test_prompts.py
│   └── test_validation.py
│
├── .env
├── .env.example
├── .gitignore
├── requirements.txt
└── README.md

This is a much more realistic setup than one app.py file trying to hold every feature at once.

4.5 Step 1: Create the Project

mkdir ai-text-platform
cd ai-text-platform

Create a virtual environment:

python -m venv .venv

Windows:

.venv\Scripts\activate

macOS/Linux:

source .venv/bin/activate

Install dependencies:

pip install openai python-dotenv pydantic

requirements.txt:

openai
python-dotenv
pydantic

4.6 Step 2: Configuration

.env:

OPENAI_API_KEY=your_api_key_here

.env.example:

OPENAI_API_KEY=your_api_key_here

.gitignore:

.env
.venv/
__pycache__/
.pytest_cache/

4.7 Step 3: Application Settings

Create src/ai_text_platform/config/settings.py:

import os
from dotenv import load_dotenv

load_dotenv()

class Settings:
    def __init__(self) -> None:
        self.openai_api_key = os.getenv("OPENAI_API_KEY", "")
        self.model_name = os.getenv(
            "OPENAI_MODEL",
            "YOUR_MODEL_NAME",
        )

        if not self.openai_api_key:
            raise ValueError(
                "OPENAI_API_KEY is not configured."
            )

settings = Settings()

Why centralize configuration? Instead of scattering model = "..." across File 1, File 2, and File 3, you have one source of truth:

Configuration → All Services

This makes changing a setting a one-line edit instead of a multi-file hunt.

4.8 Step 4: Create the OpenAI Client

Create src/ai_text_platform/clients/openai_client.py:

from openai import OpenAI
from ai_text_platform.config.settings import settings

def create_openai_client() -> OpenAI:
    return OpenAI(
        api_key=settings.openai_api_key
    )

This module has exactly one job: create and configure the OpenAI client.

4.9 Step 5: Create Prompt Templates

Content Generation Prompt — src/ai_text_platform/prompts/generation_prompts.py:

def build_content_generation_prompt(
    topic: str,
    audience: str,
    tone: str,
) -> str:
    return f"""
You are a professional content writer.

Task:
Write content about the following topic.

Topic:
{topic}

Target audience:
{audience}

Tone:
{tone}

Requirements:
- Be clear and useful.
- Do not invent unsupported facts.
- Organize the response with headings.
- Avoid unnecessary repetition.
"""

Summarization Prompt — src/ai_text_platform/prompts/summarization_prompts.py:

def build_summary_prompt(
    text: str,
    max_words: int,
) -> str:
    return f"""
You are a professional summarization assistant.

Summarize the text below.

Requirements:
- Preserve the main meaning.
- Remove unnecessary repetition.
- Do not add facts that are not in the source.
- Keep the summary below {max_words} words.

Text:
{text}
"""

Translation Prompt — src/ai_text_platform/prompts/translation_prompts.py:

def build_translation_prompt(
    text: str,
    target_language: str,
) -> str:
    return f"""
Translate the following text into {target_language}.

Rules:
- Preserve the original meaning.
- Do not add explanations.
- Return only the translation.

Text:
{text}
"""

4.10 Step 6: Create a Reusable AI Service

Create src/ai_text_platform/services/text_generation_service.py:

from openai import OpenAI
from ai_text_platform.config.settings import settings

class TextGenerationService:
    def __init__(self, client: OpenAI) -> None:
        self.client = client

    def generate(
        self,
        prompt: str,
    ) -> str:
        response = self.client.responses.create(
            model=settings.model_name,
            input=prompt,
        )
        return response.output_text

This service does one thing:

Prompt → OpenAI API → Generated Text

It doesn’t know or care whether the prompt is for summarization, translation, blog generation, or email generation — and that’s exactly the point of good design: each layer only knows what it needs to.

4.11 Why Use a Service Layer?

Without a service layer:

main.py
├── Build prompt
├── Call API
├── Parse response
├── Handle errors
├── Generate email
├── Summarize
└── Translate

This quickly becomes unmaintainable as features are added.

With a service layer:

main.py → TextGenerationService → OpenAI Client

The application layer stays thin and clean, while each domain-specific service handles its own concerns.

4.12 Application 1: Content Generator

Topic → Prompt Builder → Text Generation Service → OpenAI API → Generated Content

Example input:

Topic: Introduction to Python
Audience: Complete beginners
Tone: Friendly and educational

Generated output might look like:

# Introduction to Python

Python is a popular programming language...

## Why Learn Python?
...

4.13 Application 2: Summarization

Summarization is one of the most common enterprise GenAI use cases — turning long reports, emails, or documents into something a person can actually read in a minute.

Long Text → Validation → Summary Prompt → AI Service → Summary

4.14 Summarization Service

Create src/ai_text_platform/services/summarization_service.py:

from ai_text_platform.prompts.summarization_prompts import (
    build_summary_prompt,
)
from ai_text_platform.services.text_generation_service import (
    TextGenerationService,
)

class SummarizationService:
    def __init__(
        self,
        text_service: TextGenerationService,
    ) -> None:
        self.text_service = text_service

    def summarize(
        self,
        text: str,
        max_words: int = 150,
    ) -> str:
        if not text.strip():
            raise ValueError(
                "Text cannot be empty."
            )

        if max_words <= 0:
            raise ValueError(
                "max_words must be greater than zero."
            )

        prompt = build_summary_prompt(
            text=text,
            max_words=max_words,
        )
        return self.text_service.generate(prompt)

Responsibilities:

SummarizationService → Validate Input → Build Summary Prompt → Call Generic Text Service

This is reusable and easy to test independently.

4.15 Application 3: Translation

Original Text + Target Language → Translation Prompt → AI Service → Translated Text

Create src/ai_text_platform/services/translation_service.py:

from ai_text_platform.prompts.translation_prompts import (
    build_translation_prompt,
)
from ai_text_platform.services.text_generation_service import (
    TextGenerationService,
)

class TranslationService:
    def __init__(
        self,
        text_service: TextGenerationService,
    ) -> None:
        self.text_service = text_service

    def translate(
        self,
        text: str,
        target_language: str,
    ) -> str:
        if not text.strip():
            raise ValueError(
                "Text cannot be empty."
            )

        if not target_language.strip():
            raise ValueError(
                "Target language is required."
            )

        prompt = build_translation_prompt(
            text=text,
            target_language=target_language,
        )
        return self.text_service.generate(prompt)

4.16 Application 4: Email Generation

Imagine a user enters:

Situation: The product delivery is delayed by 5 days.
Recipient: Customer
Tone: Professional and apologetic

The AI generates:

Subject: Update Regarding Your Delivery

Dear Customer,

We sincerely apologize for the delay...

Useful across customer support, sales, HR, internal communication, and marketing.

4.17 Email Prompt

Create src/ai_text_platform/prompts/email_prompts.py:

def build_email_prompt(
    situation: str,
    recipient: str,
    tone: str,
) -> str:
    return f"""
You are a professional business communication assistant.

Write an email based on the following information.

Situation:
{situation}

Recipient:
{recipient}

Tone:
{tone}

Requirements:
- Include a clear subject.
- Use professional language.
- Keep the email concise.
- Do not invent details.
"""

4.18 Information Extraction

One of the most valuable AI use cases: converting unstructured text into structured data your systems can actually use.

Input:

John Smith purchased 3 laptops
for $3,000 on March 15, 2026.

Output:

{
  "customer_name": "John Smith",
  "product": "laptops",
  "quantity": 3,
  "amount": 3000,
  "date": "March 15, 2026"
}
Unstructured Text → Extraction Prompt → AI Model → Structured Output → Application

Widely used for invoice processing, resume parsing, contract analysis, customer data extraction, and email processing.

4.19 Why Structured Output Matters

Suppose the AI returns:

The customer is John Smith and purchased three laptops.

Your application now has to parse this sentence with fragile string logic. Compare that to:

{
  "customer_name": "John Smith",
  "product": "laptops",
  "quantity": 3
}

which can flow directly:

JSON → Python Object → Database

This is a critical, recurring pattern in production AI applications — always prefer structured output when your code needs to act on the result.

4.20 Build a CLI Application

Create src/ai_text_platform/main.py with a simple menu:

AI Text Platform
1. Generate Content
2. Summarize Text
3. Translate Text
4. Generate Email
5. Exit
def main() -> None:
    while True:
        print("1. Generate Content")
        print("2. Summarize Text")
        print("3. Translate Text")
        print("4. Generate Email")
        print("5. Exit")

        choice = input("Select an option: ")

        if choice == "1":
            generate_content()
        elif choice == "2":
            summarize_text()
        elif choice == "3":
            translate_text()
        elif choice == "4":
            generate_email()
        elif choice == "5":
            break
        else:
            print("Invalid choice.")

Architectural principle:

CLI → Application Logic → Domain Service → AI Service → OpenAI API

4.21 Input Validation

Never assume user input is valid.

Bad:

max_words = int(
    input("Maximum words: ")
)

If the user types abc, this crashes immediately.

Better:

try:
    max_words = int(
        input("Maximum words: ")
    )
except ValueError:
    print("Please enter a valid number.")

For production systems, validation should happen before the AI request is even sent — don’t waste an API call on input you already know is invalid.

4.22 Error Handling

try:
    result = service.summarize(
        text=text,
        max_words=150,
    )
except ValueError as error:
    print(f"Input error: {error}")
except Exception:
    print(
        "Unable to process your request right now."
    )

A real application should also log the underlying technical error internally — while the user-facing message stays simple and doesn’t leak sensitive internal details.

4.23 Logging

Create src/ai_text_platform/utils/logging_config.py:

import logging

def configure_logging() -> None:
    logging.basicConfig(
        level=logging.INFO,
        format=(
            "%(asctime)s "
            "%(levelname)s "
            "%(name)s "
            "%(message)s"
        ),
    )

Then:

import logging

logger = logging.getLogger(__name__)

You can log:

logger.info(
    "Starting summarization request"
)

and:

logger.exception(
    "Summarization request failed"
)

Do not log: API keys, passwords, sensitive customer data, or private documents unnecessarily — logs often have looser access controls than you’d expect.

4.24 Testing Prompt Builders

Prompt builders are pure functions, which makes them easy to test.

Create tests/test_prompts.py:

from ai_text_platform.prompts.summarization_prompts import (
    build_summary_prompt,
)

def test_summary_prompt_contains_text() -> None:
    prompt = build_summary_prompt(
        text="Python is a programming language.",
        max_words=100,
    )
    assert (
        "Python is a programming language."
        in prompt
    )

Another test:

def test_summary_prompt_contains_word_limit() -> None:
    prompt = build_summary_prompt(
        text="Example text.",
        max_words=100,
    )
    assert "100 words" in prompt

These tests never call the actual API, which makes them fast, cheap, and reliable to run constantly.

4.25 Testing Validation

import pytest
from ai_text_platform.services.summarization_service import (
    SummarizationService,
)

def test_empty_text_is_rejected() -> None:
    service = SummarizationService(
        text_service=None
    )
    with pytest.raises(ValueError):
        service.summarize(
            text="",
            max_words=100,
        )

This verifies application behavior without needing a real API call.

4.26 Mocking AI Calls

In real test suites, you generally don’t want every test hitting the external API — it’s slow, costs money, and makes tests flaky.

Application → Mock AI Service → Fake Response
class FakeTextService:
    def generate(
        self,
        prompt: str,
    ) -> str:
        return "Mock summary"

Then:

service = SummarizationService(
    text_service=FakeTextService()
)

This is a genuinely important industry practice — treat it as standard, not optional.

4.27 The Complete Text Generation Flow

┌──────────────────────┐
│      User Input       │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│      Validation       │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│    Domain Service      │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│   Prompt Builder       │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│   AI Text Service      │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│    OpenAI Client       │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│   Generated Text       │
└──────────────────────┘

4.28 Practical Exercise 1: Blog Generator

Build a function that accepts Topic, Audience, Tone, Length.

Example:

Topic: Python decorators
Audience: Beginner developers
Tone: Educational
Length: 500 words

Output structure: Title, Introduction, Main Explanation, Example, Conclusion.

4.29 Practical Exercise 2: Meeting Summarizer

Input: a meeting transcript. Output:

{
  "summary": "...",
  "decisions": [],
  "action_items": [],
  "risks": []
}

This combines summarization, extraction, and structured output all in one task.

4.30 Practical Exercise 3: Email Assistant

Input:

Situation: Customer's order is delayed.
Tone: Professional and apologetic.

Output:

Subject: Update Regarding Your Order

Dear Customer,
...

4.31 Practical Exercise 4: Multi-Language Translator

Original Text + Target Language → Translated Text

Example:

Input: Good morning, how are you?
Target: Hindi
Output: सुप्रभात, आप कैसे हैं?

4.32 Production Considerations

Input Length — very large inputs may require chunking:

Chunking → Multiple AI Requests → Combined Result

(This becomes central in the RAG chapter.)

Output Validation — never blindly trust generated output:

AI Output → Validation → Application

Sensitive Data — be careful with personal information, financial data, and confidential business documents.

Cost — repeated requests add up; consider caching, smaller inputs, appropriate model selection, and output limits.

Reliability — external API calls can fail; use retry + timeout + logging + graceful failure together.

4.33 Chapter 4 Mini Project

Build an AI Text Processing Platform with a Content Generator, Summarizer, Translator, and Email Generator.

Minimum architecture:

src/
└── ai_text_platform/
    ├── config/
    ├── clients/
    ├── prompts/
    ├── services/
    ├── models/
    ├── utils/
    └── main.py

Required development practices:

  • Secure API key management
  • Reusable OpenAI client
  • Separate prompt modules
  • Separate service classes
  • Input validation
  • Error handling
  • Logging
  • Unit tests
  • No hardcoded secrets
  • No API calls directly inside every CLI function

Chapter 4 Summary

You learned how to build text-generation applications for content generation, summarization, translation, email generation, and information extraction.

The key architecture:

User Input → Validation → Domain Service → Prompt Template →
AI Service → OpenAI API → Validated Output

The major lesson of this chapter:

A production AI application is not just an API call.

Good Prompt + Good Architecture + Validation + Error Handling + Testing + Security

Next chapter: Chapter 5 — Function Calling & Tools, where we’ll build an AI application that can interact with external functions, APIs, databases, and real-world business systems.

Scroll to Top