make-mp-data 2.1.11 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dungeons/adspend.js +35 -1
- package/dungeons/anon.js +25 -1
- package/dungeons/array-of-object-lookup.js +201 -0
- package/dungeons/benchmark-heavy.js +241 -0
- package/dungeons/benchmark-light.js +141 -0
- package/dungeons/big.js +10 -9
- package/dungeons/business.js +60 -12
- package/dungeons/complex.js +35 -1
- package/dungeons/copilot.js +383 -0
- package/dungeons/education.js +1005 -0
- package/dungeons/experiments.js +18 -4
- package/dungeons/fintech.js +976 -0
- package/dungeons/foobar.js +32 -0
- package/dungeons/food.js +988 -0
- package/dungeons/funnels.js +38 -1
- package/dungeons/gaming.js +26 -5
- package/dungeons/media.js +861 -270
- package/dungeons/mil.js +31 -3
- package/dungeons/mirror.js +33 -1
- package/dungeons/retention-cadence.js +211 -0
- package/dungeons/rpg.js +1178 -0
- package/dungeons/sanity.js +32 -2
- package/dungeons/sass.js +923 -0
- package/dungeons/scd.js +47 -1
- package/dungeons/simple.js +29 -14
- package/dungeons/social.js +928 -0
- package/dungeons/streaming.js +373 -0
- package/dungeons/strict-event-test.js +30 -0
- package/dungeons/student-teacher.js +19 -5
- package/dungeons/text-generation.js +120 -84
- package/dungeons/too-big-events.js +203 -0
- package/dungeons/{userAgent.js → user-agent.js} +23 -2
- package/entry.js +5 -4
- package/index.js +41 -54
- package/lib/core/config-validator.js +122 -7
- package/lib/core/context.js +7 -14
- package/lib/core/storage.js +57 -25
- package/lib/generators/adspend.js +12 -12
- package/lib/generators/events.js +6 -5
- package/lib/generators/funnels.js +32 -10
- package/lib/generators/product-lookup.js +262 -0
- package/lib/generators/product-names.js +195 -0
- package/lib/generators/profiles.js +3 -3
- package/lib/generators/scd.js +13 -3
- package/lib/generators/text.js +17 -4
- package/lib/orchestrators/mixpanel-sender.js +244 -204
- package/lib/orchestrators/user-loop.js +54 -16
- package/lib/templates/phrases.js +473 -16
- package/lib/templates/schema.d.ts +173 -0
- package/lib/templates/verbose-schema.js +140 -206
- package/lib/utils/chart.js +210 -0
- package/lib/utils/function-registry.js +285 -0
- package/lib/utils/json-evaluator.js +172 -0
- package/lib/utils/logger.js +34 -0
- package/lib/utils/utils.js +41 -4
- package/package.json +12 -21
- package/types.d.ts +15 -5
- package/dungeons/ai-chat-analytics-ed.js +0 -274
- package/dungeons/money2020-ed-also.js +0 -277
- package/dungeons/money2020-ed.js +0 -579
- package/lib/generators/text-bak-old.js +0 -1121
- package/lib/orchestrators/worker-manager.js +0 -203
- package/lib/templates/hooks-instructions.txt +0 -434
- package/lib/templates/phrases-bak.js +0 -925
- package/lib/templates/prompt (old).txt +0 -98
- package/lib/templates/schema-instructions.txt +0 -155
- package/lib/templates/scratch-dungeon-template.js +0 -116
- package/lib/templates/textQuickTest.js +0 -172
- package/lib/utils/ai.js +0 -120
- package/lib/utils/project.js +0 -166
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
Please generate a JSON schema for event analytics that strictly adheres to these TypeScript types:
|
|
2
|
-
|
|
3
|
-
```typescript
|
|
4
|
-
type Primitives = string | number | boolean | Date | Record<string, any>;
|
|
5
|
-
type ValidValue = Primitives | Primitives[];
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* event schema describes a single event that we might track with any number of properties
|
|
9
|
-
*/
|
|
10
|
-
interface EventSchema {
|
|
11
|
-
event: string;
|
|
12
|
-
weight: number;
|
|
13
|
-
properties?: Record<string, ValidValue>;
|
|
14
|
-
isFirstEvent?: boolean;
|
|
15
|
-
isChurnEvent?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* super props are shared across all events; common dimensions
|
|
20
|
-
*/
|
|
21
|
-
type superProps = Record<string, ValidValue>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* user props describe a user independent of their actions; user dimensions
|
|
25
|
-
*/
|
|
26
|
-
type userProps = Record<string, ValidValue>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* the schema YOU need to build
|
|
30
|
-
*/
|
|
31
|
-
type Schema = {
|
|
32
|
-
events: EventSchema[];
|
|
33
|
-
superProps: superProps;
|
|
34
|
-
userProps: userProps;
|
|
35
|
-
};
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
The schema that YOU make should include common events and properties, super properties, and user properties that describe TYPICAL user behavior for the website i mentioned above.
|
|
40
|
-
|
|
41
|
-
Let me give you a few examples, so you know how to respond.
|
|
42
|
-
|
|
43
|
-
**Example 1:**
|
|
44
|
-
|
|
45
|
-
Input: a generic e-commerce website thats sells a variety of products and also video streaming
|
|
46
|
-
|
|
47
|
-
Output:
|
|
48
|
-
```json
|
|
49
|
-
{"events":[{"event":"checkout","weight":2,"properties":{"amount":[5,500],"currency":["USD","CAD","EUR","BTC","ETH","JPY"],"coupon":["none","10%OFF","20%OFF"],"numItems":[1,10]}},{"event":"add to cart","weight":4,"properties":{"amount":[5,500],"rating":[1,5],"reviews":[0,35],"isFeaturedItem":[true,false,false],"itemCategory":["electronics","clothing","accessories","home goods","toys","tools","books","music","movies"]}},{"event":"page view","weight":10,"properties":{"page":["/","/","/help","/account","/watch","/listen","/product","/people","/peace"]}},{"event":"watch video","weight":8,"properties":{"videoCategory":["humor","scary","amsr","music","documentary","educational"],"isFeaturedItem":[true,false,false],"watchTimeSec":[10,600],"quality":["2160p","1440p","1080p","720p","480p","360p","240p"],"format":["mp4","avi","mov","mpg"]}},{"event":"view item","weight":8,"properties":{"isFeaturedItem":[true,false,false],"itemCategory":["office","school","art","crafts","party","wedding","baby","kids","adults","seniors"],"rating":[1,5]}},{"event":"save item","weight":5,"properties":{"isFeaturedItem":[true,false,false],"itemCategory":["electronics","games","food","beverages","health","beauty","sports","outdoors","party","wedding","baby","kids","adults","seniors"]}},{"event":"rent item","weight":2,"properties":{"isFeaturedItem":[true,false,false],"itemCategory":["electronics","clothing","games","food","beauty","sports","outdoors","automotive","wedding","baby","seniors"]}},{"event":"sign up","isFirstEvent":true,"weight":0,"properties":{"variants":["A","B","C","Control"],"flows":["new","existing","loyal","churned"],"flags":["on","off"],"experiment_ids":["1234","5678","9012","3456","7890"],"multiVariate":[true,false]}}],"superProps":{"platform":["web","mobile","kiosk","smartTV"],"currentTheme":["light","dark","custom"]},"userProps":{"loyalty_points":[1,100000],"age":[18,70],"premium":[true,false],"language":["english","spanish","french"]}}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Example 2:**
|
|
53
|
-
|
|
54
|
-
Input: https://www.nytimes.com
|
|
55
|
-
|
|
56
|
-
Output:
|
|
57
|
-
```json
|
|
58
|
-
{"events":[{"event":"page view","weight":10,"properties":{"page":["/","/section/world","/section/us","/section/politics","/section/business","/section/opinion","/section/technology","/section/science","/section/health","/section/sports","/section/arts","/section/fashion","/section/food","/section/travel"]}},{"event":"article read","weight":8,"properties":{"category":["world news","politics","business","technology","science","health","sports","arts","fashion","food","travel"],"length":["short (< 3 mins)","medium (3-5 mins)","long (> 5 mins)"],"author_reputation":["emerging","established","renowned"],"comment_interaction":["low (<10 comments)","medium (10-50 comments)","high (>50 comments)"]}},{"event":"search","weight":6,"properties":{"search_term_length":["short (1-3 words)","medium (4-6 words)","long (7+ words)"],"results_returned":["none","few (1-3 results)","some (4-10 results)","many (>10 results)"],"result_clicked":["first result","within top 5","none clicked"]}},{"event":"subscribe","weight":2,"properties":{"plan":["basic","premium","all-access"],"payment_method":["credit card","paypal","apple pay"],"trial_offer_accepted":[true,false]}},{"event":"newsletter sign up","weight":3,"properties":{"newsletter_type":["daily briefing","morning briefing","opinion","cooking","arts"],"opt_in_for_promotions":[true,false]}},{"event":"comment posted","weight":4,"properties":{"comment_length":["short (< 50 words)","medium (50-150 words)","long (> 150 words)"],"article_category":["news","opinion","review"],"visibility":["public","private","friends only"]}}],"superProps":{"platform":["web","mobile","tablet"],"loggedIn":[true,false],"time_of_day":["morning","afternoon","evening","night"],"browser_type":["Chrome","Firefox","Safari","Edge"]},"userProps":{"subscriptionType":["none","basic","premium","all-access"],"age_group":["<18","18-24","25-34","35-44","45-54","55-64","65+"],"location":["USA","Europe","Asia","Other"],"interests":["politics","technology","health","sports","arts","lifestyle","science","education"]}}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Example 3:**
|
|
62
|
-
|
|
63
|
-
Input: the love's truck stop app (love's connect: https://www.loves.com/en/my-love-rewards/download-loves-connect)
|
|
64
|
-
|
|
65
|
-
Output:
|
|
66
|
-
```json
|
|
67
|
-
{"events":[{"event":"home button","weight":8,"properties":{"button type":["front","side","middle"]}},{"event":"route button","weight":6,"properties":{"from screen":["home","services"]}},{"event":"services button","weight":2,"properties":{"is emergency?":[false,true]}},{"event":"stores button","weight":3,"properties":{"is from push?":[true,false]}},{"event":"email link clicked","weight":1,"properties":{"campaign_name":["Pro Email Campaign 1","Pro Email Campaign 2","Pro Email Campaign 3"]}},{"event":"pay button","weight":4,"properties":{}},{"event":"pay with location","weight":3,"properties":{}},{"event":"payment select","weight":4,"properties":{}},{"event":"select pump","weight":5,"properties":{"pump":[1,32]}},{"event":"select fuel","weight":3,"properties":{"fuel type":["diesel","reefer","def"],"fuel price":[3.99,6.79]}},{"event":"fueling","weight":4,"properties":{"fuel volume":[20,150]}}],"superProps":{"campaign_name":["Pro Email Campaign 1","Pro Email Campaign 2","Pro Email Campaign 3"],"feature flags":[["first 100k miles"],["dark mode","first 100k miles"],["dark mode","free shower"],["free shower"]]},"userProps":{"driver type":["Leased","Owner","Fleet"],"marketing":["in-app","email","sms","call"],"member status":["base","gold","platinum","diamond"],"lifetime value":[0,10000]}}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**Example 4:**
|
|
71
|
-
|
|
72
|
-
Input: the web app for one medical, a modern healthcare provider (https://app.onemedical.com/)
|
|
73
|
-
|
|
74
|
-
Output:
|
|
75
|
-
```json
|
|
76
|
-
{"events":[{"event":"login","weight":9,"properties":{"method":["standard email/password","google","apple"],"success":[true,false],"error_type":["none","password incorrect","user not found","account locked"]}},{"event":"appointment booking","weight":8,"properties":{"type":["physical","virtual"],"specialty":["primary care","mental health","pediatrics","nutrition","allergy","dermatology"],"duration":["15 minutes","30 minutes","1 hour"],"booking_advance_days":["same day","1-3 days","4-7 days","more than a week"]}},{"event":"profile update","weight":4,"properties":{"section_updated":["personal information","insurance details","medical history","preferences"],"fields_changed":["1-2","3-5","more than 5"]}},{"event":"message to provider","weight":6,"properties":{"message_length":["short (<50 words)","medium (50-150 words)","long (>150 words)"],"response_time":["<1 hour","1-24 hours","1-2 days","no response"],"urgency":["low","medium","high"]}},{"event":"medication refill request","weight":5,"properties":{"medication":["prescription","over-the-counter"],"quantity":["1 month","3 months","6 months"],"auto_refill_enrolled":[true,false]}},{"event":"health record access","weight":7,"properties":{"record_type":["lab results","vaccination records","prescription history","doctor notes"],"access_device":["desktop","mobile"],"time_spent":["<1 min","1-5 mins","5+ mins"]}},{"event":"feedback submission","weight":3,"properties":{"feedback_type":["service","app usability","provider"],"rating":["1","2","3","4","5"],"comment_provided":[true,false]}},{"event":"notification settings update","weight":2,"properties":{"notifications_enabled":[true,false],"types_enabled":["appointment reminders","health updates","newsletters","promotional offers"]}}],"superProps":{"platform":["web","mobile"],"loggedIn":[true,false],"user_type":["patient","provider","admin"],"subscription_level":["free","standard","premium"]},"userProps":{"membership_status":["active","lapsed","pending renewal"],"age_group":["<18","18-24","25-34","35-44","45-54","55-64","65+"],"has_chronic_conditions":[true,false],"preferred_contact_method":["email","phone","sms"]}}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
**Example 5:**
|
|
80
|
-
|
|
81
|
-
Input: the web app for coinbase, a cryptocurrency exchange (https://www.coinbase.com/)
|
|
82
|
-
|
|
83
|
-
Output:
|
|
84
|
-
```json
|
|
85
|
-
{"events":[{"event":"login","weight":9,"properties":{"method":["standard email/password","two-factor authentication","biometric"],"success":[true,false],"error_type":["none","password incorrect","user not found","account locked","2FA failed"]}},{"event":"trade executed","weight":8,"properties":{"crypto_pair":["BTC/USD","ETH/USD","LTC/USD","XRP/USD","BCH/USD"],"trade_type":["buy","sell"],"order_type":["market","limit","stop loss","stop limit"],"quantity":["<1","1-5","5-10","10+"],"trade_successful":[true,false],"error_type":["none","insufficient funds","slippage too high","network error"]}},{"event":"account funding","weight":7,"properties":{"method":["bank transfer","credit card","crypto deposit"],"currency":["USD","EUR","GBP"],"amount":["<100","100-1000","1000-5000","5000+"],"successful":[true,false],"error_type":["none","transaction declined","limits exceeded","network error"]}},{"event":"withdrawal request","weight":6,"properties":{"method":["bank transfer","crypto withdrawal"],"currency":["USD","BTC","ETH"],"amount":["<100","100-1000","1000-5000","5000+"],"successful":[true,false],"error_type":["none","insufficient funds","limits exceeded","network error"]}},{"event":"profile update","weight":3,"properties":{"fields_updated":["email","phone","two-factor authentication settings","payment methods"],"successful":[true,false]}},{"event":"security alert","weight":4,"properties":{"alert_type":["login from new device","suspicious transaction","profile changes"],"response_action":["no action","contact support","reset password","enable 2FA"]}},{"event":"price alert set","weight":2,"properties":{"crypto":["BTC","ETH","LTC","XRP"],"threshold":["<5000","5000-10000","10000-20000","20000+"],"alert_type":["price increase","price decrease"]}},{"event":"customer support interaction","weight":5,"properties":{"issue_type":["account access","trade issue","withdrawal problem","other"],"contact_method":["email","phone","live chat"],"resolution":["resolved","unresolved","escalated"]}}],"superProps":{"platform":["web","iOS app","Android app"],"loggedIn":[true,false],"verification_level":["none","basic","verified","pro"]},"userProps":{"account_type":["basic","pro"],"trading_frequency":["daily","weekly","monthly","rarely"],"preferred_crypto":["BTC","ETH","LTC","XRP"],"region":["North America","Europe","Asia","Other"],"investment_level":["<1000","1000-5000","5000-10000","10000+"]}}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**ADDITIONAL GUIDELINES:**
|
|
89
|
-
|
|
90
|
-
* Use specific and descriptive event names.
|
|
91
|
-
* DO NOT declare property types, properties are the key names and include an array of POSSIBLE values which could be chosen for the event or user
|
|
92
|
-
* the properties within each event should adhere to the defined TypeScript types (Primitives and ValidValue)
|
|
93
|
-
* For numerical ranges, you can use [min, max] in the JSON as above
|
|
94
|
-
* Consider both super properties (applied to all events) and user properties; they should be different from event props
|
|
95
|
-
* DO NOT include user IDs, emails, or location properties anywhere data in the schema; ONLY highlight the properties specific to the website or app
|
|
96
|
-
* DO NOT be lazy an say ['array of payment types'] or ['array of product categories'] - be specific ... ['USD', 'CAD', 'EUR', 'BTC', 'ETH', 'JPY'] ... we want to see the actual values that would be passed live production data
|
|
97
|
-
* event names should be lower case by convention; prefer spaces to underscores so "add to cart" instead of "add_to_cart"
|
|
98
|
-
* you should ALWAYS output valid JSON as your output will be fed into a JSON schema validator
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
You are an AI assistant that generates a structured JavaScript object ("Dungeon") that defines a synthetic analytics dataset designed to simulate realistic user behavior, based on a prompt describing a business or product use case.
|
|
2
|
-
|
|
3
|
-
the spec you are building is a javascript object... the high level spec looks like this:
|
|
4
|
-
|
|
5
|
-
--------------
|
|
6
|
-
|
|
7
|
-
const my_dungeon = {
|
|
8
|
-
funnels: [],
|
|
9
|
-
events: [],
|
|
10
|
-
superProps: {},
|
|
11
|
-
userProps: {},
|
|
12
|
-
scdProps: {},
|
|
13
|
-
groupKeys: [],
|
|
14
|
-
groupProps: {},
|
|
15
|
-
lookupTables: [],
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
--------------
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
here's the full typescript definition for each of the properties in the entire spec; we call the specs 'DUNGEONS' and each dungeon is a javascript object:
|
|
22
|
-
|
|
23
|
-
--------------
|
|
24
|
-
//types.d.ts
|
|
25
|
-
|
|
26
|
-
<TYPES>
|
|
27
|
-
|
|
28
|
-
--------------
|
|
29
|
-
|
|
30
|
-
here is now an implementation of the dungeon spec which shows how these above features work together to create a data set that tells a story!
|
|
31
|
-
|
|
32
|
-
Pay close attention to how function calls like weighNumRange(...) and chance.company() are written directly into the object without quotes.
|
|
33
|
-
|
|
34
|
-
Your output must follow this exact format:
|
|
35
|
-
|
|
36
|
-
--------------
|
|
37
|
-
|
|
38
|
-
//my-dungeon.js
|
|
39
|
-
/** @type {import('../../types.js').Dungeon} */
|
|
40
|
-
|
|
41
|
-
<VERBOSE_SCHEMA>
|
|
42
|
-
|
|
43
|
-
--------------
|
|
44
|
-
|
|
45
|
-
Final Instructions & Rules:
|
|
46
|
-
|
|
47
|
-
Your job is to build a dungeon based on the analytics use case described in the prompt. Your only output will be a single, valid JavaScript object literal.
|
|
48
|
-
|
|
49
|
-
Core Requirements:
|
|
50
|
-
|
|
51
|
-
1. Output Format: Your output must be a valid JavaScript object literal, NOT JSON. This is crucial. Your entire response should start with { and end with } and contain nothing else.
|
|
52
|
-
|
|
53
|
-
2. Mandatory Fields: You MUST create funnels, events, superProps, and userProps for every dungeon. They should be directly related to the analytics use cases stated in the prompt.
|
|
54
|
-
|
|
55
|
-
3. Optional Fields: You should include scdProps, groupKeys, groupProps, and lookupTables only if they are clearly relevant based on the use case prompt.
|
|
56
|
-
- Use groups if the prompt involves B2B, teams, companies, or organizations.
|
|
57
|
-
- Use SCD if user or group traits change over time (e.g., subscription tier).
|
|
58
|
-
- Use lookup tables if events reference external entities with their own attributes (e.g., product_id, video_id).
|
|
59
|
-
- Use funnel conditions when different user segments or cohorts should have different behavioral patterns (e.g., premium vs free users, students vs teachers, rider vs driver, doctor vs patient).
|
|
60
|
-
|
|
61
|
-
4. Available Functions: You have access to these built-in functions: date, weighNumRange, range, chance library methods, and createGenerator for structured text generation.
|
|
62
|
-
|
|
63
|
-
5. Structured Text Generation: When your use case involves user-generated content (reviews, comments, support tickets, chat messages, social media posts, etc.), use createGenerator() to produce realistic, contextual text.
|
|
64
|
-
|
|
65
|
-
Text Generator Usage:
|
|
66
|
-
|
|
67
|
-
- createGenerator() creates a text generator object that produces varied, authentic-sounding text
|
|
68
|
-
- Embed the createGenerator() call directly in the properties object (NOT as a quoted string)
|
|
69
|
-
- The generator automatically produces unique text for each event
|
|
70
|
-
|
|
71
|
-
Example for a customer support platform:
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
event: "support_ticket_submitted",
|
|
75
|
-
properties: {
|
|
76
|
-
ticket_text: createGenerator({
|
|
77
|
-
style: "support",
|
|
78
|
-
tone: "neg",
|
|
79
|
-
formality: "business",
|
|
80
|
-
keywords: {
|
|
81
|
-
features: ["Dashboard", "Export API", "User Management"],
|
|
82
|
-
technical: ["timeout", "authentication", "database error"],
|
|
83
|
-
errors: ["500 Internal Server", "TIMEOUT_ERROR"]
|
|
84
|
-
},
|
|
85
|
-
min: 80,
|
|
86
|
-
max: 300
|
|
87
|
-
}),
|
|
88
|
-
priority: ["low", "medium", "high", "critical"]
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
Example for social media platform:
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
event: "comment_posted",
|
|
96
|
-
properties: {
|
|
97
|
-
comment_text: createGenerator({
|
|
98
|
-
style: "chat",
|
|
99
|
-
tone: "pos",
|
|
100
|
-
formality: "casual",
|
|
101
|
-
keywords: {
|
|
102
|
-
products: ["the app", "this feature"],
|
|
103
|
-
emotions: ["love it", "amazing", "great job"]
|
|
104
|
-
},
|
|
105
|
-
typos: true,
|
|
106
|
-
typoRate: 0.03,
|
|
107
|
-
min: 10,
|
|
108
|
-
max: 150
|
|
109
|
-
}),
|
|
110
|
-
post_type: ["text", "image", "video"]
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
Text Generator Options:
|
|
115
|
-
|
|
116
|
-
- style: "support", "review", "forum", "search", "feedback", "chat", "comments", "tweet", "email"
|
|
117
|
-
- tone: "pos" (positive), "neg" (negative), "neu" (neutral)
|
|
118
|
-
- formality: "casual", "business", "technical"
|
|
119
|
-
- keywords: Object with arrays of domain-specific terms to include (features, products, technical, errors, etc.)
|
|
120
|
-
- min/max: Character length range
|
|
121
|
-
- typos: true/false (adds realistic typos)
|
|
122
|
-
- typoRate: 0.01 to 0.1 (percentage of typos)
|
|
123
|
-
- mixedSentiment: true/false (varies sentiment within text)
|
|
124
|
-
- authenticityLevel: 0.0 to 1.0 (how "real" the text sounds)
|
|
125
|
-
- specificityLevel: 0.0 to 1.0 (level of detail)
|
|
126
|
-
|
|
127
|
-
When to Use createGenerator:
|
|
128
|
-
|
|
129
|
-
- Customer support tickets and responses
|
|
130
|
-
- Product reviews and ratings
|
|
131
|
-
- Social media posts (tweets, LinkedIn, Reddit)
|
|
132
|
-
- Forum discussions and comments
|
|
133
|
-
- Chat messages and live support
|
|
134
|
-
- Search queries
|
|
135
|
-
- User feedback and feature requests
|
|
136
|
-
- Email communications
|
|
137
|
-
- Bug reports
|
|
138
|
-
- Any scenario involving user-written or generated text content
|
|
139
|
-
|
|
140
|
-
❌ Critical Rules to Follow:
|
|
141
|
-
|
|
142
|
-
- Do NOT wrap function calls in quotes.
|
|
143
|
-
|
|
144
|
-
Correct: amount: weighNumRange(5, 500)
|
|
145
|
-
Incorrect: amount: "weighNumRange(5, 500)"
|
|
146
|
-
|
|
147
|
-
- Do NOT output comments, explanations, or any text outside of the JavaScript object.
|
|
148
|
-
|
|
149
|
-
- Do NOT generate vague or placeholder values like "value1", "example", or "random_string".
|
|
150
|
-
|
|
151
|
-
- Do NOT leave required arrays empty (funnels, events, etc.).
|
|
152
|
-
|
|
153
|
-
Your only task is to generate a single JavaScript object that follows this structure based on the user's request.
|
|
154
|
-
=================
|
|
155
|
-
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* this file is NOT currently used
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import dayjs from "dayjs";
|
|
6
|
-
import utc from "dayjs/plugin/utc.js";
|
|
7
|
-
dayjs.extend(utc);
|
|
8
|
-
import "dotenv/config";
|
|
9
|
-
import { weighNumRange, range, date, initChance, exhaust, choose, integer, decimal, odds } from "../utils/utils.js";
|
|
10
|
-
const { NODE_ENV = "unknown" } = process.env;
|
|
11
|
-
import * as u from '../utils/utils.js'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Dungeon template for AI-generated configurations
|
|
16
|
-
* This template provides the structure and standard configuration
|
|
17
|
-
* AI-generated content will be injected into the placeholders
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export function createDungeonTemplate({
|
|
21
|
-
seed = "ai-generated-seed",
|
|
22
|
-
numUsers = 1000,
|
|
23
|
-
numDays = 100,
|
|
24
|
-
events = [],
|
|
25
|
-
funnels = [],
|
|
26
|
-
superProps = {},
|
|
27
|
-
userProps = {},
|
|
28
|
-
scdProps = {},
|
|
29
|
-
mirrorProps = {},
|
|
30
|
-
groupKeys = [],
|
|
31
|
-
groupProps = {},
|
|
32
|
-
lookupTables = [],
|
|
33
|
-
hookFunction = null
|
|
34
|
-
}) {
|
|
35
|
-
const chance = u.initChance(seed);
|
|
36
|
-
const numEvents = numUsers * 100;
|
|
37
|
-
|
|
38
|
-
/** @typedef {import("../../types.js").Dungeon} Config */
|
|
39
|
-
|
|
40
|
-
/** @type {Config} */
|
|
41
|
-
const config = {
|
|
42
|
-
token: "",
|
|
43
|
-
seed: seed,
|
|
44
|
-
numDays: numDays,
|
|
45
|
-
numEvents: numEvents,
|
|
46
|
-
numUsers: numUsers,
|
|
47
|
-
hasAnonIds: false,
|
|
48
|
-
hasSessionIds: false,
|
|
49
|
-
format: "json",
|
|
50
|
-
alsoInferFunnels: true,
|
|
51
|
-
hasLocation: true,
|
|
52
|
-
hasAndroidDevices: true,
|
|
53
|
-
hasIOSDevices: true,
|
|
54
|
-
hasDesktopDevices: true,
|
|
55
|
-
hasBrowser: true,
|
|
56
|
-
hasCampaigns: true,
|
|
57
|
-
isAnonymous: false,
|
|
58
|
-
hasAdSpend: true,
|
|
59
|
-
|
|
60
|
-
hasAvatar: true,
|
|
61
|
-
makeChart: false,
|
|
62
|
-
|
|
63
|
-
batchSize: 1_500_000,
|
|
64
|
-
concurrency: 1,
|
|
65
|
-
writeToDisk: false,
|
|
66
|
-
|
|
67
|
-
// AI-generated content will be injected here
|
|
68
|
-
funnels: funnels,
|
|
69
|
-
events: events,
|
|
70
|
-
superProps: superProps,
|
|
71
|
-
userProps: userProps,
|
|
72
|
-
scdProps: scdProps,
|
|
73
|
-
mirrorProps: mirrorProps,
|
|
74
|
-
groupKeys: groupKeys,
|
|
75
|
-
groupProps: groupProps,
|
|
76
|
-
lookupTables: lookupTables,
|
|
77
|
-
|
|
78
|
-
hook: hookFunction || function (record, type, meta) {
|
|
79
|
-
// const NOW = dayjs();
|
|
80
|
-
|
|
81
|
-
// CALLED AFTER EACH EVENT IS CREATED
|
|
82
|
-
if (type === "event") {
|
|
83
|
-
// const EVENT_TIME = dayjs(record.time);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// CALLED ONCE FOR EACH USER AND DEFINES THEIR PROPS
|
|
87
|
-
if (type === "user") {
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// CALLED AFTER FUNNELS EVENTS ARE CHOSEN
|
|
92
|
-
if (type === "funnel-post") {
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// CALLED BEFORE FUNNELS EVENTS ARE CHOSEN
|
|
97
|
-
if (type === "funnel-pre") {
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// CALLED BEFORE SCD EVENTS ARE CHOSEN
|
|
102
|
-
if (type === "scd-pre") {
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// CALLED AT THE END WHEN A USERS ENTIRE HISTORY EXISTS
|
|
107
|
-
if (type === "everything") {
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return record;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
return config;
|
|
116
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { createGenerator, generateBatch } from "../generators/text.js";
|
|
2
|
-
|
|
3
|
-
function main() {
|
|
4
|
-
// Enterprise support ticket generator with keywords and high authenticity
|
|
5
|
-
const enterpriseSupportGen = createGenerator({
|
|
6
|
-
style: "support",
|
|
7
|
-
tone: "neg",
|
|
8
|
-
intensity: "high",
|
|
9
|
-
formality: "technical",
|
|
10
|
-
keywords: {
|
|
11
|
-
features: ['Dashboard Analytics', 'Export API', 'SSO Login', 'Admin Console', 'User Management'],
|
|
12
|
-
products: ['DataViz Pro', 'Enterprise Suite', 'v3.2.1', 'v2.8.4'],
|
|
13
|
-
technical: ['CORS error', 'timeout', 'memory leak', 'authentication', 'database'],
|
|
14
|
-
errors: ['ERR_CONNECTION_REFUSED', '500 Internal Server', 'TIMEOUT_ERROR', 'AUTH_FAILED'],
|
|
15
|
-
competitors: ['Tableau', 'PowerBI', 'Looker', 'Qlik']
|
|
16
|
-
},
|
|
17
|
-
mixedSentiment: true,
|
|
18
|
-
authenticityLevel: 0.7,
|
|
19
|
-
typos: true,
|
|
20
|
-
typoRate: 0.02,
|
|
21
|
-
specificityLevel: 0.8,
|
|
22
|
-
min: 80,
|
|
23
|
-
max: 300,
|
|
24
|
-
includeMetadata: false,
|
|
25
|
-
// System is now always optimized for speed + uniqueness
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const twentyEnterpriseSupport = enterpriseSupportGen.generateBatch({ n: 20 });
|
|
29
|
-
|
|
30
|
-
// Casual review generator with typos and mixed sentiment
|
|
31
|
-
const casualReviewGen = createGenerator({
|
|
32
|
-
style: "review",
|
|
33
|
-
tone: "pos",
|
|
34
|
-
intensity: "medium",
|
|
35
|
-
formality: "casual",
|
|
36
|
-
keywords: {
|
|
37
|
-
features: ['user interface', 'mobile app', 'notifications', 'search function'],
|
|
38
|
-
products: ['the app', 'this tool', 'the platform'],
|
|
39
|
-
metrics: ['response time', 'uptime', 'user experience']
|
|
40
|
-
},
|
|
41
|
-
mixedSentiment: true,
|
|
42
|
-
authenticityLevel: 0.4,
|
|
43
|
-
typos: true,
|
|
44
|
-
typoRate: 0.03,
|
|
45
|
-
sentimentDrift: 0.3,
|
|
46
|
-
min: 30,
|
|
47
|
-
max: 200,
|
|
48
|
-
includeMetadata: false
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const twentyCasualReviews = casualReviewGen.generateBatch({ n: 20 });
|
|
52
|
-
|
|
53
|
-
// Technical forum posts with advanced features
|
|
54
|
-
const technicalForumGen = createGenerator({
|
|
55
|
-
style: "forum",
|
|
56
|
-
tone: "neu",
|
|
57
|
-
formality: "technical",
|
|
58
|
-
keywords: {
|
|
59
|
-
technical: ['REST API', 'GraphQL', 'webhooks', 'microservices', 'cloud infrastructure'],
|
|
60
|
-
versions: ['v1.2.3', 'latest', 'beta', 'stable release'],
|
|
61
|
-
errors: ['404 Not Found', 'Rate Limiting', 'SSL Certificate']
|
|
62
|
-
},
|
|
63
|
-
userPersona: true,
|
|
64
|
-
timestamps: true,
|
|
65
|
-
authenticityLevel: 0.6,
|
|
66
|
-
specificityLevel: 0.9,
|
|
67
|
-
min: 20,
|
|
68
|
-
max: 250,
|
|
69
|
-
includeMetadata: false
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const twentyTechForms = technicalForumGen.generateBatch({ n: 20 });
|
|
73
|
-
|
|
74
|
-
// Search queries with realistic typos
|
|
75
|
-
const searchQueryGen = createGenerator({
|
|
76
|
-
style: "search",
|
|
77
|
-
tone: "neu",
|
|
78
|
-
formality: "casual",
|
|
79
|
-
keywords: {
|
|
80
|
-
features: ['export data', 'user settings', 'help docs', 'pricing'],
|
|
81
|
-
technical: ['API documentation', 'integration guide', 'troubleshooting']
|
|
82
|
-
},
|
|
83
|
-
typos: true,
|
|
84
|
-
typoRate: 0.05,
|
|
85
|
-
min: 2,
|
|
86
|
-
max: 50,
|
|
87
|
-
includeMetadata: false
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const twentySearch = searchQueryGen.generateBatch({ n: 20 });
|
|
91
|
-
|
|
92
|
-
// Business feedback with professional tone
|
|
93
|
-
const businessFeedbackGen = createGenerator({
|
|
94
|
-
style: "feedback",
|
|
95
|
-
tone: "neu",
|
|
96
|
-
formality: "business",
|
|
97
|
-
keywords: {
|
|
98
|
-
metrics: ['ROI', 'efficiency', 'cost savings', 'productivity'],
|
|
99
|
-
features: ['reporting', 'analytics', 'integration capabilities']
|
|
100
|
-
},
|
|
101
|
-
authenticityLevel: 0.3,
|
|
102
|
-
specificityLevel: 0.7,
|
|
103
|
-
min: 40,
|
|
104
|
-
max: 180,
|
|
105
|
-
includeMetadata: false
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const twentyFeedback = businessFeedbackGen.generateBatch({ n: 20 });
|
|
109
|
-
|
|
110
|
-
// Chat messages with high authenticity and typos
|
|
111
|
-
const chatMessageGen = createGenerator({
|
|
112
|
-
style: "chat",
|
|
113
|
-
tone: "neu",
|
|
114
|
-
formality: "casual",
|
|
115
|
-
keywords: {
|
|
116
|
-
products: ['the app', 'dashboard', 'mobile version'],
|
|
117
|
-
features: ['notifications', 'sync', 'offline mode']
|
|
118
|
-
},
|
|
119
|
-
mixedSentiment: true,
|
|
120
|
-
authenticityLevel: 0.8,
|
|
121
|
-
typos: true,
|
|
122
|
-
typoRate: 0.04,
|
|
123
|
-
sentimentDrift: 0.4,
|
|
124
|
-
min: 5,
|
|
125
|
-
max: 150,
|
|
126
|
-
includeMetadata: false
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const twentyChatMsg = chatMessageGen.generateBatch({ n: 20 });
|
|
130
|
-
|
|
131
|
-
// Email communication generator
|
|
132
|
-
const emailGen = createGenerator({
|
|
133
|
-
style: "email",
|
|
134
|
-
tone: "neu",
|
|
135
|
-
formality: "business",
|
|
136
|
-
keywords: {
|
|
137
|
-
features: ['account management', 'billing', 'subscription'],
|
|
138
|
-
products: ['Enterprise Plan', 'Pro Account']
|
|
139
|
-
},
|
|
140
|
-
authenticityLevel: 0.5,
|
|
141
|
-
userPersona: true,
|
|
142
|
-
min: 60,
|
|
143
|
-
max: 300,
|
|
144
|
-
includeMetadata: false
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const twentyEmails = emailGen.generateBatch({ n: 20 });
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
email: twentyEmails,
|
|
151
|
-
chat: twentyChatMsg,
|
|
152
|
-
feedback: twentyFeedback,
|
|
153
|
-
search: twentySearch,
|
|
154
|
-
tech: twentyTechForms,
|
|
155
|
-
casual: twentyCasualReviews,
|
|
156
|
-
enterprise: twentyEnterpriseSupport
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const result = main();
|
|
163
|
-
|
|
164
|
-
for (const key in result) {
|
|
165
|
-
console.log(`${key?.toUpperCase()}`);
|
|
166
|
-
console.log(`----------`)
|
|
167
|
-
const toShow = result[key]?.join("\n\n");
|
|
168
|
-
console.log(toShow)
|
|
169
|
-
console.log(`----------\n\n`)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// debugger;
|
package/lib/utils/ai.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/** @typedef {import('../../types.js').Dungeon} Dungeon */
|
|
3
|
-
/** @typedef {import('../../types.js').EventConfig} EventConfig */
|
|
4
|
-
|
|
5
|
-
import * as u from "ak-tools";
|
|
6
|
-
import 'dotenv/config';
|
|
7
|
-
const { GEMINI_API_KEY: API_KEY, NODE_ENV = "unknown" } = process.env;
|
|
8
|
-
if (!API_KEY) throw new Error("Please provide a Gemini API key");
|
|
9
|
-
import AITransformer from 'ak-gemini';
|
|
10
|
-
|
|
11
|
-
let CURRENT_PROMPT = ``;
|
|
12
|
-
CURRENT_PROMPT = `build me a dungeon stream with these events and structure
|
|
13
|
-
|
|
14
|
-
{ "event": "impression", "carousel": [{"product": "big mac"}] }
|
|
15
|
-
{ "event": "viewed", "product_viewed": "big mac" }
|
|
16
|
-
{ "event": "add to basket", "product_added": "big mac" }
|
|
17
|
-
{ "event": "customized", "product_customized": "big mac" }
|
|
18
|
-
{ "event": "checked out", "cart": [{"item": "big mac"}] }
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
but use all the different mcdonalds products as a possible values`;
|
|
22
|
-
CURRENT_PROMPT = ``;
|
|
23
|
-
|
|
24
|
-
export async function ask(question) {
|
|
25
|
-
const prompt = question;
|
|
26
|
-
const ai = new AITransformer({
|
|
27
|
-
apiKey: API_KEY,
|
|
28
|
-
onlyJSON: false,
|
|
29
|
-
responseSchema: {
|
|
30
|
-
type: "string"
|
|
31
|
-
},
|
|
32
|
-
modelName: "gemini-2.5-flash-lite"
|
|
33
|
-
});
|
|
34
|
-
await ai.init();
|
|
35
|
-
const response = await ai.message(prompt);
|
|
36
|
-
// if (NODE_ENV === "dev") {
|
|
37
|
-
// debugger;
|
|
38
|
-
// }
|
|
39
|
-
return response?.toString()?.trim();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function main(params) {
|
|
43
|
-
const { prompt } = params;
|
|
44
|
-
if (!prompt) throw new Error("Please provide a prompt");
|
|
45
|
-
let INSTRUCTIONS = await u.load('./lib/templates/schema-instructions.txt', false);
|
|
46
|
-
const TYPES = await u.load('./lib/templates/abbreviated.d.ts', false);
|
|
47
|
-
const VERBOSE_SCHEMA_FILE = await u.load('./lib/templates/verbose-schema.js', false);
|
|
48
|
-
const VERBOSE_SCHEMA = VERBOSE_SCHEMA_FILE.split(`//SPLIT HERE`).pop()?.trim() || ``;
|
|
49
|
-
INSTRUCTIONS = INSTRUCTIONS
|
|
50
|
-
.replace(/<TYPES>/g, TYPES)
|
|
51
|
-
.replace(/<VERBOSE_SCHEMA>/g, VERBOSE_SCHEMA);
|
|
52
|
-
|
|
53
|
-
const ai = new AITransformer({
|
|
54
|
-
apiKey: API_KEY,
|
|
55
|
-
onlyJSON: false,
|
|
56
|
-
systemInstructions: INSTRUCTIONS?.trim(),
|
|
57
|
-
modelName: "gemini-2.5-pro",
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
});
|
|
61
|
-
await ai.init();
|
|
62
|
-
const response = await ai.message(prompt);
|
|
63
|
-
|
|
64
|
-
// if (NODE_ENV === "dev") {
|
|
65
|
-
// debugger;
|
|
66
|
-
// }
|
|
67
|
-
|
|
68
|
-
return response;
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Generate AI hooks based on current schema and user's desired trends
|
|
74
|
-
* @param {object} params - Parameters object
|
|
75
|
-
* @param {string} params.prompt - User's description of desired trends
|
|
76
|
-
* @param {object} params.currentSchema - The existing dungeon schema
|
|
77
|
-
* @returns {Promise<string>} Generated hook function code
|
|
78
|
-
*/
|
|
79
|
-
export async function generateAIHooks(params) {
|
|
80
|
-
const { prompt, currentSchema } = params;
|
|
81
|
-
if (!prompt) throw new Error("Please provide a prompt describing the trends you want");
|
|
82
|
-
if (!currentSchema) throw new Error("Please provide the current schema");
|
|
83
|
-
|
|
84
|
-
// Load hooks instructions template
|
|
85
|
-
let HOOKS_INSTRUCTIONS = await u.load('./lib/templates/hooks-instructions.txt', false);
|
|
86
|
-
|
|
87
|
-
// Format the current schema as a readable string
|
|
88
|
-
const schemaString = JSON.stringify(currentSchema, null, 2);
|
|
89
|
-
|
|
90
|
-
// Replace placeholder with actual schema
|
|
91
|
-
HOOKS_INSTRUCTIONS = HOOKS_INSTRUCTIONS.replace(/<CURRENT_SCHEMA>/g, schemaString);
|
|
92
|
-
|
|
93
|
-
const ai = new AITransformer({
|
|
94
|
-
apiKey: API_KEY,
|
|
95
|
-
onlyJSON: false,
|
|
96
|
-
systemInstructions: HOOKS_INSTRUCTIONS?.trim(),
|
|
97
|
-
modelName: "gemini-2.5-pro",
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
await ai.init();
|
|
101
|
-
const response = await ai.message(prompt);
|
|
102
|
-
|
|
103
|
-
return response?.toString()?.trim();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export default main;
|
|
107
|
-
|
|
108
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
109
|
-
main(
|
|
110
|
-
{
|
|
111
|
-
prompt: CURRENT_PROMPT || "Generate a dungeon spec for a simple e-commerce site with checkout and add to cart events."
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
.then((result) => {
|
|
115
|
-
if (NODE_ENV === "dev") debugger;
|
|
116
|
-
})
|
|
117
|
-
.catch((error) => {
|
|
118
|
-
if (NODE_ENV === "dev") debugger;
|
|
119
|
-
});
|
|
120
|
-
}
|