跳转至

Final 6-File Prompt Architecture (v3.1 - Simplified)

Overview

This document consolidates all architectural decisions for the 6-file prompt structure. Version 3.1 simplifies deployment by keeping all files under site paths initially, with a clear migration path to franchise-level sharing when scale demands it. All files remain simple text files (no JSON schemas required) with Pydantic validation through Bedrock tool-calling.

The 6-File Structure (v1.0 - Current Implementation)

s3://{bucket}/
└── {franchise}/{siteId}/                    # All files under site (for now)
    └── prompts/v6/
        ├── 01-franchise-core.txt            # Core instructions & role
        ├── 02-knowledge.txt                 # Business knowledge base
        ├── 03-coaching.txt                  # Coaching scenarios
        ├── 04-staff-list.txt                # Site staff names
        ├── 05-studio-output-instructions.txt # Output requirements
        └── 06-custom-requirements.txt        # Local business context

Future Scaling Strategy (Keep Site-Level Isolation)

Instead of moving files to franchise level, maintain site-level structure for better testing and risk management:

s3://{bucket}/
└── {franchise}/{siteId}/                    # All files stay under site
    └── prompts/v6/
        ├── 01-franchise-core.txt            # Updated via Lambda batch
        ├── 02-knowledge.txt                 # Updated via Lambda batch
        ├── 03-coaching.txt                  # Updated via Lambda batch
        ├── 04-staff-list.txt                # Site-specific (manual)
        ├── 05-studio-output-instructions.txt # Site-specific (manual)
        └── 06-custom-requirements.txt        # Site-specific (manual)

Why This is Better: 1. Isolated Testing: Test changes on one site before rolling out 2. Damage Control: If something breaks, only one site affected 3. Gradual Rollout: Update sites in batches with validation 4. No Complex Path Logic: Simple single-path file loading

Lambda for Batch Updates:

# When updating franchise-wide files (1-3)
def update_franchise_files(franchise, files_to_update):
    sites = get_all_sites(franchise)

    # Test on pilot site first
    update_site(sites[0], files_to_update)
    validate_results()

    # Roll out to remaining sites
    for site in sites[1:]:
        update_site(site, files_to_update)

Why Start Simple

  1. Only 2 sites currently - Duplication is minimal
  2. 20 lines of code vs 60+ - Simpler implementation
  3. Single path loading - Easier debugging
  4. No complex fallback logic - Lower risk
  5. Easy migration later - Just change file paths when ready

File Details and Content Mapping

1. 01-franchise-core.txt (Site-Level)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/01-franchise-core.txt From original prompt: Lines 1-165 Note: Duplicated per site for testing isolation, updated via batch Lambda

You are an expert gym business analyst for Orange Theory Fitness.
Your task is to analyze customer service phone calls and extract actionable insights.

CORE RESPONSIBILITIES:
1. Identify call participants and their roles
2. Categorize the primary purpose of the call
3. Assess business outcomes
4. Provide coaching feedback

PROCESSING STEPS:
1. Identify who is on the call (staff vs customer)
2. Determine primary call intent
3. Evaluate outcome success
4. Identify follow-up needs
5. Provide coaching opportunities

[Standard processing logic for all locations]

2. 02-knowledge.txt (Site-Level)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/02-knowledge.txt From original prompt: Lines 168-596 Note: Duplicated per site for testing isolation, updated via batch Lambda

SALES KNOWLEDGE MODULE:
- Membership types: Elite ($189), Premier ($159), Basic ($99)
- Intro offers: First class free, 3-for-$49 intro pack
- Common objections and responses
- Upsell paths: Basic → Premier → Elite

CANCELLATION PROCEDURES:
- 30-day written notice required
- Freeze option as retention alternative
- Win-back strategies

FREEZE/HOLD POLICIES:
- Medical freeze: Unlimited duration with documentation
- Travel freeze: Up to 60 days
- Vacation hold: 30 days max

[Additional franchise-wide knowledge]

3. 03-coaching.txt (Site-Level)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/03-coaching.txt From original prompt: Lines 270-347, 389-402, 527-540, 583-595 Note: Duplicated per site for testing isolation, updated via batch Lambda

COACHING SCENARIOS:

SALES COACHING:
Scenario: Customer says "I need to think about it"
INSTEAD OF: "Okay, take your time"
SAY: "What specifically would you like to think about?"
WHY: Uncovers real objections to address

BILLING ISSUE COACHING:
Scenario: Customer upset about charge
INSTEAD OF: "I can't help with that"
SAY: "Let me review your account and see what happened"
WHY: Shows ownership and care

[Additional coaching scenarios grouped by topic]

4. 04-staff-list.txt (Site-Specific)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/04-staff-list.txt Unique to: Each site

KNOWN STAFF MEMBERS:
The following staff members work at this location:
- Drew (Sales Manager, works M-F mornings)
- Nadia (Head Coach, specializes in strength training)
- Jess (Front Desk Lead, handles billing issues)
- Holly (Assistant Manager, membership specialist)
- Ryanne (Sales Associate, Spanish speaker)
- Ryan (Front Desk, part-time evenings)
- Will (Coach, runs transformation challenges)
- Coach Marcus (Lead Coach, nutrition certified)

STAFF NAME CLARIFICATIONS:
- "Ryan" and "Ryanne" are different people
- "Jessica" is the same person as "Jess"
- "Marcus" should be identified as "Coach Marcus"

IDENTIFICATION RULE:
If you cannot identify the staff member with >80% confidence,
use "unidentified staff member" rather than guessing.

5. 05-studio-output-instructions.txt (Site-Specific)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/05-studio-output-instructions.txt From original prompt: Lines 599-781 (includes TAXONOMY section) Unique to: Each site

OUTPUT FORMAT AND TRACKING REQUIREMENTS:

CORE OUTPUT STRUCTURE:
All analyses must follow the CallAnalysis schema with these required fields:
- ai_call_analysis
- customer_profile
- primary_topic
- secondary_topics
- revenue_priority
- summary
- follow_up
- practical_coaching

TAXONOMY FOR CATEGORIZATION:
primary_topic.category can be:
- "scheduling" → subcategories: [class_booking, class_reschedule, class_cancellation, waitlist]
- "billing" → subcategories: [charge_inquiry, payment_update, refund_request, freeze_billing]
- "sales" → subcategories: [intro_booking, membership_inquiry, package_purchase, upgrade]
- "retention" → subcategories: [cancellation_request, freeze_request, downgrade]
- "service" → subcategories: [general_inquiry, complaint, equipment_issue, facility_question]

SITE-SPECIFIC TRACKING (populate in site_context field):
promotions_mentioned: List these if discussed:
- "student_discount" (Columbia/City College 20% off)
- "healthcare_special" ($99 for hospital employees)
- "new_year_challenge" (January promotion)

special_programs_discussed: Track if mentioned:
- "6am_warriors" (Early morning program)
- "transformation_challenge" (8-week program)
- "columbia_crew" (Thursday college night)

competitor_mentioned: Note if discussed:
- "equinox", "planet_fitness", "ymca", "crunch"

CUSTOM METRICS (populate in site_specific field):
- "spanish_language_request": true/false
- "parking_concern_raised": true/false
- "student_status_mentioned": true/false
- "morning_preference_expressed": true/false

INSTRUCTIONS: You MUST respond by calling the tool `record_call_analysis`

6. 06-custom-requirements.txt (Site-Specific)

Location: s3://{bucket}/{franchise}/{siteId}/prompts/v6/06-custom-requirements.txt Unique to: Each site

LOCAL BUSINESS CONTEXT FOR WEST HARLEM:

MARKET CHARACTERISTICS:
- Dense urban area with many young professionals
- Columbia University nearby (seasonal student population)
- High competition: Equinox 2 blocks away (premium)
- Limited parking (major customer concern)
- 40% Spanish-speaking community

CURRENT PROMOTIONS (Updated: January 2025):
- Student Special: 20% off unlimited (verify .edu email)
- Healthcare Heroes: $99/month for hospital ID holders
- New Year Challenge: Join in January, get February 50% off
- Corporate rates for 5+ employees from same company

OUR UNIQUE PROGRAMS:
- 6AM Warriors: M/W/F high-intensity for finance professionals
- Transformation Challenge: 8-week program with meal plans ($299)
- Columbia Crew: Thursday 8pm classes with DJ
- Lunch Express: 30-minute classes at noon

SALES PRIORITIES FOR THIS QUARTER:
1. Fill 6AM classes (currently 60% capacity)
2. Convert intro packs to Elite memberships
3. Capture Columbia students before semester starts
4. Upsell transformation challenge to new year members

COMPETITIVE POSITIONING:
- vs Equinox: Emphasize community and coaching over luxury
- vs Planet Fitness: Highlight coaching quality and results
- vs YMCA: Focus on specialized programs and technology

MANAGER NOTES:
- Always mention parking validation for intro classes
- Spanish-speaking staff: Ryanne, Miguel (not always available)
- Peak times: 6-8am and 5-7pm (suggest off-peak for intros)

Pydantic Model with Site Extensions

# models.py - Supporting site-specific fields

from pydantic import BaseModel, Field
from typing import Dict, Any, Optional, List

class CallAnalysis(BaseModel):
    """Core fields validated for ALL sites"""

    # Standard fields (strict validation)
    ai_call_analysis: AICallAnalysis
    customer_profile: CustomerProfile
    primary_topic: PrimaryTopic
    secondary_topics: List[SecondaryTopic] = []
    revenue_priority: RevenuePriority
    revenue_priority_evidence: str
    summary: str
    follow_up: FollowUp
    practical_coaching: PracticalCoaching

    # Site extensions (flexible validation)
    site_context: Optional[Dict[str, Any]] = Field(
        default_factory=dict,
        description="Semi-structured site fields from output-instructions"
    )

    site_specific: Optional[Dict[str, Any]] = Field(
        default_factory=dict,
        description="Fully flexible site-specific metrics"
    )

Lambda Implementation

Current v1.0 Implementation (Simple)

def load_prompt_v6(s3_client, bucket, franchise, site_id):
    """
    Load and concatenate 6 prompt files from site directory
    All files are .txt, no JSON parsing needed
    Schema.json not required - Pydantic handles validation
    """
    prompt_parts = []

    # Simple single-path loading - all files under site
    base_path = f"{franchise}/{site_id}/prompts/v6"
    files = [
        "01-franchise-core.txt",
        "02-knowledge.txt",
        "03-coaching.txt",
        "04-staff-list.txt",
        "05-studio-output-instructions.txt",
        "06-custom-requirements.txt"
    ]

    # Load each file
    for filename in files:
        try:
            content = s3_client.get_object(
                Bucket=bucket,
                Key=f"{base_path}/{filename}"
            )['Body'].read().decode('utf-8')
            prompt_parts.append(content)
            logger.info(f"Loaded: {filename}")
        except Exception as e:
            # Only file 6 is optional - file 5 contains CRITICAL taxonomy
            if "06-custom" in filename:
                logger.info(f"Optional file not found: {filename}")
            else:
                logger.error(f"Required file missing: {filename}")
                raise ValueError(f"Files 1-5 are mandatory. Missing: {filename}")

    # Simple concatenation
    return "\n\n".join(prompt_parts)

# Note: schema.json is NOT loaded - Pydantic models define the schema

Future Batch Update Tool (When Scaling)

def batch_update_franchise_prompts(franchise, files_to_update, test_site=None):
    """
    Update shared files (1-3) across all sites with controlled rollout
    Maintains site-level isolation for safe testing
    """
    sites = list_all_sites_for_franchise(franchise)

    # Phase 1: Test on pilot site
    pilot_site = test_site or sites[0]
    logger.info(f"[UPDATE] Testing on pilot site: {pilot_site}")

    for filename, content in files_to_update.items():
        if filename in ['01-franchise-core.txt', '02-knowledge.txt', '03-coaching.txt']:
            s3_client.put_object(
                Bucket=bucket,
                Key=f"{franchise}/{pilot_site}/prompts/v6/{filename}",
                Body=content
            )

    # Phase 2: Validate pilot site
    validation_result = validate_site_processing(franchise, pilot_site)
    if not validation_result.success:
        logger.error(f"[UPDATE] Pilot site validation failed: {validation_result.errors}")
        return False

    # Phase 3: Gradual rollout
    batch_size = 5  # Update 5 sites at a time
    for i in range(1, len(sites), batch_size):
        batch = sites[i:i+batch_size]
        logger.info(f"[UPDATE] Updating batch: {batch}")

        for site in batch:
            for filename, content in files_to_update.items():
                s3_client.put_object(
                    Bucket=bucket,
                    Key=f"{franchise}/{site}/prompts/v6/{filename}",
                    Body=content
                )

        # Monitor each batch before proceeding
        time.sleep(300)  # Wait 5 minutes
        for site in batch:
            if not validate_site_processing(franchise, site).success:
                logger.error(f"[UPDATE] Site {site} failed, stopping rollout")
                return False

    logger.info(f"[UPDATE] Successfully updated all {len(sites)} sites")
    return True

def process_transcript(transcript, franchise, site_id):
    """Main processing with Bedrock tool calling"""

    # Load 6-file prompt
    prompt = load_prompt_v6(s3_client, bucket, franchise, site_id)

    # Call Bedrock with tool
    result = ask_claude_for_analysis(
        transcript=transcript,
        prompt_text=prompt
    )

    # Validate core fields strictly
    try:
        analysis = CallAnalysis.model_validate(result)
    except ValidationError as e:
        # Retry once with error feedback
        error_prompt = f"{prompt}\n\nFIX THESE ERRORS:\n{e.errors()}"
        result = ask_claude_for_analysis(transcript, error_prompt)
        analysis = CallAnalysis.model_validate(result)

    return analysis

Site-Specific Output Examples

West Harlem Output

{
  "ai_call_analysis": {
    "call_state": "human_conversation",
    "staff_name": "Ryanne"
  },
  "primary_topic": {
    "category": "sales",
    "subcategory": "intro_booking"
  },
  "site_context": {
    "promotions_mentioned": ["student_discount"],
    "special_programs_discussed": ["6am_warriors"],
    "competitor_mentioned": "equinox"
  },
  "site_specific": {
    "spanish_language_request": false,
    "student_status_mentioned": true,
    "morning_preference_expressed": true
  }
}

Totowa Output (Different Fields)

{
  "ai_call_analysis": {
    "call_state": "human_conversation",
    "staff_name": "Jessica"
  },
  "primary_topic": {
    "category": "sales",
    "subcategory": "membership_inquiry"
  },
  "site_context": {
    "promotions_mentioned": ["family_package"],
    "special_programs_discussed": ["kids_fitness"],
    "competitor_mentioned": null
  },
  "site_specific": {
    "parking_availability_asked": true,
    "family_membership_interest": true,
    "suburban_concerns": true
  }
}

Key Architecture Principles

1. Separation of Concerns

File Purpose Update Frequency Updated By
01-franchise-core Core instructions Quarterly Franchise HQ
02-knowledge Business knowledge Monthly Training team
03-coaching Coaching standards Monthly Operations
04-staff-list Staff names Weekly Studio manager
05-studio-output What to track As needed Studio manager
06-custom-requirements Local context Weekly Studio manager

2. Validation Strategy

  • Core fields: Strict Pydantic validation (must pass)
  • Site context: Flexible Dict (logged if missing expected fields)
  • Site specific: Completely open (experimental metrics)

3. Progressive Enhancement Path

Month 1: Experiment in site_specific{}
Month 3: Promote to site_context{} (semi-structured)
Month 6: Standardize across franchise (add to core model)

Migration Checklist

Phase 1: Current Implementation (v1.0)

  • Split current prompt into 6 files using line mappings
  • Upload all 6 files to {franchise}/{siteId}/prompts/v6/
  • Update Lambda with simple loader function (20 lines)
  • Keep existing Pydantic models (no changes needed)
  • Test concatenation produces valid prompt
  • Deploy to test environment with feature flag
  • Validate output with Bedrock tool calling
  • Production rollout with monitoring

Phase 2: Future Enhancement (v1.5 - When 10+ sites)

  • Create franchise-level folder structure
  • Move files 1-3 to franchise level
  • Update loader with dual-path logic
  • Test backward compatibility
  • Gradual site migration

Benefits Summary

  1. Simplicity: All text files, no JSON schema files needed
  2. Flexibility: Sites add fields without code changes
  3. Standardization: Core fields validated via Pydantic models
  4. Minimal Changes: Only ~20 lines of code for v1.0
  5. Maintainability: Clear separation of what each file controls
  6. Evolution: Start simple, add complexity only when needed
  7. No Schema.json: Pydantic models handle all validation

Future Considerations

v3.1: Industry Expansion

When adding non-fitness franchises:

s3://bucket/
├── fitness/orange-theory/prompts/v6/
├── healthcare/mercy-clinic/prompts/v6/
└── banking/wells-fargo/prompts/v6/

v3.2: Dynamic Loading

# Load industry-specific base model
if industry == "fitness":
    base_model = FitnessCallAnalysis
elif industry == "healthcare":
    base_model = HealthcareCallAnalysis

v3.3: A/B Testing

# Test different prompt versions
if random.random() < 0.5:
    version = "v6"
else:
    version = "v6-experimental"

This architecture provides the foundation for growth from 2 sites to 200+ sites across multiple industries while maintaining quality and flexibility.