This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Null PII Kunden Intelligence - Del | 1.1: | Genererande av proverdata ♫ ( ♫ och bilder ♫) ♫ Lokalt
Wednesday, 31 December 2025
I Del 1 vi täckte filosofin:", transparent segmentation utan PII, . Del 2 täcker sessionsprofiler, signaler , och segmentdefinitioner
Men först hur kan man validera något av detta utan att någonsin röra vid riktiga kunders data?
För den här serien genererar jag en komplett syntetisk e-commerce dataset lokalt:
- Produktkatalog ( namn , beschreibungar, märkenM SK3 priserMSC4
- Anonyma “profiler” / personer ( intressen + signaler)
- Produktbilder ( och profilporträtt ) via ComfyUI
- Optionell DB-import så att den riktiga appen kan köra emot den
Det här är en av dom där. “, det känns som att fuska. ♫ ”, arbetsflöden. ♪ :, du får realistiska ingångar. | ,, du kan regenerera dem närsomhelst.
Varför är lokala syntetiska data så kraftfulla
Om du bygger segmentering, personalisering och personalisering, behöver du datamängder som:
- Ha tillräckligt med variation för att bryta naivt heuristik
- Är säkra att dela med sig av ( i koden , tester
- Är reproducerbara ( så att du kan jämföra modellförändringarM SK1
Verkliga data är motsatsen.
Syntetiska data ger dig tre superkrafter:
- snabb repetition: byta segmenteringslogiken , regenerera M SK2 återskapa
- Förhärdning: simulera märkliga långa kretsar
- Förklaringstest: kan du inspektera varje genererade fält och bekräfta din “skaffa mig varför
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
verktyget ( Vad som faktiskt körs)
Generatoren lever i Mostlylucid.SegmentCommerce.SampleData.
Det är inte avsiktligt ett ramverk, det är en pragmatisk CLI som talar med
- Ollama (lokal LLM) för strukturerad generation av JSONM SK2
- KomfyUI (lokal stabil diffusering) för produktfotografering -stilbilderM SK3
- A taksonom JSON som håller utsläppen konsekventa (kategorier, typerM SK2 varianter , prissegmenter
Konfigurationen är kopplad upp så att du kan köra den via miljövariabler:
// Mostlylucid.SegmentCommerce.SampleData/Program.cs
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables("SAMPLEDATA_")
.Build();
Vinnigstart
Du kommer typically att köra tre lokala tjänster tillsammans med generatorn.
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
kör generatorn från repo root:
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- status
Sedan generera en datauppsättning:
# 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
användbara skivor:
# 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
Beteckning: om ComfyUI inte är tillgängligt’ , så ramlar generatorn tillbaka till placeholderbilderna M SK4 den använder picsum.photos, så att vägen inte är --no-images.
v2 Generatorn : Försäljare | → | produkter | МSK3 | kunder |→ | order | → | inrymme
Det finns också ett nytt genereringskommando (gen) som bygger upp en mer komplett
# 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
Den är orkestrerad som en multi- -Phass- -Pipeline.
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
Och du kan se dessa faser direkt i koden:
// 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
Embeddings (Local ONNX , Cached after first run)
Generatoren v2 kan bearbeta embeddings med hjälp av en ONNX-modell. all-MiniLM-L6-v2). När du kör den första gången , så laddas den ned modellen och kommer in i ditt utgångsordnet
Det betyder:".
- Den första körningen behöver tillgång till nätverk (modelldownload)
- Efterföljande prover är lokala och snabba
- Om du vill köra “ inget nätverk någonsin
--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);
}
Hur vi genererar “LLM-formadeM SK2 produkter (JSON-onlystMSC4
Product generation prompten är uppsåtligt strikt: LLM måste bara ge tillbaka JSON , med ett inbyggdt JSON-skemaexamples
// 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:
""";
Detta spelar roll eftersom system i nedströmning (bildskapande + införing ♫ + ♫ inbäddar ♫) ♫ vill ha strukturerade data ♫ ingångar till en pipeline, inte skriva noter
LLM-responser : analysera JSON, eller falla tillbaka
LLMs är inte kompilatorer. Även med “JSON baraM SK2 behöver du fortfarande försvarsmässigt analysera och eleganta fallbackar
Generatoren v2 gör det via en liten hjälpman (LlmService) som extraherar den första {...} blockera och deserialisera den:
// 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
});
}
Och den totala produktionskedjan explicit kontrollerar tillgänglighet och nedgraderingar till deterministiska templater när det behövs:
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
exempel: Kunden Personas (vM SK2
Person prompten för kunder är kort och strukturerad så den kan skapas snabbt med en liten lokal modell:
// 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: Produktfotografering via API
ComfyUI är jättebra eftersom det ger dig en styrbar pipeline ( arbetsflöden ) snarare än ett ♫ “ en enda svarta låda bild slutpunkt ”.
Generatorn:
- Lader ett arbetsflödes-template (
ComfyUI/workflows/product_image.json) - Patchar prompten till
CLIPTextEncode - köer
/prompt - Poller
/history/{promptId} - ladda ned bilden via
/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
KomfyUI-modellselektionen är också patchad in i arbetsflödet vid starttid ( så du kan byta kontrollpunkter utan att redigera JSON
// 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");
Och arbetsflödet att patcha är avsiktligt enkelt och robust
// 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;
}
}
Profile och personligheter (användbar, Inte läskigtM SK2
Generatoren v1 skapar anonyma profiler och förstärker dem med en person. (still ingen PII, ). Då får du realistiska data.
I v1,-profiler aktiveras med hjälp av en oneM SK1way hash , så det finns inget att ’
// 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();
}
Att "’" är exakt samma tankesätt som hela serien, att ":", du kan "’", att inte läcka ut det du aldrig har lagrat.
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
Validation: Vad detta låter dig bevisa
Den här lokala pipelinen är kraftfull eftersom den modellvalidering, inte bara demonstrerade
- Segmenteringshygien: gör segmenten du bearbetar “ känner dig koherent | ” | när du undersöker produkternas namn
- Förklaringsförmågan till förslaget: visar mig varför
- Kaldstart: om du löser datauppsättningen och återskapar den , beter systemet förutsägbart
- Regressionstest: återskapa samma form av data och se till att dina ändringar inte bryter pris
Den viktiga subtiliteten : genom att generera både text och bilder, du kan validera hela produktupplevelsen , inte bara tillbaka
Vad' är nästa
Del 2: Sektionsprofiler , signaler M SK2 och segmentdefinitioner — där vi kopplar dessa data till arbetssegmentationen
Del 3 ( kommande ): utgångsmönsterna i utboxen M SK2 arbetslinjet , och transparenta gränssnittet
Generatorkod: Mostlylucid.SegmentCommerce.SampleData/