# Zero PII Intelligence des clients - Partie 1.1: Gérer les données d'échantillonnage (et les images) localement

<!--category-- Product, Privacy, LLM, ComfyUI, C# -->
<datetime class="hidden">2025-12-31T20:00</datetime>

À l'intérieur [Partie 1](/blog/zero-pii-customer-intelligence-part1) Nous avons couvert la philosophie de segmentation transparente sans PII. [Partie 2](/blog/zero-pii-customer-intelligence-part2) couvre les profils de session, signauxM SK1 et définitions des segments.

Mais tout d’abord **Comment valider quelque chose de cela sans jamais toucher les données réelles des clients?**

Pour cette série, j’élabore un ensemble de données synthétiques complète sur le commerce électronique localement:

- Catalogue de produits (nomsM SK1 descriptions , étiquettesMSC3 prix)
- Nom anonyme “profilsM SK1 / personnes (intérêts S+ signaux)
- Images de produits (et portraits de profils) via ComfyUI
- Importation de DB facultative pour que l'application réelle puisse s'y opposer

C'est l'un de ces “il se sent comme un chevauchement ” les flux de travail: vous obtiendrez des intrants réalistesMSC3 vous pouvez les régénérer à tout momentM SK4 et vous n'introduissez jamais PII dans votre environnement de dével

## Pourquoi les données synthétiques locales sont si puissantes

Si vous construisez une segmentation / personalisation , vous avez besoin d’un ensemble de données qui

- Avoir suffisamment de variation pour briser l'héuristique naïve
- sont sûrs de partager (dans le codeM SK1essais ,démos)
- sont reproductibles (soit que vous pouvez comparer les modifications du modèleM SK1

Les données réelles sont l’inverse.

Les données synthétiques vous donnent trois superpuisances:

1. **Iteration rapide**: changer la logique de segmentationM SK1 régénérer , re-runMSC4
2. **Dégradation**: simuler des comportements de taille étranges longs - que vous aurez obtenus dans un petit ensemble de données devM SK2 ne voyez pas
3. **Évaluation de l'explicabilité**: vous pouvez *inspecter chaque champ généré* et confirmez votre “ montrez-moi pourquoi l’interface de ” est vraie

```mermaid
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
```

## Utilisation (Qu'est-ce qui fonctionne en fait?

Le générateur vit dans `Mostlylucid.SegmentCommerce.SampleData`.

Il ne s’agit pas intentionnellement d’un cadre, mais plutôt d’une CLI pragmatique qui discute avec la Commission.

- **Ollama** (local LLM) pour la génération structurelle de JSONM SK2
- **ComfyUI** (diffusion locale stableM SK1 pour la photographie du produit-images de styleMSC3
- A **taxonomie JSON** qui maintient la cohérence des produits (catégories,typesM SK2 variantes , plages de prixMSC4

La configuration est câblée de sorte que vous pouvez la déplacer par des variables environnementales:

```csharp
// Mostlylucid.SegmentCommerce.SampleData/Program.cs
var configuration = new ConfigurationBuilder()
    .SetBasePath(AppContext.BaseDirectory)
    .AddJsonFile("appsettings.json", optional: true)
    .AddEnvironmentVariables("SAMPLEDATA_")
    .Build();
```

## Démarrage rapide

Vous effectuez habituellement trois services locaux à côté du générateur.

```mermaid
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
```

Faire fonctionner le générateur à partir de la racine repo:

```bash
dotnet run --project Mostlylucid.SegmentCommerce.SampleData -- status
```

Ensuite, générer un ensemble de données:

```bash
# 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
```

Switches utiles:

```bash
# 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
```

Remarque: si ComfyUI n'est pas disponibleM SK1 non disponible , le générateur v1 revient aux images de place-holders MSC4 il utilise `picsum.photos`, de sorte que le chemin n'est pas “ entièrement hors ligne”). Si vous voulez strictementM SK3localMSC4 fonctionner avec `--no-images`.

## v2 GénérateurM SK1 Vendeurs → Produits → Clients → Commandes → Embeddings

Il y a aussi un nouveau commande de générateur (`gen`) qui construit un marché plus complet

```bash
# 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
```

Il s’agit d’un pipeline à phases multiples.

```mermaid
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
```

Vous pouvez voir ces phases directement dans le code:

```csharp
// 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 ONNXM SK1 Caché après le premier essai)

Le générateur v2 peut calculer les embeddings à l'aide d'un modèle ONNX. `all-MiniLM-L6-v2`). La première fois que vous l’utilisez, , il télécharge le modèle et le vocab dans votre dossier de sortie.

Cela signifie

- Pour le premier essai, il faut avoir accès au réseau ( téléchargement de modèle)
- Les essais subséquents sont locaux et rapides
- Si vous voulez que “aucun réseau n'a jamais été exploité `--no-embeddings`

```csharp
// 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);
}
```

## Comment nous produisons “LLM-ShapedM SK2 Produits (JSON seulementMSC4

Le prompt de production du produit est délibérément strict: le LLM doit retourner JSON seulement, avec un exemple de schéma JSON embeddedM SK2

```csharp
// 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:
    """;
```

Cela est important parce que les systèmes en aval (génération d'images + importation MSC2 embeddings MSC3 veulent des données structurées MSc4 Le LLM produit *entrées dans un pipeline*, ne écrit pas de prose.

### Réponses de LLM: Parser JSON, ou Retourner

Les LLM ne sont pas compilers. Même avec “JSON seulementM SK2 vous avez toujours besoin d’une analyse défensive et de la rétroaction graceuse .

Le générateur v2 le fait par l'intermédiaire d'un petit outil (`LlmService`) qui extrait la première `{...}` bloquer et déserialiser ce dernier:

```csharp
// 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
    });
}
```

L’ensemble du pipeline de production vérifie explicitement la disponibilité des modèles déterministes et les reclassements lorsque cela est nécessaire:

```mermaid
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
```

### Exemple: Personnes clients M SK1v2)

Le message personnel pour les clients est court et structuré de sorte qu’il peut être produit rapidement avec un petit modèle local:

```csharp
// 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: Photographie de produit via API

ComfyUI est excellent parce qu'il vous donne un pipeline contrôlable (workflows) plutôt qu'un point final d'image unique de la boîte noire “

Le générateur:

1. Charge un modèle de flux de travail (`ComfyUI/workflows/product_image.json`)
2. Patche le prompt dans `CLIPTextEncode`
3. Couloirs `/prompt`
4. Enquêtes `/history/{promptId}`
5. Télécharge l'image par `/view?...`

```mermaid
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
```

La sélection du modèle ComfyUI est également prise en charge dans le flux de travail au moment de l'exécution (soit que vous pouvez échanger les points de contrôle sans modifier la JSON):

```csharp
// 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");
```

Et le patchage du flux de travail est intentionnellement simple et robuste:

```csharp
// 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;
    }
}
```

## Profils et personnalités (UsefulM SK1 Not Creepy)

Le générateur v1 crée des profils anonymes et les enrichit ensuite d’une personne M SK1pas encore de PII). Vous obtiendrez des données réalistes “personnesMSC4forméesMST5 sans courrielsMSL6 adresses MST7 ou tout ce que vous pourriez éventuellement expédier par accident

Dans v1,, les profils sont chiffrés à l’aide d’un oneM SK1way hash , de sorte qu’il n’y a rien à “recoverMSC5

```csharp
// 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();
}
```

C’est exactement la mentalité de toute la série.

```mermaid
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: Ce que cela vous permet de prouver

Ce pipeline local est puissant parce qu'il appuie *validation du modèle*, pas seulement les démonstrationsM SK1

- **Santé par segmentation**: les segments que vous computez “ le sentiment de cohérence M SK2 l'inspection des noms de produits / les marques et les personnes générées MSC4
- **Expliquement de la recommandation**: montre-t-il “me montre pourquoiM SK2 je pointe vers un signal réel que vous pouvez vérifier?
- **Démarrage froid**: si vous nettoyez l’ensemble de données et que vous régénérez les données , le système se comporte-t-il prévisiblement ?
- **Essais de régression**: régénérer la même forme de données et vous assurer que vos changements n’entraînent pas une interruption du classement

La subtilité importante: par la production des deux *Textes* et le *images*, vous pouvez valider l'ensemble de l'expérience du produitM SK1 pas seulement le retour - terminer la mathématique.

## Quoi' Suivant

**[Partie 2](/blog/zero-pii-customer-intelligence-part2)**: Profils de sessionM SK1 signaux, et définitions des segments —dans lesquels nous connectons ces données d'échantillon à la segmentation de travailMSC4

**Partie 3** ( arrivant ): Modèle de la boîte d'envoi, cote des tâchesM SK3 et l'interface de transparenceMSC4

---


*Code de générateur: `Mostlylucid.SegmentCommerce.SampleData/`*