feat: convert to nextjs

This commit is contained in:
2024-12-07 07:45:24 +01:00
parent b248ee80ee
commit 633b8ee207
52 changed files with 4121 additions and 982 deletions

75
utils/consumer/prompt.ts Normal file
View File

@@ -0,0 +1,75 @@
import { Moment } from 'moment';
export function generatePrompt(
letters: string,
birthday: Moment,
zipCode: string
): string {
return `You are tasked with creating a detailed consumer of an Italian individual based on the following seed information:
<consumer_seed>
<name_letters>${letters}</name_letters>
<birthday>${birthday.format('YYYY-MM-DD')}</birthday>
<zip_code>${zipCode}</zip_code>
</consumer_seed>
Your goal is to generate a realistic and diverse consumer that reflects the complexity of Italian society. Follow these steps to create the consumer:
1. Analyze the demographic data:
- Create a full name that includes ALL the letters provided in <name_letters>, though it may contain additional letters.
- Consider the implications of the birth year and postal code on the person's background and lifestyle.
2. Generate core demographics:
- Name and age (derived from the seed information)
- Occupation (including title, level, approximate income, location, and schedule)
- Home situation (residence type, ownership status, location)
- Household (relationship status, family members, pets if any)
3. Describe daily patterns:
- Detailed weekday schedule with approximate times and locations
- Typical weekend activities
- Commute details (transportation method, route, regular stops if applicable)
4. Define preferences and behaviors:
- Financial management style
- Brand relationships (with loyalty scores from 1 to 10)
- Preferred payment methods
5. Outline a financial profile:
- Fixed monthly expenses:
* Housing: rent/mortgage payments
* Utilities: electricity, gas, water, waste management
* Internet and phone services
* Insurance payments (home, car, health, life)
* Property taxes (if applicable)
- Regular subscriptions:
* Digital services (streaming, apps, etc.)
* Memberships (gym, clubs, etc.)
* Regular services (cleaning, maintenance, etc.)
- Category-specific spending patterns
- Impulse buying tendency (score from 1 to 10)
6. Describe regular activities:
- Exercise routines or lack thereof
- Social activities
7. Add consumerl context:
- Key stress triggers
- Reward behaviors
- Upcoming significant events
Throughout this process, consider the following:
- Ensure a diverse representation of technological aptitudes, not focusing solely on tech-savvy individuals.
- Use inclusive language and avoid stereotypes or discriminatory assumptions.
- Align numerical scores (1-10) and monetary values (in EUR) with:
a) Regional economic indicators
b) Generational trends
c) Professional sector norms
d) Local cost of living
Before providing the final consumer, wrap your analysis in <consumer_creation_process> tags. For each major section:
1. Break down the postal code implications on the person's background and lifestyle.
2. Consider multiple options for each aspect (at least 2-3 choices).
3. Explain your reasoning for the final choice.
This will help ensure a thorough and well-reasoned consumer creation.`;
}

54
utils/consumer/store.ts Normal file
View File

@@ -0,0 +1,54 @@
import 'dotenv/config';
import { Consumer, consumerSchema } from './types';
import { Tool } from './tool';
import { BaseTool, makeRequest } from '../anthropicClient';
import { generatePrompt } from './prompt';
import { generateConsumerSeed } from '@utils/generateConsumerSeed';
import prisma from '../../prisma/prisma';
export async function generate() {
const { letters, birthday, zipCode } = generateConsumerSeed();
const newConsumer = await prisma.consumer.create({
data: {
letters,
birthday: birthday.toDate(),
zipCode
}
});
console.info(`New consumer being generated with id ${newConsumer.id}`);
const prompt = generatePrompt(letters, birthday, zipCode);
try {
const result = (await makeRequest(prompt, Tool as BaseTool)) as Consumer;
const validConsumer = consumerSchema.safeParse(result);
if (validConsumer.error) {
throw Error(`Invalid consumer generated: ${validConsumer.error.message}`);
}
console.info('Generated consumer by Anthropic', validConsumer.data);
await prisma.consumer.update({
where: {
id: newConsumer.id
},
data: {
value: validConsumer.data
}
});
console.info(`Consumer with id ${newConsumer.id} stored in database.`);
return {
id: newConsumer.id,
consumer: validConsumer.data
};
} catch (error) {
console.error('Error generating purchases:', error);
throw error;
}
}

408
utils/consumer/tool.ts Normal file
View File

@@ -0,0 +1,408 @@
export const Tool = {
name: 'ConsumerSchema' as const,
input_schema: {
type: 'object' as const,
description: 'User consumer',
properties: {
core: {
type: 'object' as const,
description: 'Core user information and demographics',
properties: {
age: {
type: 'number' as const,
description: "User's age in years"
},
name: {
type: 'string' as const,
description: "User's full name"
},
occupation: {
type: 'object' as const,
description: 'Employment details',
properties: {
title: {
type: 'string' as const,
description: 'Job title'
},
level: {
type: 'string' as const,
description: 'Career level (e.g., entry, senior, manager)'
},
income: {
type: 'number' as const,
description: 'Annual income'
},
location: {
type: 'string' as const,
description: 'Work location'
},
schedule: {
type: 'array' as const,
description: 'Working days/hours',
items: {
type: 'string' as const
}
}
}
},
home: {
type: 'object' as const,
description: 'Housing information',
properties: {
type: {
type: 'string' as const,
description: 'Type of residence (e.g., apartment, house)'
},
ownership: {
type: 'string' as const,
description: 'Ownership status (e.g., owned, rented)'
},
location: {
type: 'string' as const,
description: 'Home address or area'
},
commute_distance_km: {
type: 'number' as const,
description: 'Distance to work in kilometers'
}
}
},
household: {
type: 'object' as const,
description: 'Household composition',
properties: {
status: {
type: 'string' as const,
description: 'Marital/living status'
},
members: {
type: 'array' as const,
description: 'Other household members',
items: {
type: 'string' as const
}
},
pets: {
type: 'array' as const,
description: 'Household pets',
items: {
type: 'object' as const,
properties: {
type: {
type: 'string' as const,
description: 'Type of pet'
},
name: {
type: 'string' as const,
description: "Pet's name"
}
}
}
}
}
}
}
},
routines: {
type: 'object' as const,
description: 'Daily and weekly routines',
properties: {
weekday: {
type: 'object' as const,
description: 'Typical weekday schedule',
additionalProperties: {
type: 'object' as const,
properties: {
activity: {
type: 'string' as const,
description: 'Activity description'
},
location: {
type: 'string' as const,
description: 'Location of activity'
},
duration_minutes: {
type: 'number' as const,
description: 'Duration in minutes'
}
}
}
},
weekend: {
type: 'array' as const,
description: 'Regular weekend activities',
items: {
type: 'string' as const
}
},
commute: {
type: 'object' as const,
description: 'Commute details',
properties: {
method: {
type: 'string' as const,
description: 'Primary mode of transportation'
},
route: {
type: 'array' as const,
description: 'Regular route points',
items: {
type: 'string' as const
}
},
regular_stops: {
type: 'array' as const,
description: 'Regular stops during commute',
items: {
type: 'object' as const,
properties: {
location: {
type: 'string' as const,
description: 'Stop location'
},
purpose: {
type: 'string' as const,
description: 'Purpose of stop'
},
frequency: {
type: 'string' as const,
description: 'How often this stop is made'
}
}
}
}
}
}
}
},
preferences: {
type: 'object' as const,
description: 'User preferences and habits',
properties: {
diet: {
type: 'array' as const,
description: 'Dietary preferences and restrictions',
items: {
type: 'string' as const
}
},
brands: {
type: 'array' as const,
description: 'Brand preferences',
items: {
type: 'object' as const,
properties: {
name: {
type: 'string' as const,
description: 'Brand name'
},
loyalty_score: {
type: 'number' as const,
description: 'Brand loyalty score (1-10)',
minimum: 1,
maximum: 10
}
}
}
},
price_sensitivity: {
type: 'number' as const,
description: 'Price sensitivity score (1-10)',
minimum: 1,
maximum: 10
},
payment_methods: {
type: 'array' as const,
description: 'Preferred payment methods',
items: {
type: 'string' as const
}
}
}
},
finances: {
type: 'object' as const,
description: 'Financial information',
properties: {
subscriptions: {
type: 'array' as const,
description: 'Regular subscriptions and fixed expenses',
items: {
type: 'object' as const,
properties: {
name: {
type: 'string' as const,
description: 'Subscription or expense name'
},
amount: {
type: 'number' as const,
description: 'Monthly cost'
},
frequency: {
type: 'string' as const,
description: 'Billing frequency'
},
next_due_date: {
type: 'string' as const,
description: 'Next payment date',
format: 'date'
},
category: {
type: 'string' as const,
description: 'Expense category',
enum: [
'housing',
'utilities',
'insurance',
'services',
'memberships',
'digital',
'taxes',
'other'
]
},
is_fixed_expense: {
type: 'boolean' as const,
description:
'Whether this is a fixed expense (utilities, rent) or optional subscription'
},
auto_payment: {
type: 'boolean' as const,
description: 'Whether payment is automated'
}
},
required: [
'name',
'amount',
'frequency',
'next_due_date',
'category',
'is_fixed_expense',
'auto_payment'
]
}
},
spending_patterns: {
type: 'object' as const,
description: 'Spending behavior',
properties: {
impulsive_score: {
type: 'number' as const,
description: 'Impulse buying tendency (1-10)',
minimum: 1,
maximum: 10
},
categories: {
type: 'object' as const,
description: 'Spending categories',
additionalProperties: {
type: 'object' as const,
properties: {
preference_score: {
type: 'number' as const,
description: 'Category preference (1-10)',
minimum: 1,
maximum: 10
},
monthly_budget: {
type: 'number' as const,
description: 'Typical monthly spend'
}
}
}
}
}
}
}
},
habits: {
type: 'object' as const,
description: 'Regular activities and habits',
properties: {
exercise: {
type: 'array' as const,
description: 'Exercise routines',
items: {
type: 'object' as const,
properties: {
activity: {
type: 'string' as const,
description: 'Type of exercise'
},
frequency: {
type: 'string' as const,
description: 'How often performed'
},
duration_minutes: {
type: 'number' as const,
description: 'Typical duration'
}
}
}
},
social: {
type: 'array' as const,
description: 'Social activities',
items: {
type: 'object' as const,
properties: {
activity: {
type: 'string' as const,
description: 'Type of social activity'
},
frequency: {
type: 'string' as const,
description: 'How often performed'
}
}
}
}
}
},
context: {
type: 'object' as const,
description: 'Contextual information',
properties: {
stress_triggers: {
type: 'array' as const,
description: 'Known stress factors',
items: {
type: 'string' as const
}
},
reward_behaviors: {
type: 'array' as const,
description: 'Activities used as rewards',
items: {
type: 'string' as const
}
},
upcoming_events: {
type: 'array' as const,
description: 'Planned future events',
items: {
type: 'object' as const,
properties: {
name: {
type: 'string' as const,
description: 'Event name'
},
date: {
type: 'string' as const,
description: 'Event date',
format: 'date'
},
importance: {
type: 'number' as const,
description: 'Event importance (1-10)',
minimum: 1,
maximum: 10
}
}
}
}
}
}
}
}
} as const;

138
utils/consumer/types.ts Normal file
View File

@@ -0,0 +1,138 @@
import { z } from 'zod';
const petSchema = z.object({
type: z.string(),
name: z.string()
});
const regularStopSchema = z.object({
location: z.string(),
purpose: z.string(),
frequency: z.string()
});
const weekdayActivitySchema = z.object({
activity: z.string(),
location: z.string(),
duration_minutes: z.number()
});
const brandPreferenceSchema = z.object({
name: z.string(),
loyalty_score: z.number().min(1).max(10)
});
const subscriptionSchema = z.object({
name: z.string(),
amount: z.number(),
frequency: z.string(),
next_due_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
category: z.enum([
'housing',
'utilities',
'insurance',
'services',
'memberships',
'digital',
'taxes',
'other'
]),
is_fixed_expense: z.boolean(),
auto_payment: z.boolean()
});
const spendingCategorySchema = z.object({
preference_score: z.number().min(1).max(10),
monthly_budget: z.number()
});
const exerciseActivitySchema = z.object({
activity: z.string(),
frequency: z.string(),
duration_minutes: z.number()
});
export type ExerciseActivity = z.infer<typeof exerciseActivitySchema>;
const socialActivitySchema = z.object({
activity: z.string(),
frequency: z.string()
});
export type SocialActivity = z.infer<typeof socialActivitySchema>;
const upcomingEventSchema = z.object({
name: z.string(),
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
importance: z.number().min(1).max(10)
});
const coreSchema = z.object({
age: z.number(),
name: z.string(),
occupation: z.object({
title: z.string(),
level: z.string(),
income: z.number(),
location: z.string(),
schedule: z.array(z.string())
}),
home: z.object({
type: z.string(),
ownership: z.string(),
location: z.string(),
commute_distance_km: z.number()
}),
household: z.object({
status: z.string(),
members: z.array(z.string()),
pets: z.array(petSchema)
})
});
const routinesSchema = z.object({
weekday: z.record(weekdayActivitySchema),
weekend: z.array(z.string()),
commute: z.object({
method: z.string(),
route: z.array(z.string()),
regular_stops: z.array(regularStopSchema)
})
});
const preferencesSchema = z.object({
diet: z.array(z.string()),
brands: z.array(brandPreferenceSchema),
price_sensitivity: z.number().min(1).max(10),
payment_methods: z.array(z.string())
});
const financesSchema = z.object({
subscriptions: z.array(subscriptionSchema),
spending_patterns: z.object({
impulsive_score: z.number().min(1).max(10),
categories: z.record(spendingCategorySchema)
})
});
const habitsSchema = z.object({
exercise: z.array(exerciseActivitySchema),
social: z.array(socialActivitySchema)
});
const contextSchema = z.object({
stress_triggers: z.array(z.string()),
reward_behaviors: z.array(z.string()),
upcoming_events: z.array(upcomingEventSchema)
});
export const consumerSchema = z.object({
core: coreSchema,
routines: routinesSchema,
preferences: preferencesSchema,
finances: financesSchema,
habits: habitsSchema,
context: contextSchema
});
export type Consumer = z.infer<typeof consumerSchema>;