In Deel 1 We bespraken de filosofie: transparante segmentatie zonder PII. Deel 2 omvat sessieprofielen, signalen en segmentdefinities.
Maar eerst: hoe valideer je dit zonder ooit echte klantgegevens aan te raken?
Voor deze serie maak ik lokaal een complete synthetische ecommerce dataset:
Dit is een van die ..het voelt als vals spelen workflows: je krijgt realistische input, je kunt ze regenereren op elk moment, en je nooit PII in te voeren in uw dev-omgeving.
Als je segmentatie / personalisatie bouwt, heb je datasets nodig die:
Echte gegevens zijn het tegenovergestelde: gevoelig, rommelig, moeilijk te verplaatsen, en vol historische vooroordelen.
Synthetische data geeft je drie superkrachten:
flowchart LR
Taxonomy[gadget-taxonomy.json] --> Gen[SampleData generator]
Gen --> Products[products.json]
Gen --> Profiles[profiles.json]
Gen --> Images[images/*]
Products --> Import[Import into Postgres]
Profiles --> Import
style Taxonomy stroke:#1971c2,stroke-width:3px
style Gen stroke:#1971c2,stroke-width:3px
style Import stroke:#2f9e44,stroke-width:3px
De generator leeft in Mostlylucid.SegmentCommerce.SampleData.
Het is opzettelijk geen kader; het is een pragmatische CLI die praat met:
Configuratie is bekabeld zodat je het kunt rijden via omgevingsvariabelen:
// Mostlylucid.SegmentCommerce.SampleData/Program.cs
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables("SAMPLEDATA_")
.Build();
Je zult meestal draaien drie lokale diensten naast de generator:
flowchart LR
CLI[SampleData CLI] --> Ollama["Ollama
http://localhost:11434"]
CLI --> Comfy["ComfyUI
http://localhost:8188"]
CLI -. optional .-> DB[(Postgres)]
style CLI stroke:#1971c2,stroke-width:3px
style Ollama stroke:#1971c2,stroke-width:3px
style Comfy stroke:#2f9e44,stroke-width:3px
style DB stroke:#fab005,stroke-width:3px
Start de generator van de repo-root:
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- status
Genereer dan een dataset:
# v1 generator: taxonomy + optional Ollama + optional ComfyUI
# Writes ./Output/products.json, ./Output/profiles.json, ./Output/images/...
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- generate --count 20
Nuttige schakelaars:
# No LLM calls, taxonomy only
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- generate --no-ollama
# No ComfyUI images
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- generate --no-images
# Write into Postgres (uses configured connection string)
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- generate --db
Opmerking: als ComfyUI niet beschikbaar is, valt de v1 generator terug naar plaatshouder afbeeldingen (het maakt gebruik van picsum.photos, zodat dat pad is niet volledig offline. Als u wilt strikt-lokaal, lopen met --no-images.
Er is ook een nieuwer generator commando (gen) dat bouwt een meer complete marktplaats-geribbelde settle:
# v2 generator
# Writes dataset.json plus sellers/products/customers/orders split files
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- gen --sellers 50 --products 20 --customers 1000
Het wordt georkestreerd als een multi-fase pijpleiding:
flowchart LR
A[Sellers] --> B[Products]
B --> C[Customers]
C --> D[Orders]
D --> E[Embeddings]
B -. optional .-> I[ComfyUI images]
style A stroke:#1971c2,stroke-width:3px
style B stroke:#1971c2,stroke-width:3px
style C stroke:#1971c2,stroke-width:3px
style D stroke:#1971c2,stroke-width:3px
style E stroke:#2f9e44,stroke-width:3px
style I stroke:#2f9e44,stroke-width:3px
En je kunt die fasen direct in code zien:
// Mostlylucid.SegmentCommerce.SampleData/Services/DataGenerator.cs
// 1. Generate Sellers
// 2. Generate Products for each seller
// 3. Generate Customers
// 4. Generate Orders (with fake checkout data via Bogus)
// 5. Generate embeddings for all entities
De v2 generator kan inbeddingen berekenen met behulp van een ONNX model (standaard: all-MiniLM-L6-v2De eerste keer dat je het uitvoert, downloadt het model en vocab in je uitvoermap.
Dat betekent:
--no-embeddings// Mostlylucid.SegmentCommerce.SampleData/Services/EmbeddingService.cs
private const string ModelUrl = "https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main/onnx/model.onnx";
private const string VocabUrl = "https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main/vocab.txt";
// Download model if not exists
if (!File.Exists(_config.ModelPath))
{
await DownloadFileAsync(ModelUrl, _config.ModelPath, ct);
}
De prompt voor het genereren van producten is bewust streng: de LLM moet alleen JSON retourneren, met een ingebed JSON schema voorbeeld.
// Mostlylucid.SegmentCommerce.SampleData/Services/OllamaProductGenerator.cs
return $"""
You are a product catalog generator for an e-commerce store. Generate {count} unique, realistic product listings for the \"{category.DisplayName}\" category.
Category description: {category.Description}
Example products in this category: {category.ExampleProducts}
Price range: £{category.PriceRange.Min:F2} - £{category.PriceRange.Max:F2}
For each product, provide:
1. A compelling product name (realistic brand-style naming)
2. A detailed description (2-3 sentences, highlighting key features and benefits)
3. A realistic price within the range
4. Optional original price if on sale (20-40% higher than current price)
5. 3-5 relevant tags
6. Whether it's trending (about 20% should be trending)
7. Whether it's featured (about 15% should be featured)
8. An image prompt for AI image generation (detailed, product photography style)
9. 2-3 colour variants for the product
IMPORTANT: Respond with ONLY valid JSON, no markdown formatting, no code blocks, no explanations.
Generate {count} diverse products now:
""";
Dit is belangrijk omdat downstream systemen (image generation + import + inbeddingen) gestructureerde gegevens willen. ingangen van een pijpleiding, niet het schrijven van proza.
LLM's zijn geen compilers. Zelfs met alleen JSON heb je nog steeds defensieve ontleden en sierlijke terugval nodig.
De v2 generator doet dat via een kleine helper (LlmService) dat de eerste {...} blok en deserialiseert het:
// Mostlylucid.SegmentCommerce.SampleData/Services/LlmService.cs
var jsonStart = response.IndexOf('{');
var jsonEnd = response.LastIndexOf('}');
if (jsonStart >= 0 && jsonEnd > jsonStart)
{
var jsonStr = response.Substring(jsonStart, jsonEnd - jsonStart + 1);
return JsonSerializer.Deserialize<T>(jsonStr, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
En de algemene generatie pijplijn controleert expliciet beschikbaarheid en downgrades naar deterministische templates wanneer dat nodig is:
flowchart LR
A[EnableLlm=true?] -->|no| F[Fallback templates]
A -->|yes| B[GET /api/tags]
B -->|model present| C[LLM JSON prompts]
B -->|not available| F
style A stroke:#1971c2,stroke-width:3px
style C stroke:#2f9e44,stroke-width:3px
style F stroke:#fab005,stroke-width:3px
De persona prompt voor klanten is kort en gestructureerd zodat het snel kan worden gegenereerd met een klein lokaal model:
// Mostlylucid.SegmentCommerce.SampleData/Services/DataGenerator.cs
var prompt = $$"""
Generate a shopper persona interested in: {{string.Join(", ", categoryNames)}}.
Return JSON only:
{
"persona": "Brief persona description (e.g. 'Tech enthusiast who values quality')",
"name": "Realistic first name",
"bio": "One sentence about their shopping habits",
"age": 25,
"shopping_style": "budget|value|premium|luxury",
"preferred_categories": ["category1", "category2"]
}
""";
ComfyUI is geweldig omdat het geeft u een controleerbare pijplijn (workflows) in plaats van een enkele zwarte doos afbeelding eindpunt.
De generator:
ComfyUI/workflows/product_image.json)CLIPTextEncode/prompt/history/{promptId}/view?...sequenceDiagram
participant Gen as SampleData
participant Comfy as ComfyUI
Gen->>Comfy: POST /prompt (workflow + prompt)
Comfy-->>Gen: prompt_id
loop poll
Gen->>Comfy: GET /history/{prompt_id}
Comfy-->>Gen: outputs / images
end
Gen->>Comfy: GET /view?filename=...&type=output
Comfy-->>Gen: PNG bytes
ComfyUI modelselectie wordt ook gepatcht in de workflow op runtime (dus je kunt checkpoints ruilen zonder de JSON te bewerken):
// Mostlylucid.SegmentCommerce.SampleData/Services/ComfyUIImageGenerator.cs
TryPatchCheckpoint(workflow, _config.ComfyUICheckpointName ?? "sd_xl_base_1.0.safetensors");
TryPatchRefiner(workflow, _config.ComfyUIRefinerName ?? "sd_xl_refiner_1.0.safetensors");
En de workflow patching is opzettelijk eenvoudig en robuust:
// Mostlylucid.SegmentCommerce.SampleData/Services/ComfyUIImageGenerator.cs
// Update CLIPTextEncode nodes with our prompt
if (classType == "CLIPTextEncode")
{
var inputs = nodeObj["inputs"]?.AsObject();
if (inputs != null && inputs.ContainsKey("text"))
{
var currentText = inputs["text"]?.GetValue<string>() ?? "";
if (!currentText.Contains("bad") && !currentText.Contains("ugly") && !currentText.Contains("deformed"))
{
inputs["text"] = prompt;
}
}
}
// Update image dimensions
if (classType == "EmptyLatentImage")
{
var inputs = nodeObj["inputs"]?.AsObject();
if (inputs != null)
{
inputs["width"] = _config.ImageWidth;
inputs["height"] = _config.ImageHeight;
}
}
De v1 generator maakt anonieme profielen en verrijkt ze vervolgens met een persona (nog steeds geen PII). U eindigt met realistische mensen-geribbelde testgegevens zonder e-mails, adressen, of iets dat je ooit per ongeluk zou kunnen verzenden.
In v1 worden profielen getoetst met behulp van een one-way hash, dus er is niets om te herstellen:
// Mostlylucid.SegmentCommerce.SampleData/Services/ProfileGenerator.cs
var profileKey = Hash($"fp-{Guid.NewGuid():N}");
private static string Hash(string input)
{
using var sha = SHA256.Create();
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
Dat is precies de mindset van de hele serie: je kunt niet lekken wat je nooit opgeslagen.
flowchart TB
Signals["Generated signals
views/cart/purchase weights"] --> Persona["Persona enrichment
Ollama JSON-only"]
Persona --> Portrait[Portrait prompt]
Portrait --> Comfy[ComfyUI]
style Signals stroke:#1971c2,stroke-width:3px
style Persona stroke:#1971c2,stroke-width:3px
style Comfy stroke:#2f9e44,stroke-width:3px
Deze lokale pijpleiding is krachtig omdat het ondersteunt modelvalidatieNiet alleen demo's.
De belangrijke subtiliteit: door het genereren van zowel de tekst en de afbeeldingen, kunt u de gehele productervaring te valideren, niet alleen back-end wiskunde.
Deel 2: Sessieprofielen, signalen en segmentdefinities.
Deel 3 (coming): Outbox patroon, taak wachtrij, en de transparantie UI.
Generatorcode: Mostlylucid.SegmentCommerce.SampleData/
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.