""" Anonymize costs.json with fictional names and randomized numbers. This script: 1. Replaces real names and emails with fictional ones 2. Randomizes all numeric values (tokens, costs) by applying random multipliers """ import json import random from pathlib import Path from typing import Any # Fictional names pool FIRST_NAMES = [ 'Alice', 'Bob', 'Charlie', 'Diana', 'Ethan', 'Fiona', 'George', 'Hannah', 'Isaac', 'Julia', 'Kevin', 'Laura', 'Michael', 'Nina', 'Oliver', 'Petra', 'Quinn', 'Rachel', 'Samuel', 'Teresa', 'Uma', 'Victor', 'Wendy', 'Xavier', 'Yara', 'Zachary', 'Aria', 'Blake', 'Chloe', 'Derek', 'Eva', 'Felix', 'Grace', 'Hugo', 'Iris', 'Jack', 'Kara', 'Liam', 'Maya', 'Noah', ] LAST_NAMES = [ 'Anderson', 'Brown', 'Clark', 'Davis', 'Evans', 'Fischer', 'Garcia', 'Harris', 'Irving', 'Johnson', 'Klein', 'Lopez', 'Miller', 'Nelson', "O'Brien", 'Parker', 'Quinn', 'Robinson', 'Smith', 'Taylor', 'Underwood', 'Vasquez', 'Wilson', 'Xavier', 'Young', 'Zhang', 'Adams', 'Baker', 'Cooper', 'Diaz', 'Edwards', 'Foster', 'Green', 'Hill', 'Jackson', 'King', 'Lee', 'Martinez', 'Moore', 'Nguyen', ] DOMAINS = [ 'techcorp.com', 'innovate.io', 'digitalwave.net', 'cloudify.co', 'datastream.com', 'nexusgroup.com', 'alphatech.io', 'betasystems.net', 'gammasoft.com', 'deltaworks.co', ] def generate_fictional_name() -> str: """Generate a fictional full name.""" return f'{random.choice(FIRST_NAMES)} {random.choice(LAST_NAMES)}' def generate_fictional_email(name: str) -> str: """Generate a fictional email address from a name.""" first, last = name.lower().split() domain = random.choice(DOMAINS) return f'{first}.{last}@{domain}' def generate_username(name: str) -> str: """Generate a username from a name.""" first, last = name.lower().split() suffix = random.choice(['dev', 'prod', 'test', 'staging', 'api']) return f'{first}{last[0]}-{suffix}' def randomize_number(value: float | int, min_factor: float = 0.5, max_factor: float = 1.5) -> float | int: """ Randomize a number by multiplying with a random factor. Args: value: Original value min_factor: Minimum multiplier (default 0.5 = -50%) max_factor: Maximum multiplier (default 1.5 = +50%) Returns: Randomized value (same type as input) """ if value == 0: return value factor = random.uniform(min_factor, max_factor) randomized = value * factor # Preserve integer type for token counts if isinstance(value, int): return int(randomized) return randomized def anonymize_api_key(api_key: dict[str, Any], name_mapping: dict[str, str]) -> dict[str, Any]: """Anonymize a single API key entry.""" # Get or create fictional name for this person original_email = api_key['created_by_email'] if original_email not in name_mapping: fictional_name = generate_fictional_name() name_mapping[original_email] = fictional_name else: fictional_name = name_mapping[original_email] fictional_email = generate_fictional_email(fictional_name) username = generate_username(fictional_name) # Create anonymized copy anonymized = api_key.copy() anonymized['name'] = username anonymized['created_by_name'] = fictional_name anonymized['created_by_email'] = fictional_email anonymized['total_cost'] = randomize_number(api_key['total_cost']) # Randomize time periods anonymized['time_periods'] = [] for period in api_key['time_periods']: anonymized_period = period.copy() # Randomize models anonymized_period['models'] = [] for model in period['models']: anonymized_model = model.copy() # Randomize tokens anonymized_model['tokens'] = { 'input': randomize_number(model['tokens']['input']), 'cache_write': randomize_number(model['tokens']['cache_write']), 'cache_read': randomize_number(model['tokens']['cache_read']), 'output': randomize_number(model['tokens']['output']), 'web_search_requests': randomize_number(model['tokens']['web_search_requests']), } # Randomize costs anonymized_model['cost'] = { 'input': randomize_number(model['cost']['input']), 'cache_write': randomize_number(model['cost']['cache_write']), 'cache_read': randomize_number(model['cost']['cache_read']), 'output': randomize_number(model['cost']['output']), 'total': randomize_number(model['cost']['total']), } anonymized_period['models'].append(anonymized_model) anonymized_period['period_cost'] = randomize_number(period['period_cost']) anonymized['time_periods'].append(anonymized_period) return anonymized def anonymize_costs_file(input_path: Path, output_path: Path) -> None: """ Anonymize costs.json file. Args: input_path: Path to original costs.json output_path: Path to save anonymized version """ print(f'Reading {input_path}...') with open(input_path) as f: data = json.load(f) print(f'Anonymizing {len(data["api_keys"])} API keys...') # Track name mappings to keep consistency across API keys name_mapping: dict[str, str] = {} anonymized_data = {'api_keys': [anonymize_api_key(key, name_mapping) for key in data['api_keys']]} print(f'Writing to {output_path}...') with open(output_path, 'w') as f: json.dump(anonymized_data, f, indent=2) print(f'Done! Created {len(name_mapping)} fictional identities.') print('\nSample mappings:') for original_email, fictional_name in list(name_mapping.items())[:5]: print(f' {original_email} -> {fictional_name}') if __name__ == '__main__': import argparse parser = argparse.ArgumentParser(description='Anonymize costs.json with fictional data') parser.add_argument( '--input', type=Path, default=Path('output/usage/costs.json'), help='Input costs.json file (default: output/usage/costs.json)', ) parser.add_argument( '--output', type=Path, default=Path('output/usage/costs_anonymized.json'), help='Output anonymized file (default: output/usage/costs_anonymized.json)', ) parser.add_argument( '--min-factor', type=float, default=0.5, help='Minimum randomization factor (default: 0.5 = -50%%)', ) parser.add_argument( '--max-factor', type=float, default=1.5, help='Maximum randomization factor (default: 1.5 = +50%%)', ) args = parser.parse_args() # Set random seed for reproducibility (optional - remove for different results each time) random.seed(42) anonymize_costs_file(args.input, args.output)