feat: convert to nextjs
This commit is contained in:
75
utils/consumer/prompt.ts
Normal file
75
utils/consumer/prompt.ts
Normal 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
54
utils/consumer/store.ts
Normal 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
408
utils/consumer/tool.ts
Normal 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
138
utils/consumer/types.ts
Normal 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>;
|
||||
Reference in New Issue
Block a user