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 (e.g., https://openrouter.ai/api/v1) No
OPENAI_BASE_URL OpenAI-compatible API base URL No
OPENROUTER_MODEL Model to use for extraction No
OPENAI_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.1.tar.gz (12.7 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.1-py3-none-any.whl (18.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: whatsapp_formatter-0.1.1.tar.gz
  • Upload date:
  • Size: 12.7 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.1.tar.gz
Algorithm Hash digest
SHA256 ccb82974df7cb4fb512383b2a1b3a110f203bf669b48570d4aed1cbcd0f91627
MD5 392161193c4c6788d30844bc19ef537a
BLAKE2b-256 e017d056212e62942d30aba4f288c6967e915790031f6289b4bedb3db860ca0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for whatsapp_formatter-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ca4ec963356404e03272565aa937004bdd626ea8fb4e64035b0636b7342d83aa
MD5 d34193fd80cb6996a1f83ec3ea1b8d17
BLAKE2b-256 ea6355447be69f0e013334062d35dd482cec7b9b179934b0e7ff0cd99e39bc4e

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