Added documentation for the auto-population feature and the analytics integration.
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user