# Provider Switching for AI Autofill

## Overview

This document clarifies that AI autofill **already supports provider switching** via the `GPT_PROVIDER` environment variable, similar to how blog writer and story writer handle provider selection.

## Current Architecture

### AI Autofill Flow

```
AIStructuredAutofillService.generate_autofill_fields()
  ↓
AIServiceManager.execute_structured_json_call()
  ↓
AIServiceManager._call_llm_with_checks()
  ↓
llm_text_gen() from main_text_generation.py
  ↓
Provider Selection (based on GPT_PROVIDER env var)
  ↓
gemini_provider OR huggingface_provider
```

### Provider Switching Pattern

**File**: `backend/services/ai_service_manager.py`

The `AIServiceManager.execute_structured_json_call()` method already uses `llm_text_gen()` from `main_text_generation.py`, which supports provider switching:

```python
def _call_llm_with_checks(self, prompt: str, schema: Dict[str, Any], user_id: str):
    """Call LLM through main_text_generation with subscription checks."""
    from services.llm_providers.main_text_generation import llm_text_gen
    
    # Call through main_text_generation for subscription checks
    result = llm_text_gen(
        prompt=prompt,
        json_struct=schema,
        user_id=user_id  # Pass user_id for subscription checks
    )
    return result
```

**File**: `backend/services/llm_providers/main_text_generation.py`

The `llm_text_gen()` function already supports provider switching via `GPT_PROVIDER` environment variable:

```python
def llm_text_gen(prompt: str, system_prompt: Optional[str] = None, json_struct: Optional[Dict[str, Any]] = None, user_id: str = None):
    # Check for GPT_PROVIDER environment variable
    env_provider = os.getenv('GPT_PROVIDER', '').lower()
    if env_provider in ['gemini', 'google']:
        gpt_provider = "google"
        model = "gemini-2.0-flash-001"
    elif env_provider in ['hf_response_api', 'huggingface', 'hf']:
        gpt_provider = "huggingface"
        model = "openai/gpt-oss-120b:groq"
    
    # Auto-detect based on available API keys if no env var
    if not env_provider:
        api_key_manager = APIKeyManager()
        if api_key_manager.get_api_key("gemini"):
            gpt_provider = "google"
        elif api_key_manager.get_api_key("hf_token"):
            gpt_provider = "huggingface"
    
    # Route to appropriate provider
    if gpt_provider == "google":
        if json_struct:
            response_text = gemini_structured_json_response(...)
        else:
            response_text = gemini_text_response(...)
    elif gpt_provider == "huggingface":
        if json_struct:
            response_text = huggingface_structured_json_response(...)
        else:
            response_text = huggingface_text_response(...)
```

## Comparison with Blog Writer and Story Writer

### Blog Writer Pattern

**File**: `backend/api/blog_writer/content/enhanced_content_generator.py`

```python
from services.llm_providers.main_text_generation import llm_text_gen

async def generate_section(self, section: Any, research: Any, mode: str = "polished"):
    # Provider-agnostic text generation (respect GPT_PROVIDER & circuit-breaker)
    ai_resp = llm_text_gen(
        prompt=prompt,
        json_struct=None,
        system_prompt=None,
    )
```

### Story Writer Pattern

Story writer follows the same pattern - uses `llm_text_gen()` from `main_text_generation.py` which respects `GPT_PROVIDER`.

### AI Autofill Pattern

**File**: `backend/api/content_planning/services/content_strategy/autofill/ai_structured_autofill.py`

```python
from services.ai_service_manager import AIServiceManager, AIServiceType

class AIStructuredAutofillService:
    def __init__(self):
        self.ai = AIServiceManager()  # Uses AIServiceManager, not direct provider
    
    async def generate_autofill_fields(self, user_id: int, context: Dict[str, Any]):
        result = await self.ai.execute_structured_json_call(
            service_type=AIServiceType.STRATEGIC_INTELLIGENCE,
            prompt=prompt,
            schema=schema
        )
        # AIServiceManager routes to llm_text_gen() which respects GPT_PROVIDER
```

## Supported Providers

### Google Gemini (Default)

- **Environment Variable**: `GPT_PROVIDER=gemini` or `GPT_PROVIDER=google`
- **Model**: `gemini-2.0-flash-001`
- **Structured JSON**: `gemini_structured_json_response()`
- **Text Generation**: `gemini_text_response()`

### HuggingFace

- **Environment Variable**: `GPT_PROVIDER=huggingface` or `GPT_PROVIDER=hf` or `GPT_PROVIDER=hf_response_api`
- **Model**: `openai/gpt-oss-120b:groq`
- **Structured JSON**: `huggingface_structured_json_response()`
- **Text Generation**: `huggingface_text_response()`

## Configuration

### Environment Variable

Set `GPT_PROVIDER` environment variable to control provider selection:

```bash
# Use Google Gemini
export GPT_PROVIDER=gemini

# Use HuggingFace
export GPT_PROVIDER=huggingface
```

### Auto-Detection

If `GPT_PROVIDER` is not set, the system auto-detects based on available API keys:

1. **Gemini**: If `GEMINI_API_KEY` is configured, uses Gemini
2. **HuggingFace**: If `HF_TOKEN` is configured and Gemini is not available, uses HuggingFace

### API Key Configuration

Ensure API keys are configured in the environment:

```bash
# For Gemini
export GEMINI_API_KEY=your_gemini_api_key

# For HuggingFace
export HF_TOKEN=your_huggingface_token
```

## Key Points

### ✅ Already Supported

1. **Provider Switching**: AI autofill already supports provider switching via `GPT_PROVIDER` env var
2. **Consistent Pattern**: Uses the same pattern as blog writer and story writer (`llm_text_gen()`)
3. **No Hardcoding**: Not hardcoded to `gemini_provider` - routes through `main_text_generation.py`
4. **HuggingFace Support**: Already supports HuggingFace provider

### Architecture Benefits

1. **Consistent Provider Selection**: All AI features use the same provider selection logic
2. **Subscription Checks**: All AI calls go through `llm_text_gen()` which includes subscription checks
3. **Usage Tracking**: All AI calls are tracked through the same usage tracking system
4. **Provider Abstraction**: AI autofill doesn't need to know about specific providers

## Migration Notes

### No Changes Required

The AI autofill code **does not need any changes** - it already uses the correct pattern:

- ✅ Uses `AIServiceManager.execute_structured_json_call()`
- ✅ Routes through `llm_text_gen()` from `main_text_generation.py`
- ✅ Respects `GPT_PROVIDER` environment variable
- ✅ Supports both Gemini and HuggingFace

### Verification

To verify provider switching works:

1. Set `GPT_PROVIDER=huggingface` in environment
2. Call AI autofill endpoint
3. Check logs for provider used (should show "huggingface")
4. Verify structured JSON response format

## Summary

**AI autofill already supports provider switching** - no code changes are required. The system uses the same provider selection pattern as blog writer and story writer, routing through `llm_text_gen()` from `main_text_generation.py`, which respects the `GPT_PROVIDER` environment variable and supports both Gemini and HuggingFace providers.
