upgraded to Gemini 3.0 Pro (gemini-3-pro-preview) from Gemini 2.5 Pro
- Upgraded google-genai package from 1.31.0 to 1.52.0 - Updated DEFAULT_MODEL in llm_service.py to gemini-3-pro-preview - Updated all backend routes, services, and models with new model string - Updated all frontend components with new model string and display labels - Updated CLAUDE.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d3aca7c309
commit
4d9b0afde7
19 changed files with 85 additions and 63 deletions
44
CLAUDE.md
44
CLAUDE.md
|
|
@ -15,7 +15,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
- **Start Backend**: `python run.py` (from backend/ directory)
|
||||
- **Backend Server**: Runs on port 5137 with Hypercorn ASGI server
|
||||
- **Database**: MongoDB with PyMongo
|
||||
- **Authentication**: JWT tokens via Flask-JWT-Extended
|
||||
- **Authentication**: Custom Quart-compatible JWT (not Flask-JWT-Extended)
|
||||
|
||||
## Testing
|
||||
**Python Backend**: After modifying any Python files:
|
||||
|
|
@ -26,9 +26,30 @@ python -c "from app import create_app; app = create_app()" # Test app creation
|
|||
```
|
||||
**Frontend**: Run `npm run build` to verify TypeScript compilation
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Real-Time Communication
|
||||
The application uses Socket.IO for real-time WebSocket communication between frontend and backend:
|
||||
- **Backend**: `python-socketio` with `AsyncServer` wrapped in ASGI app
|
||||
- **Frontend**: `socket.io-client` managed via `WebSocketContext`
|
||||
- WebSocket manager (`websocket_manager_async.py`) handles room-based messaging for focus group sessions
|
||||
|
||||
### Autonomous Conversation System
|
||||
Focus group sessions can run autonomously with AI-driven conversations:
|
||||
- `ai_runner_service.py` - Manages background task execution for autonomous mode
|
||||
- `autonomous_conversation_controller.py` - Orchestrates multi-persona conversations
|
||||
- `conversation_decision_service.py` - Determines next speaker and conversation flow
|
||||
- `conversation_context_service.py` - Maintains conversation state and history
|
||||
|
||||
### LLM Integration
|
||||
Multi-model support through `llm_service.py`:
|
||||
- **Google Gemini** (`gemini-3-pro-preview`) - Default model
|
||||
- **OpenAI** (`gpt-4.1`, `gpt-5`) - Alternative models
|
||||
- Prompts are stored as markdown templates in `/backend/prompts/`
|
||||
|
||||
## Code Style Guidelines
|
||||
- **Imports**: Group imports by source (React, third-party, local)
|
||||
- **Types**: Use TypeScript. Project allows nullable types (`strictNullChecks: false`)
|
||||
- **Types**: Use TypeScript. Project allows nullable types (`strictNullChecks: false`)
|
||||
- **Components**: Use functional components with hooks
|
||||
- **Naming**: Use PascalCase for components, camelCase for variables/functions
|
||||
- **Formatting**: Follow ESLint recommendations, focus on readability
|
||||
|
|
@ -41,12 +62,13 @@ python -c "from app import create_app; app = create_app()" # Test app creation
|
|||
|
||||
## Project Stack
|
||||
**Frontend**: Vite, React 18, TypeScript, Tailwind CSS, shadcn-ui
|
||||
**Backend**: Flask 2.2.3, Hypercorn, PyMongo, JWT Extended
|
||||
**Key Libraries**:
|
||||
**Backend**: Quart (async Flask), Hypercorn ASGI, PyMongo, python-socketio
|
||||
**Key Libraries**:
|
||||
- UI: Radix UI components, Lucide React icons
|
||||
- State: TanStack Query, React Hook Form with Zod validation
|
||||
- Routing: React Router DOM
|
||||
- AI/LLM: OpenAI, Google Generative AI
|
||||
- AI/LLM: OpenAI, Google Generative AI (genai)
|
||||
- Real-time: Socket.IO (client and server)
|
||||
- Charts: Recharts
|
||||
- Drag & Drop: DND Kit
|
||||
|
||||
|
|
@ -58,15 +80,15 @@ python -c "from app import create_app; app = create_app()" # Test app creation
|
|||
|
||||
## File Organization
|
||||
- **Backend Services**: `/backend/app/services/` - Business logic and AI integrations
|
||||
- **Backend Models**: `/backend/app/models/` - Data models (User, FocusGroup, Persona)
|
||||
- **Backend Routes**: `/backend/app/routes/` - API endpoints
|
||||
- **AI Prompts**: `/backend/prompts/` - LLM prompt templates
|
||||
- **Frontend Components**:
|
||||
- **Backend Models**: `/backend/app/models/` - Data models (User, FocusGroup, Persona, Folder)
|
||||
- **Backend Routes**: `/backend/app/routes/` - API endpoints (auth, personas, focus-groups, ai-personas, folders, tasks)
|
||||
- **AI Prompts**: `/backend/prompts/` - LLM prompt templates (markdown files loaded by `prompt_loader.py`)
|
||||
- **Frontend Components**:
|
||||
- `/src/components/ui/` - Reusable shadcn-ui components
|
||||
- `/src/components/focus-group-session/` - Focus group specific components
|
||||
- `/src/components/focus-group-session/` - Focus group session UI (DiscussionPanel, ParticipantPanel, ThemesPanel, etc.)
|
||||
- `/src/components/persona/` - Persona management components
|
||||
- **Types**: `/src/types/` - TypeScript type definitions
|
||||
- **Contexts**: `/src/contexts/` - React context providers
|
||||
- **Contexts**: `/src/contexts/` - React context providers (AuthContext, WebSocketContext, NavigationContext)
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class FocusGroup:
|
|||
|
||||
# Set default LLM model if not provided
|
||||
if "llm_model" not in focus_group_data:
|
||||
focus_group_data["llm_model"] = "gemini-2.5-pro"
|
||||
focus_group_data["llm_model"] = "gemini-3-pro-preview"
|
||||
|
||||
# Set default GPT-5 parameters if not provided
|
||||
if "reasoning_effort" not in focus_group_data:
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ async def generate_basic_profiles():
|
|||
temperature = 1.0
|
||||
|
||||
customer_data_session_id = data.get('customer_data_session_id') # Optional parameter
|
||||
llm_model = data.get('llm_model', 'gemini-2.5-pro') # Optional parameter with default
|
||||
llm_model = data.get('llm_model', 'gemini-3-pro-preview') # Optional parameter with default
|
||||
|
||||
try:
|
||||
# Register current task for cancellation
|
||||
|
|
@ -197,7 +197,7 @@ async def complete_and_save_persona():
|
|||
temperature = 1.0
|
||||
|
||||
customer_data_session_id = data.get('customer_data_session_id') # Optional parameter
|
||||
llm_model = data.get('llm_model', 'gemini-2.5-pro') # Optional parameter with default
|
||||
llm_model = data.get('llm_model', 'gemini-3-pro-preview') # Optional parameter with default
|
||||
|
||||
# Get persona name for logging
|
||||
persona_name = basic_profile.get('name', 'Unknown')
|
||||
|
|
@ -816,7 +816,7 @@ async def batch_generate_summaries():
|
|||
if not (0 <= temperature <= 1.5):
|
||||
temperature = 1.0
|
||||
|
||||
llm_model = data.get('llm_model', 'gemini-2.5-pro') # Optional parameter with default
|
||||
llm_model = data.get('llm_model', 'gemini-3-pro-preview') # Optional parameter with default
|
||||
|
||||
# Log the request with model information
|
||||
print(f"🔄 Backend: Received batch-generate-summaries request for {len(persona_ids)} personas with model: {llm_model}")
|
||||
|
|
@ -1013,7 +1013,7 @@ async def generate_personas_full():
|
|||
"count": 5,
|
||||
"temperature": 0.8,
|
||||
"customer_data_session_id": "optional_session_id",
|
||||
"llm_model": "gemini-2.5-pro",
|
||||
"llm_model": "gemini-3-pro-preview",
|
||||
"target_folder_id": "optional_folder_id"
|
||||
}
|
||||
|
||||
|
|
@ -1038,7 +1038,7 @@ async def generate_personas_full():
|
|||
temperature = 1.0
|
||||
|
||||
customer_data_session_id = data.get('customer_data_session_id')
|
||||
llm_model = data.get('llm_model', 'gemini-2.5-pro')
|
||||
llm_model = data.get('llm_model', 'gemini-3-pro-preview')
|
||||
target_folder_id = data.get('target_folder_id')
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ async def generate_ai_response():
|
|||
import datetime
|
||||
log_msg = f"🤖 [{datetime.datetime.now()}] AI RESPONSE - Focus group keys: {list(focus_group.keys())}\n"
|
||||
log_msg += f"🤖 [{datetime.datetime.now()}] AI RESPONSE - Raw llm_model from DB: '{focus_group.get('llm_model')}' (type: {type(focus_group.get('llm_model'))})\n"
|
||||
log_msg += f"🤖 [{datetime.datetime.now()}] AI RESPONSE - Using model: {llm_model or 'default (gemini-2.5-pro)'} for focus group {focus_group_id}\n"
|
||||
log_msg += f"🤖 [{datetime.datetime.now()}] AI RESPONSE - Using model: {llm_model or 'default (gemini-3-pro-preview)'} for focus group {focus_group_id}\n"
|
||||
with open('/tmp/focus_group_debug.log', 'a') as f:
|
||||
f.write(log_msg)
|
||||
f.flush()
|
||||
|
|
@ -93,7 +93,7 @@ async def generate_ai_response():
|
|||
|
||||
current_app.logger.info(f"🔍 DEBUG: Focus group data keys: {list(focus_group.keys())}")
|
||||
current_app.logger.info(f"🔍 DEBUG: Raw llm_model value from DB: '{focus_group.get('llm_model')}' (type: {type(focus_group.get('llm_model'))})")
|
||||
current_app.logger.info(f"🤖 Generating AI response using model: {llm_model or 'default (gemini-2.5-pro)'} for focus group {focus_group_id}")
|
||||
current_app.logger.info(f"🤖 Generating AI response using model: {llm_model or 'default (gemini-3-pro-preview)'} for focus group {focus_group_id}")
|
||||
|
||||
# Validate persona exists
|
||||
persona = await Persona.find_by_id(persona_id)
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ async def modify_persona_with_ai(persona_id):
|
|||
|
||||
Request body should include:
|
||||
- modification_prompt: Natural language description of desired changes
|
||||
- llm_model: Model to use (defaults to 'gemini-2.5-pro')
|
||||
- llm_model: Model to use (defaults to 'gemini-3-pro-preview')
|
||||
- reasoning_effort: For GPT-5 (minimal, low, medium, high)
|
||||
- verbosity: For GPT-5 (low, medium, high)
|
||||
- preview_only: If true, returns modified data without saving to database (defaults to false)
|
||||
|
|
@ -188,7 +188,7 @@ async def modify_persona_with_ai(persona_id):
|
|||
if not modification_prompt:
|
||||
return jsonify({"error": "modification_prompt is required"}), 400
|
||||
|
||||
llm_model = request_data.get('llm_model', 'gemini-2.5-pro')
|
||||
llm_model = request_data.get('llm_model', 'gemini-3-pro-preview')
|
||||
reasoning_effort = request_data.get('reasoning_effort', 'medium')
|
||||
verbosity = request_data.get('verbosity', 'medium')
|
||||
preview_only = request_data.get('preview_only', False)
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ async def _generate_basic_personas_attempt(
|
|||
|
||||
# Log the LLM API call with attempt number
|
||||
attempt_text = f" (attempt {attempt})" if attempt > 1 else ""
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-2.5-pro'} for basic persona generation{attempt_text}")
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-3-pro-preview'} for basic persona generation{attempt_text}")
|
||||
|
||||
raw_response = await LLMService.generate_content(
|
||||
prompt=final_prompt,
|
||||
|
|
@ -504,7 +504,7 @@ async def generate_persona(
|
|||
|
||||
# Log the LLM API call
|
||||
persona_name = basic_persona.get('name', 'Unknown') if basic_persona else 'New Persona'
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-2.5-pro'} for detailed persona generation of '{persona_name}'")
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-3-pro-preview'} for detailed persona generation of '{persona_name}'")
|
||||
|
||||
persona_data = await LLMService.generate_structured_response(
|
||||
prompt=final_prompt,
|
||||
|
|
@ -589,7 +589,7 @@ async def generate_persona_summary(
|
|||
|
||||
# Log the LLM API call
|
||||
persona_name = persona_data.get('name', 'Unknown')
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-2.5-pro'} for summary generation of '{persona_name}'")
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-3-pro-preview'} for summary generation of '{persona_name}'")
|
||||
|
||||
raw_response = await LLMService.generate_content(
|
||||
prompt=final_prompt,
|
||||
|
|
@ -694,7 +694,7 @@ async def generate_persona_download_summary(
|
|||
|
||||
# Log the LLM API call
|
||||
persona_name = persona_data.get('name', 'Unknown')
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-2.5-pro'} for download summary of '{persona_name}'")
|
||||
print(f"🤖 Backend: Making LLM API call to {llm_model or 'gemini-3-pro-preview'} for download summary of '{persona_name}'")
|
||||
|
||||
# Generate the markdown content directly
|
||||
markdown_response = await LLMService.generate_content(
|
||||
|
|
|
|||
|
|
@ -664,7 +664,7 @@ class AutonomousConversationController:
|
|||
llm_model = focus_group.get('llm_model')
|
||||
reasoning_effort = focus_group.get('reasoning_effort', 'medium')
|
||||
verbosity = focus_group.get('verbosity', 'medium')
|
||||
self.logger.info(f"🤖 Autonomous conversation using model: {llm_model or 'default (gemini-2.5-pro)'} for focus group {self.focus_group_id}")
|
||||
self.logger.info(f"🤖 Autonomous conversation using model: {llm_model or 'default (gemini-3-pro-preview)'} for focus group {self.focus_group_id}")
|
||||
|
||||
# Get recent messages
|
||||
messages = await FocusGroup.get_messages(self.focus_group_id)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ async def generate_persona_response(
|
|||
if llm_model == 'gpt-5':
|
||||
print(f" - llm_model: {llm_model} (reasoning_effort: {reasoning_effort or 'medium'}, verbosity: {verbosity or 'medium'}) [using Responses API]")
|
||||
else:
|
||||
print(f" - llm_model: {llm_model or 'default (gemini-2.5-pro)'}")
|
||||
print(f" - llm_model: {llm_model or 'default (gemini-3-pro-preview)'}")
|
||||
|
||||
# Import LLMService at the top to avoid scoping issues
|
||||
from app.services.llm_service import LLMService
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ class FocusGroupService:
|
|||
'content': question.get('content', 'No content')[:100] + '...'
|
||||
})
|
||||
|
||||
logger.info(f"=== CREATIVE REVIEW VALIDATION RESULTS (Model: {llm_model or 'gemini-2.5-pro'}) ===")
|
||||
logger.info(f"=== CREATIVE REVIEW VALIDATION RESULTS (Model: {llm_model or 'gemini-3-pro-preview'}) ===")
|
||||
logger.info(f"Found {creative_review_count} creative_review activities for {len(uploaded_assets)} uploaded assets")
|
||||
|
||||
if creative_review_activities:
|
||||
|
|
@ -236,7 +236,7 @@ class FocusGroupService:
|
|||
# If no creative review activities were generated, retry with enhanced prompt
|
||||
if creative_review_count == 0:
|
||||
logger.warning(f"❌ WARNING: No creative_review activities generated despite {len(uploaded_assets)} uploaded assets!")
|
||||
logger.warning(f"❌ This suggests {llm_model or 'gemini-2.5-pro'} is not following the creative asset instructions")
|
||||
logger.warning(f"❌ This suggests {llm_model or 'gemini-3-pro-preview'} is not following the creative asset instructions")
|
||||
|
||||
# For GPT models, if this was already the enhanced prompt, we have a serious issue
|
||||
if llm_model and llm_model.startswith('gpt') and attempt < max_retries:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class KeyThemeService:
|
|||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"Starting key theme generation for focus group {focus_group_id} with temperature {temperature}")
|
||||
logger.info(f"Using LLM model: {llm_model or 'default (gemini-2.5-pro)'}")
|
||||
logger.info(f"Using LLM model: {llm_model or 'default (gemini-3-pro-preview)'}")
|
||||
|
||||
try:
|
||||
# Get the focus group
|
||||
|
|
@ -105,7 +105,7 @@ class KeyThemeService:
|
|||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"Beginning theme extraction from {len(messages)} messages")
|
||||
logger.info(f"Theme extraction using LLM model: {llm_model or 'default (gemini-2.5-pro)'}")
|
||||
logger.info(f"Theme extraction using LLM model: {llm_model or 'default (gemini-3-pro-preview)'}")
|
||||
|
||||
try:
|
||||
# Load and prepare the prompt for the LLM
|
||||
|
|
@ -135,7 +135,7 @@ class KeyThemeService:
|
|||
|
||||
for attempt in range(max_retries):
|
||||
attempt_num = attempt + 1
|
||||
logger.info(f"Attempt {attempt_num}/{max_retries}: Calling LLM ({llm_model or 'gemini-2.5-pro'}) for theme generation")
|
||||
logger.info(f"Attempt {attempt_num}/{max_retries}: Calling LLM ({llm_model or 'gemini-3-pro-preview'}) for theme generation")
|
||||
|
||||
try:
|
||||
themes = await LLMService.generate_structured_array(
|
||||
|
|
@ -145,7 +145,7 @@ class KeyThemeService:
|
|||
model_name=llm_model
|
||||
)
|
||||
|
||||
logger.info(f"Attempt {attempt_num}/{max_retries}: LLM ({llm_model or 'gemini-2.5-pro'}) call successful, received {len(themes)} themes")
|
||||
logger.info(f"Attempt {attempt_num}/{max_retries}: LLM ({llm_model or 'gemini-3-pro-preview'}) call successful, received {len(themes)} themes")
|
||||
|
||||
# Validate the response structure
|
||||
validated_themes = []
|
||||
|
|
@ -175,7 +175,7 @@ class KeyThemeService:
|
|||
|
||||
validated_themes.append(validated_theme)
|
||||
|
||||
logger.info(f"Theme generation completed successfully with {len(validated_themes)} validated themes using {llm_model or 'gemini-2.5-pro'}")
|
||||
logger.info(f"Theme generation completed successfully with {len(validated_themes)} validated themes using {llm_model or 'gemini-3-pro-preview'}")
|
||||
return validated_themes
|
||||
|
||||
except LLMServiceError as e:
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ gemini_client = genai.Client(api_key=GEMINI_API_KEY)
|
|||
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY', 'REDACTED_OPENAI_KEY')
|
||||
openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY, timeout=600.0)
|
||||
|
||||
# The default model we're using
|
||||
DEFAULT_MODEL = "gemini-2.5-pro"
|
||||
# The default model we're using
|
||||
DEFAULT_MODEL = "gemini-3-pro-preview"
|
||||
|
||||
# Supported models
|
||||
SUPPORTED_MODELS = {
|
||||
'gemini-2.5-pro': 'gemini',
|
||||
'gemini-3-pro-preview': 'gemini',
|
||||
'gpt-4.1': 'openai',
|
||||
'gpt-5': 'openai'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ class PersonaModificationService:
|
|||
async def modify_persona(
|
||||
persona_id: str,
|
||||
modification_prompt: str,
|
||||
llm_model: str = 'gemini-2.5-pro',
|
||||
llm_model: str = 'gemini-3-pro-preview',
|
||||
reasoning_effort: str = 'medium',
|
||||
verbosity: str = 'medium',
|
||||
max_retries: int = 3,
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ export default function AIRecruiter({ targetFolderId, targetFolderName }: AIRecr
|
|||
if (response.partial_success || (response.errors && response.errors.length > 0)) {
|
||||
// Some personas succeeded but others failed
|
||||
toast.success("Some personas generated successfully", {
|
||||
description: `${personas.length} synthetic personas were created using ${values.llm_model || 'Gemini 2.5 Pro'}. ${response.errors?.length || 0} failed due to timeout or other errors.`,
|
||||
description: `${personas.length} synthetic personas were created using ${values.llm_model || 'Gemini 3 Pro'}. ${response.errors?.length || 0} failed due to timeout or other errors.`,
|
||||
duration: 8000
|
||||
});
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ export default function AIRecruiter({ targetFolderId, targetFolderName }: AIRecr
|
|||
} else {
|
||||
// All personas succeeded
|
||||
toast.success("Personas generated and saved successfully", {
|
||||
description: `${personas.length} synthetic personas have been created using ${values.llm_model || 'Gemini 2.5 Pro'} and saved ${targetFolderId ? `to the "${targetFolderName}" folder` : 'to the database'}.`
|
||||
description: `${personas.length} synthetic personas have been created using ${values.llm_model || 'Gemini 3 Pro'} and saved ${targetFolderId ? `to the "${targetFolderName}" folder` : 'to the database'}.`
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ export default function FocusGroupModerator({ draftToEdit, onDraftSaved, preSele
|
|||
focusGroupName: "",
|
||||
discussionTopics: "",
|
||||
duration: "60",
|
||||
llm_model: "gemini-2.5-pro",
|
||||
llm_model: "gemini-3-pro-preview",
|
||||
reasoning_effort: "medium",
|
||||
verbosity: "medium",
|
||||
},
|
||||
|
|
@ -554,7 +554,7 @@ export default function FocusGroupModerator({ draftToEdit, onDraftSaved, preSele
|
|||
objective: values.researchBrief || '',
|
||||
topic: values.discussionTopics || '',
|
||||
duration: values.duration ? parseInt(values.duration) : 60,
|
||||
llm_model: values.llm_model || 'gemini-2.5-pro',
|
||||
llm_model: values.llm_model || 'gemini-3-pro-preview',
|
||||
reasoning_effort: values.reasoning_effort || 'medium',
|
||||
verbosity: values.verbosity || 'medium',
|
||||
participants: selectedParticipants,
|
||||
|
|
@ -692,7 +692,7 @@ export default function FocusGroupModerator({ draftToEdit, onDraftSaved, preSele
|
|||
topic: values.discussionTopics || '',
|
||||
description: values.researchBrief || '',
|
||||
objective: values.researchBrief || '',
|
||||
llm_model: values.llm_model || 'gemini-2.5-pro',
|
||||
llm_model: values.llm_model || 'gemini-3-pro-preview',
|
||||
reasoning_effort: values.reasoning_effort || 'medium',
|
||||
verbosity: values.verbosity || 'medium',
|
||||
discussionGuide: sourceFocusGroup.discussionGuide
|
||||
|
|
@ -860,7 +860,7 @@ export default function FocusGroupModerator({ draftToEdit, onDraftSaved, preSele
|
|||
objective: draftToEdit.description || draftToEdit.objective || '',
|
||||
topic: draftToEdit.topic || '',
|
||||
duration: draftToEdit.duration || 60,
|
||||
llm_model: draftToEdit.llm_model || 'gemini-2.5-pro',
|
||||
llm_model: draftToEdit.llm_model || 'gemini-3-pro-preview',
|
||||
reasoning_effort: draftToEdit.reasoning_effort || 'medium',
|
||||
verbosity: draftToEdit.verbosity || 'medium',
|
||||
participants: draftToEdit.participants || [],
|
||||
|
|
@ -1580,7 +1580,7 @@ true;
|
|||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="gemini-2.5-pro">Gemini 2.5 Pro</SelectItem>
|
||||
<SelectItem value="gemini-3-pro-preview">Gemini 3 Pro</SelectItem>
|
||||
<SelectItem value="gpt-4.1">GPT-4.1</SelectItem>
|
||||
<SelectItem value="gpt-5">GPT-5</SelectItem>
|
||||
</SelectContent>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default function AIRecruiterForm({ onSubmit, isGenerating }: AIRecruiterF
|
|||
researchObjective: "",
|
||||
personaCount: "5",
|
||||
temperature: 1.0,
|
||||
llm_model: "gemini-2.5-pro",
|
||||
llm_model: "gemini-3-pro-preview",
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -380,7 +380,7 @@ export default function AIRecruiterForm({ onSubmit, isGenerating }: AIRecruiterF
|
|||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="gemini-2.5-pro">Gemini 2.5 Pro</SelectItem>
|
||||
<SelectItem value="gemini-3-pro-preview">Gemini 3 Pro</SelectItem>
|
||||
<SelectItem value="gpt-4.1">GPT-4.1</SelectItem>
|
||||
<SelectItem value="gpt-5">GPT-5</SelectItem>
|
||||
</SelectContent>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default function PersonaModificationModal({
|
|||
resolver: zodResolver(modificationFormSchema),
|
||||
defaultValues: {
|
||||
modificationPrompt: "",
|
||||
llm_model: "gemini-2.5-pro",
|
||||
llm_model: "gemini-3-pro-preview",
|
||||
reasoning_effort: "medium",
|
||||
verbosity: "medium",
|
||||
},
|
||||
|
|
@ -221,7 +221,7 @@ export default function PersonaModificationModal({
|
|||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="gemini-2.5-pro">Gemini 2.5 Pro</SelectItem>
|
||||
<SelectItem value="gemini-3-pro-preview">Gemini 3 Pro</SelectItem>
|
||||
<SelectItem value="gpt-4.1">GPT-4.1</SelectItem>
|
||||
<SelectItem value="gpt-5">GPT-5</SelectItem>
|
||||
</SelectContent>
|
||||
|
|
|
|||
|
|
@ -730,11 +730,11 @@ const FocusGroupSession = () => {
|
|||
duration: data.duration || 60,
|
||||
topic: data.topic || 'general',
|
||||
discussionGuide: data.discussionGuide || '',
|
||||
llm_model: data.llm_model || 'gemini-2.5-pro'
|
||||
llm_model: data.llm_model || 'gemini-3-pro-preview'
|
||||
};
|
||||
|
||||
setFocusGroup(focusGroupData);
|
||||
setSelectedModel(focusGroupData.llm_model || 'gemini-2.5-pro');
|
||||
setSelectedModel(focusGroupData.llm_model || 'gemini-3-pro-preview');
|
||||
setSelectedReasoningEffort(focusGroupData.reasoning_effort || 'medium');
|
||||
setSelectedVerbosity(focusGroupData.verbosity || 'medium');
|
||||
|
||||
|
|
@ -816,7 +816,7 @@ const FocusGroupSession = () => {
|
|||
} : null);
|
||||
toastService.success('AI Model Updated', {
|
||||
description: `Focus group will now use ${
|
||||
newModel === 'gemini-2.5-pro' ? 'Gemini 2.5 Pro' :
|
||||
newModel === 'gemini-3-pro-preview' ? 'Gemini 3 Pro' :
|
||||
newModel === 'gpt-4.1' ? 'GPT-4.1' :
|
||||
newModel === 'gpt-5' ? 'GPT-5' : newModel
|
||||
} for AI responses`
|
||||
|
|
@ -869,11 +869,11 @@ const FocusGroupSession = () => {
|
|||
duration: data.duration || 60,
|
||||
topic: data.topic || 'general',
|
||||
discussionGuide: data.discussionGuide || '',
|
||||
llm_model: data.llm_model || 'gemini-2.5-pro'
|
||||
llm_model: data.llm_model || 'gemini-3-pro-preview'
|
||||
};
|
||||
|
||||
setFocusGroup(focusGroupData);
|
||||
setSelectedModel(focusGroupData.llm_model || 'gemini-2.5-pro');
|
||||
setSelectedModel(focusGroupData.llm_model || 'gemini-3-pro-preview');
|
||||
setSelectedReasoningEffort(focusGroupData.reasoning_effort || 'medium');
|
||||
setSelectedVerbosity(focusGroupData.verbosity || 'medium');
|
||||
|
||||
|
|
@ -1932,7 +1932,7 @@ const FocusGroupSession = () => {
|
|||
<Bot className="h-3 w-3 text-slate-500 mr-1" />
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{focusGroup.llm_model === 'gpt-4.1' ? 'GPT-4.1' :
|
||||
focusGroup.llm_model === 'gpt-5' ? 'GPT-5' : 'Gemini 2.5 Pro'}
|
||||
focusGroup.llm_model === 'gpt-5' ? 'GPT-5' : 'Gemini 3 Pro'}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2294,7 +2294,7 @@ const FocusGroupSession = () => {
|
|||
<span className="text-sm font-medium">Current Model:</span>
|
||||
<Badge variant="secondary">
|
||||
{focusGroup?.llm_model === 'gpt-4.1' ? 'GPT-4.1' :
|
||||
focusGroup?.llm_model === 'gpt-5' ? 'GPT-5' : 'Gemini 2.5 Pro'}
|
||||
focusGroup?.llm_model === 'gpt-5' ? 'GPT-5' : 'Gemini 3 Pro'}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
|
|
@ -2308,7 +2308,7 @@ const FocusGroupSession = () => {
|
|||
<SelectValue placeholder="Select AI model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="gemini-2.5-pro">Gemini 2.5 Pro</SelectItem>
|
||||
<SelectItem value="gemini-3-pro-preview">Gemini 3 Pro</SelectItem>
|
||||
<SelectItem value="gpt-4.1">GPT-4.1</SelectItem>
|
||||
<SelectItem value="gpt-5">GPT-5</SelectItem>
|
||||
</SelectContent>
|
||||
|
|
@ -2364,7 +2364,7 @@ Controls how thoroughly GPT-5 thinks and how detailed responses are
|
|||
)}
|
||||
|
||||
<div className="text-xs text-slate-600">
|
||||
<p><strong>Gemini 2.5 Pro:</strong> Google's advanced model, great for creative and analytical tasks.</p>
|
||||
<p><strong>Gemini 3 Pro:</strong> Google's advanced model, great for creative and analytical tasks.</p>
|
||||
<p><strong>GPT-4.1:</strong> OpenAI's latest model, excellent for conversational and reasoning tasks.</p>
|
||||
<p><strong>GPT-5:</strong> OpenAI's newest model with advanced reasoning and customizable response styles.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ const SyntheticUsers = () => {
|
|||
});
|
||||
// LLM selection for download
|
||||
const [downloadLlmModalOpen, setDownloadLlmModalOpen] = useState(false);
|
||||
const [selectedDownloadLlmModel, setSelectedDownloadLlmModel] = useState<string>('gemini-2.5-pro');
|
||||
const [selectedDownloadLlmModel, setSelectedDownloadLlmModel] = useState<string>('gemini-3-pro-preview');
|
||||
|
||||
// Bulk export no longer needs state - direct download
|
||||
|
||||
|
|
@ -1057,7 +1057,7 @@ const SyntheticUsers = () => {
|
|||
summaryGenerationControls.completeGeneration();
|
||||
|
||||
// Show success toast with details including model information
|
||||
const modelDisplayName = selectedDownloadLlmModel === 'gpt-4.1' ? 'GPT-4.1' : 'Gemini 2.5 Pro';
|
||||
const modelDisplayName = selectedDownloadLlmModel === 'gpt-4.1' ? 'GPT-4.1' : 'Gemini 3 Pro';
|
||||
if (summary_stats.total_successful === summary_stats.total_requested) {
|
||||
toastService.success("Persona summary downloaded", {
|
||||
description: `Successfully processed all ${summary_stats.total_successful} persona${summary_stats.total_successful !== 1 ? 's' : ''} from "${folderName}" using ${modelDisplayName}`
|
||||
|
|
@ -1929,9 +1929,9 @@ const SyntheticUsers = () => {
|
|||
className="space-y-3"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="gemini-2.5-pro" id="download-gemini" />
|
||||
<RadioGroupItem value="gemini-3-pro-preview" id="download-gemini" />
|
||||
<Label htmlFor="download-gemini" className="text-sm font-medium">
|
||||
Gemini 2.5 Pro
|
||||
Gemini 3 Pro
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export async function generateSyntheticPersonas(
|
|||
): Promise<{personas: Persona[], task_id?: string, partial_success?: boolean, errors?: any[]}> {
|
||||
// Debug logging for folder and model
|
||||
console.log(`generateSyntheticPersonas called with targetFolderId: ${targetFolderId || 'none'}`);
|
||||
console.log(`🔄 generateSyntheticPersonas using model: ${llmModel || 'gemini-2.5-pro'}`);
|
||||
console.log(`🔄 generateSyntheticPersonas using model: ${llmModel || 'gemini-3-pro-preview'}`);
|
||||
|
||||
try {
|
||||
// We'll use the two-stage approach
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue