Who: E-commerce teams, content managers, accessibility specialists Why: Good alt text improves accessibility and SEO. Manual writing is time-consuming at scale.
name: product-photo-alt-text-writerversion: "1.0.0"description: "Generate accessible alt text for product images"author: "PraisonAI"license: "MIT"tags: - image - accessibility - ecommerce - seorequires: env: - OPENAI_API_KEY packages: - praisonaiagentsinputs: 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
# recipe.pyimport osfrom praisonaiagents import Agent, Task, AgentTeamdef 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
# test_recipe.pyimport pytestfrom recipe import rundef 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.integrationdef 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
# Batch process product imagesfor img in products/*.jpg; do praison recipes run product-photo-alt-text-writer \ --input "{\"image_path\": \"$img\"}" --jsondone
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} )