Skip to main content

Transform LLM output to WhatsApp Business API JSON format

Project description

WhatsApp Formatter

Transform LLM output to WhatsApp Business API JSON format.

This library uses an LLM to parse free-form text (with options, headers, footers) and automatically converts it to valid WhatsApp message formats (plain text, quick reply buttons, or interactive lists).

Installation

pip install whatsapp-formatter

Quick Start

import os
from whatsapp_formatter import format_for_whatsapp

# Set your API key (OpenRouter or OpenAI)
os.environ["OPENROUTER_API_KEY"] = "your-api-key"
os.environ["OPENROUTER_BASE_URL"] = "https://openrouter.ai/api/v1"

# Format LLM output for WhatsApp
raw_text = """
I can help with your account. What would you like to do?

1. Check your balance
2. Transfer funds
3. View recent transactions
"""

result = format_for_whatsapp(raw_text)
print(result.whatsapp_json)

Output:

{
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": { "text": "I can help with your account. What would you like to do?" },
    "action": {
      "buttons": [
        { "type": "reply", "reply": { "id": "check_your_balance", "title": "Check your balance" } },
        { "type": "reply", "reply": { "id": "transfer_funds", "title": "Transfer funds" } },
        { "type": "reply", "reply": { "id": "view_recent_transac", "title": "View Transactions" } }
      ]
    }
  }
}

Features

  • Automatic format selection based on option count:

    • 0 options → Plain text message
    • 1-3 options → Quick reply buttons
    • 4-10 options → Interactive list
    • 11+ options → Plain text fallback with numbered list
  • Smart truncation to fit WhatsApp constraints:

    • Button titles: max 20 characters
    • List row titles: max 24 characters
    • Body text: max 1024 characters (interactive) or 1600 (plain text)
  • Automatic deduplication of option titles with suffixes

  • Header/footer extraction from structured messages

  • Multiple option formats supported:

    • Numbered lists (1. Option)
    • Bullet points (- Option, • Option)
    • Inline choices (Yes, No, or Cancel)

API Reference

format_for_whatsapp(text: str) -> TransformResult

The main entry point. Parses text and returns WhatsApp-ready JSON.

from whatsapp_formatter import format_for_whatsapp

result = format_for_whatsapp("Your balance is $500.")
print(result.format_used)      # FormatType.PLAIN_TEXT
print(result.whatsapp_json)    # {"type": "text", "text": {"body": "..."}}
print(result.fallback_used)    # False
print(result.modifications)    # List of any truncations applied

transform(llm_output: LLMOutput) -> TransformResult

Transform pre-parsed data to WhatsApp format (skip LLM parsing step).

from whatsapp_formatter import transform, LLMOutput, Option

llm_output = LLMOutput(
    body="Choose an option:",
    options=[
        Option(title="Yes"),
        Option(title="No"),
    ]
)
result = transform(llm_output)

parse(text: str) -> LLMOutput

Parse text using LLM (requires API key).

from whatsapp_formatter import parse

llm_output = parse("Select: 1. Apple 2. Banana 3. Cherry")
print(llm_output.body)     # "Select:"
print(llm_output.options)  # [Option(title="Apple"), ...]

Data Types

LLMOutput

class LLMOutput:
    body: str                    # Main message text (required)
    options: list[Option] | None # Flat list of options
    sections: list[Section] | None # Grouped options (for list format)
    header: str | None           # Optional header text
    footer: str | None           # Optional footer text

TransformResult

class TransformResult:
    success: bool                # Always True unless error
    whatsapp_json: dict          # Ready-to-send WhatsApp payload
    format_used: FormatType      # PLAIN_TEXT, QUICK_REPLY, or LIST
    fallback_used: bool          # True if format was downgraded
    fallback_reason: str | None  # Reason for fallback
    modifications: list[str]     # Truncations/deduplications applied

FormatType

class FormatType(Enum):
    PLAIN_TEXT = "plain_text"
    QUICK_REPLY = "quick_reply"
    LIST = "list"

Configuration

Environment Variables

Variable Description Required
OPENROUTER_API_KEY OpenRouter API key Yes*
OPENAI_API_KEY OpenAI API key Yes*
OPENROUTER_BASE_URL API base URL No
OPENROUTER_MODEL Model to use (default: openai/gpt-4o-mini) No

*One of OPENROUTER_API_KEY or OPENAI_API_KEY is required.

Recommended Models

For best results with structured extraction:

  • qwen/qwen3-30b-a3b-instruct-2507 (91%+ accuracy)
  • openai/gpt-4o-mini (with JSON mode)

WhatsApp Constraints

The library automatically handles these WhatsApp Business API limits:

Element Max Length
Quick reply button title 20 chars
Quick reply buttons 3 max
List row title 24 chars
List row description 72 chars
List sections 10 max
List rows total 10 max
Interactive body 1024 chars
Plain text body 1600 chars
Header 60 chars
Footer 60 chars

Examples

Plain Text (no options)

result = format_for_whatsapp("Your balance is $500.")
# → {"type": "text", "text": {"body": "Your balance is $500."}}

Quick Reply (1-3 options)

result = format_for_whatsapp("""
Was this transaction authorized?
1. Yes
2. No
""")
# → {"type": "interactive", "interactive": {"type": "button", ...}}

List (4-10 options)

result = format_for_whatsapp("""
Select a service:
1. Balance
2. Transfer
3. Cards
4. Loans
5. Support
""")
# → {"type": "interactive", "interactive": {"type": "list", ...}}

With Header and Footer

result = format_for_whatsapp("""
⚠️ Security Alert

We detected a login from a new device. Was this you?

1. Yes, it was me
2. No, secure my account

Reply within 24 hours.
""")
# Extracts header: "Security Alert"
# Extracts footer: "Reply within 24 hours."

Development

# Clone the repository
git clone https://github.com/dnivra26/whatsapp-formatter.git
cd whatsapp-formatter

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

whatsapp_formatter-0.1.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

whatsapp_formatter-0.1.0-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file whatsapp_formatter-0.1.0.tar.gz.

File metadata

  • Download URL: whatsapp_formatter-0.1.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for whatsapp_formatter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 527b1ee0d9ee2969dee8165fe3d2afcec55b9d13a88f2cecfa057c5042086f5c
MD5 4c1245836624626cf48db944dd5c2055
BLAKE2b-256 9c2d9bfa19f83867254c5ff759a637dc9adf0b13ef01905bd6eb7e9c5d753577

See more details on using hashes here.

File details

Details for the file whatsapp_formatter-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for whatsapp_formatter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3385712836be476f92932280106d8abaf4fc49b64f0e0cf28643e122cd1e4253
MD5 c752e86137af7e44455ac858bfea6fd8
BLAKE2b-256 68a2e7c091260c23fb938c00206510eb7872cb6af95a7e6473745bfcc8d2d8cb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page