Product Photo Alt Text Writer

Generate accessible alt text and tags for product images

Product Photo Alt Text Writer

Generate SEO-friendly, accessible alt text and tags for product images.

Problem Statement

Who: E-commerce teams, content managers, accessibility specialists

Why: Good alt text improves accessibility and SEO. Manual writing is time-consuming at scale.

What You’ll Build

A recipe that analyzes product images and generates descriptive alt text with relevant tags.

Diagram

🖼️ Product Image

Analyze Image

Generate Alt Text

Extract Tags

📝 Alt Text + Tags

Input/Output Contract

InputTypeRequiredDescription
image_pathstringYesPath to product image
brand_tonestringNoBrand voice (default: neutral)
localestringNoTarget locale (default: en-US)
OutputTypeDescription
alt_textstringGenerated alt text
tagsarrayRelevant product tags
okbooleanSuccess indicator

Prerequisites

bash
export OPENAI_API_KEY=your_key_here
pip install praisonaiagents

Step-by-Step Build

  1. Create Recipe Directory
    bash
    mkdir -p ~/.praisonai/templates/product-photo-alt-text-writer
    cd ~/.praisonai/templates/product-photo-alt-text-writer
  2. Create TEMPLATE.yaml
    yaml
    name: product-photo-alt-text-writer
    version: "1.0.0"
    description: "Generate accessible alt text for product images"
    author: "PraisonAI"
    license: "MIT"
    
    tags:
      - image
      - accessibility
      - ecommerce
      - seo
    
    requires:
      env:
        - OPENAI_API_KEY
      packages:
        - praisonaiagents
    
    inputs:
      image_path:
        type: string
        description: "Path to the product image"
        required: true
      brand_tone:
        type: string
        description: "Brand voice for alt text"
        required: false
        default: "neutral"
        enum:
          - neutral
          - luxury
          - casual
          - technical
      locale:
        type: string
        description: "Target locale for alt text"
        required: false
        default: "en-US"
    
    outputs:
      alt_text:
        type: string
        description: "Generated alt text"
      tags:
        type: array
        description: "Relevant product tags"
      ok:
        type: boolean
        description: "Success indicator"
    
    cli:
      command: "praison recipes run product-photo-alt-text-writer"
      examples:
        - 'praison recipes run product-photo-alt-text-writer --input ''{"image_path": "product.jpg"}'''
    
    safety:
      dry_run_default: false
      requires_consent: false
      overwrites_files: false
      network_access: true
      pii_handling: false
  3. Create recipe.py
    python
    # recipe.py
    import os
    from praisonaiagents import Agent, Task, AgentTeam
    
    def run(input_data: dict, config: dict = None) -> dict:
        """Generate alt text for product images."""
        image_path = input_data.get("image_path")
        brand_tone = input_data.get("brand_tone", "neutral")
        locale = input_data.get("locale", "en-US")
    
        if not image_path:
            return {"ok": False, "error": {"code": "MISSING_INPUT", "message": "image_path is required"}}
    
        if not os.path.exists(image_path):
            return {"ok": False, "error": {"code": "FILE_NOT_FOUND", "message": f"Image not found: {image_path}"}}
    
        try:
            tone_guidelines = {
                "neutral": "Clear, factual descriptions",
                "luxury": "Elegant, sophisticated language emphasizing quality",
                "casual": "Friendly, approachable descriptions",
                "technical": "Precise specifications and features"
            }
    
            # Create vision agent
            vision_agent = Agent(
                name="Product Analyst",
                role="Visual Product Expert",
                goal="Analyze product images accurately",
                instructions=f"""
                You are a product image analyst.
                - Identify the product type and category
                - Note colors, materials, and features
                - Describe the product's appearance
                - Consider the {brand_tone} tone: {tone_guidelines[brand_tone]}
                """,
            )
    
            # Create alt text writer
            alt_writer = Agent(
                name="Alt Text Writer",
                role="Accessibility Specialist",
                goal="Write effective alt text for screen readers",
                instructions=f"""
                You are an accessibility expert writing alt text.
                - Keep alt text under 125 characters
                - Be descriptive but concise
                - Include key product details
                - Use {brand_tone} tone
                - Write for {locale} audience
                - Don't start with "Image of" or "Picture of"
                """,
            )
    
            # Create tag generator
            tagger = Agent(
                name="Product Tagger",
                role="E-commerce SEO Specialist",
                goal="Generate relevant product tags",
                instructions="""
                You are an e-commerce tagging expert.
                - Generate 5-10 relevant tags
                - Include category, color, material, style
                - Use lowercase, hyphenated format
                - Focus on searchable terms
                """,
            )
    
            # Define tasks
            analyze_task = Task(
                name="analyze_image",
                description=f"Analyze the product image at: {image_path}",
                expected_output="Detailed product description",
                agent=vision_agent,
            )
    
            alt_task = Task(
                name="write_alt_text",
                description="Write accessible alt text based on the analysis",
                expected_output="Alt text under 125 characters",
                agent=alt_writer,
                context=[analyze_task],
            )
    
            tag_task = Task(
                name="generate_tags",
                description="Generate product tags for SEO",
                expected_output="List of 5-10 tags",
                agent=tagger,
                context=[analyze_task],
            )
    
            # Execute
            agents = AgentTeam(
                agents=[vision_agent, alt_writer, tagger],
                tasks=[analyze_task, alt_task, tag_task],
            )
    
            result = agents.start()
    
            # Parse tags
            tags_text = result.get("generate_tags", "")
            tags = [t.strip().lower().replace(" ", "-") for t in tags_text.split(",") if t.strip()]
            if not tags:
                tags = [t.strip() for t in tags_text.split("\n") if t.strip() and not t.startswith("-")]
    
            return {
                "ok": True,
                "alt_text": result.get("write_alt_text", "").strip()[:125],
                "tags": tags[:10],
                "artifacts": [],
                "warnings": [],
            }
    
        except Exception as e:
            return {"ok": False, "error": {"code": "PROCESSING_ERROR", "message": str(e)}}
  4. Create test_recipe.py
    python
    # test_recipe.py
    import pytest
    from recipe import run
    
    def test_missing_image_path():
        result = run({})
        assert result["ok"] is False
        assert result["error"]["code"] == "MISSING_INPUT"
    
    def test_file_not_found():
        result = run({"image_path": "/nonexistent.jpg"})
        assert result["ok"] is False
        assert result["error"]["code"] == "FILE_NOT_FOUND"
    
    def test_brand_tones():
        valid_tones = ["neutral", "luxury", "casual", "technical"]
        for tone in valid_tones:
            assert tone in valid_tones
    
    @pytest.mark.integration
    def test_end_to_end():
        import os
        test_image = os.environ.get("TEST_IMAGE_PATH")
        if not test_image:
            pytest.skip("No test image available")
    
        result = run({"image_path": test_image, "brand_tone": "neutral"})
        assert result["ok"] is True
        assert len(result["alt_text"]) <= 125
        assert len(result["tags"]) > 0

Run Locally

bash
# Basic usage
praison recipes run product-photo-alt-text-writer \
  --input '{"image_path": "shoe.jpg"}'

# With brand tone
praison recipes run product-photo-alt-text-writer \
  --input '{"image_path": "watch.png", "brand_tone": "luxury", "locale": "en-GB"}'

Deploy & Integrate: 6 Integration Models

Model 1: Embedded SDK

python
from praisonai import recipe

result = recipe.run(
    "product-photo-alt-text-writer",
    input={"image_path": "product.jpg", "brand_tone": "luxury"}
)

if result.ok:
    print(f"Alt: {result.output['alt_text']}")
    print(f"Tags: {result.output['tags']}")

Model 2: CLI Invocation

bash
# Batch process product images
for img in products/*.jpg; do
  praison recipes run product-photo-alt-text-writer \
    --input "{\"image_path\": \"$img\"}" --json
done

Model 3: Plugin Mode

python
class AltTextPlugin:
    def generate(self, image_path, tone="neutral"):
        from praisonai import recipe
        return recipe.run(
            "product-photo-alt-text-writer",
            input={"image_path": image_path, "brand_tone": tone}
        )

Model 4: Local HTTP Sidecar

javascript
const response = await fetch('http://localhost:8765/recipes/product-photo-alt-text-writer/run', {
  method: 'POST',
  body: JSON.stringify({ image_path: '/uploads/product.jpg' })
});

Model 5: Remote Managed Runner

python
response = requests.post(
    "https://api.ecommerce-tools.com/alt-text",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"image_url": "https://cdn.example.com/product.jpg"}
)

Model 6: Event-Driven

python
def on_product_image_uploaded(event):
    import queue as q
    job_queue = q.Queue()  # Replace with SQS/RabbitMQ in production
    job_queue.put({
        "recipe": "product-photo-alt-text-writer",
        "input": {"image_path": event['image_path']},
        "callback_url": f"https://api.example.com/products/{event['product_id']}/alt-text"
    })

Troubleshooting

Alt text too generic

Try using a more specific brand_tone or ensure the image is clear and well-lit.

Missing product details

The vision model works best with clear, well-composed product photos on neutral backgrounds.

Next Steps