Yufan_Zhou
Refactor: Match reference version parameter passing logic
db7d8fe
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Web API bridge script for handling inputs from the web interface
and generating user personas following the logic in generate_profile.py.
"""
import json
import argparse
import sys
import os
from typing import Dict, Any, List, Optional
# Import required modules
from based_data import (
generate_age_info,
generate_gender,
generate_career_info,
generate_location,
generate_personal_values,
generate_life_attitude,
generate_personal_story,
generate_interests_and_hobbies
)
from generate_profile import generate_final_summary
from select_attributes import get_selected_attributes, save_results
def parse_input_data(input_file: str) -> Dict[str, Any]:
"""
Parse data from the input file
Args:
input_file: Path to the input JSON file
Returns:
Dict: Parsed input data
"""
try:
with open(input_file, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
except Exception as e:
print(f"Error parsing input file: {e}")
return {}
def generate_profile_from_input(input_data: Dict[str, Any], attribute_count: int = 200) -> Dict[str, Any]:
"""
Generate a complete user persona from input data
Args:
input_data: Input data containing basic information and optional custom values
attribute_count: Number of attributes to generate (default: 200)
Returns:
Dict: Generated complete user persona
"""
try:
# Extract basic information from input data
basic_info = input_data.get('basic_info', {})
# Extract custom values if provided
custom_values = input_data.get('custom_values', {})
# Use provided basic information or generate new basic information
age = basic_info.get('age')
if not age:
print("βœ— Age not provided, generating...")
age_info = generate_age_info()
age = age_info['age']
else:
print(f"βœ“ Using provided age: {age}")
gender = basic_info.get('gender')
if not gender:
print("βœ— Gender not provided, generating...")
gender = generate_gender()
else:
print(f"βœ“ Using provided gender: {gender}")
occupation_info = basic_info.get('occupation', {})
occupation = occupation_info.get('status')
if not occupation:
print("βœ— Occupation not provided, generating...")
career_info = generate_career_info(age)
occupation = career_info['status']
else:
print(f"βœ“ Using provided occupation: {occupation}")
location_info = basic_info.get('location', {})
if not location_info.get('city') or not location_info.get('country'):
print("βœ— Location not provided, generating...")
location_info = generate_location()
else:
print(f"βœ“ Using provided location: {location_info.get('city')}, {location_info.get('country')}")
# Use custom personal values if provided, otherwise generate them
custom_personal_values = custom_values.get('personal_values')
if custom_personal_values and custom_personal_values.strip():
print(f"βœ“ Using provided personal values: {custom_personal_values[:50]}...")
values_orientation = custom_personal_values.strip()
else:
print("βœ— Personal values not provided, generating based on inputs...")
values_dict = generate_personal_values(age, gender, occupation, location_info)
values_orientation = values_dict.get("values_orientation", "") if isinstance(values_dict, dict) else str(values_dict)
# Use custom life attitude if provided, otherwise generate it
custom_life_attitude = custom_values.get('life_attitude')
if custom_life_attitude and custom_life_attitude.strip():
print(f"βœ“ Using provided life attitude: {custom_life_attitude[:50]}...")
life_attitude = {
"outlook": custom_life_attitude.strip(),
"coping_mechanism": "Custom life attitude provided by user"
}
else:
print("βœ— Life attitude not provided, generating based on inputs...")
life_attitude = generate_life_attitude(age, gender, occupation, location_info, values_orientation)
# Use custom life story if provided, otherwise generate it
custom_life_story = custom_values.get('life_story')
if custom_life_story and custom_life_story.strip():
print(f"βœ“ Using provided life story: {custom_life_story[:50]}...")
personal_story = {"personal_story": custom_life_story.strip()}
else:
print("βœ— Life story not provided, generating based on inputs...")
personal_story = generate_personal_story(age, gender, occupation, location_info, values_orientation, life_attitude)
# Use custom interests/hobbies if provided, otherwise generate them
custom_interests = custom_values.get('interests_hobbies')
if custom_interests and custom_interests.strip():
print(f"βœ“ Using provided interests: {custom_interests}")
# Split by comma and clean up
interests_list = [i.strip() for i in custom_interests.split(',') if i.strip()]
interests_and_hobbies = {"interests": interests_list}
else:
print("βœ— Interests not provided, generating based on life story...")
interests_and_hobbies = generate_interests_and_hobbies(personal_story)
# Build complete user persona (matching reference version structure)
profile = {
"basic_info": {
"age": age,
"gender": gender,
"occupation": {"status": occupation},
"location": location_info
},
"values_orientation": values_orientation,
"life_attitude": life_attitude,
"personal_story": personal_story,
"interests_and_hobbies": interests_and_hobbies
}
# Select attributes
print(f"Selecting {attribute_count} attributes...")
# Pass the profile directly to get_selected_attributes
selected_paths = get_selected_attributes(profile, attribute_count)
profile["selected_attributes"] = selected_paths
# Save the selected attributes to output files
print("Saving selected attributes...")
save_results(profile, selected_paths)
# Generate final summary
print("Generating final summary...")
summary = generate_final_summary(profile)
profile["Summary"] = summary
return profile
except Exception as e:
print(f"Error generating user persona: {e}")
import traceback
traceback.print_exc()
return {}
def main():
"""Main function to process command line arguments and execute generation workflow"""
parser = argparse.ArgumentParser(description="Generate user persona from input data")
parser.add_argument('--input', type=str, required=True, help="Path to input JSON file")
parser.add_argument('--attributes', type=int, default=200, help="Number of attributes to generate (default: 200)")
args = parser.parse_args()
# Parse input data
input_data = parse_input_data(args.input)
if not input_data:
print("Unable to parse input data, exiting")
sys.exit(1)
# Generate user persona
profile = generate_profile_from_input(input_data, attribute_count=args.attributes)
if not profile:
print("Failed to generate user persona, exiting")
sys.exit(1)
# Output results
if "Summary" in profile:
print("\n" + "="*50)
print("Generated User Persona Summary:")
print("="*50)
print(profile["Summary"])
print("="*50)
# Output the profile as JSON to stdout for the Next.js API to capture
# Clean the summary for JSON output
if "Summary" in profile:
cleaned_summary = profile["Summary"].replace("`", "")
cleaned_summary = cleaned_summary.replace('"', "'")
profile["Summary"] = cleaned_summary
# Format for API output - clean newlines for JSON compatibility
if "Summary" in profile:
profile["Summary"] = profile["Summary"].replace('\n', " ")
print(f'\n{{"summary": "{profile["Summary"]}"}}\n')
else:
print("Failed to generate summary")
sys.exit(1)
# Output the full profile as JSON
print(json.dumps(profile, ensure_ascii=False))
if __name__ == "__main__":
main()