# LLMAPI: Real-Time Mock Data med LLMs och SignalR: En praktisk guide

<!--category-- AI, LLM, LLMApi , ASP.NET Core, API, Nuget, mockllmapi, SignalR, AI-Article-->
<datetime class="hidden">2025-11-04T21:15</datetime>

# Inledning

[![Hämta](https://img.shields.io/nuget/v/mostlylucid.mockllmapi.svg)](https://www.nuget.org/packages/mostlylucid.mockllmapi) [![Hämta](https://img.shields.io/nuget/dt/mostlylucid.mockllmapi.svg)](https://www.nuget.org/packages/mostlylucid.mockllmapi)

> OBS: This artikeln är främst AI genererad som en del av mitt nuget paket som release dokumentation. Det är ganska intressant så jag lägger det här men om det är ett problem för dig vänligen ignorera det.

Som en del av min [Nuget paket LLMApi / mestadels lucid.mockllmapi ](https://www.nuget.org/packages/mostlylucid.mockllmapi) Jag behövde ha en sida för att aktivera användningen av SignalR funktioner den har (det kan simulera SignalR-flöden med hjälp av LLMs för att ge data). Så detta är vad jag kom fram till.

Du kan hitta[ GitHub här ](https://github.com/scottgal/LLMApi)för projektet, alla offentliga domäner etc...

Det blev snabbt ett riktigt fint verktyg!

![SignalR-simulator](signalrsimulator.png)

Om du någonsin har behövt att bygga en instrumentpanel eller realtid UI innan den faktiska datakällan finns, vet du utmaningen. Du slutar skriva hårdkodade JSON fixturer eller utarbeta `setInterval()` loopar som roterar genom samma handfull objekt.

Jag byggde denna SignalR demo för att lösa det problemet på ett mer flexibelt sätt. Du beskriver vilka data du behöver på vanlig engelska, och en lokal LLM genererar realistiska, varierade JSON som strömmar till din webbläsare i realtid. Inga fixturer att underhålla, inga fröfiler att uppdatera, bara beskriva vad du vill och se det flöda.

Låt mig visa hur det fungerar och hur man får ut det mesta av det.

[TOC]

## Vad detta verktyg gör

På sidan SignalR demo (`Index.cshtml`) är en kontrollpanel för hantering av dataströmmar i realtid. Här är det grundläggande flödet:

1. Du skapar en "context" (en namngiven dataström)
2. Du beskriver vilken typ av data du vill ha på engelska
3. En LLM genererar lämplig JSON baserat på din beskrivning
4. SignalR skickar nya data till din webbläsare var femte sekund
5. Du ser resultaten med syntax highlighting i realtid

Det är särskilt användbart när du prototypar, bygger demos, eller arbetar på frontend funktioner medan väntar på backend API:er för att vara redo. Datan ser realistisk eftersom LLM förstår sammanhang och genererar lämpliga värden.

### Den stora bilden

```mermaid
graph TB
    Browser[Your Browser]
    UI[Demo UI]
    API[Management API]
    Hub[SignalR Hub]
    Manager[Context Manager]
    BG[Background Service]
    LLM[LLM Ollama/OpenAI]
    Cache[Response Cache]

    Browser -->|Create Context| API
    API -->|Store Config| Manager
    Browser -->|Connect Subscribe| Hub
    Hub -->|Register Client| Manager
    BG -->|Generate Data| LLM
    LLM -->|Return JSON| BG
    BG -->|Cache Responses| Cache
    BG -->|Push to Clients| Hub
    Hub -->|Real-time Updates| Browser

```

## Varför SignalR för realtidsuppdateringar?

SignalR upprätthåller en ihållande WebSocket-anslutning mellan din webbläsare och servern. Istället för att välja en endpoint med några sekunder med HTTP-förfrågningar trycker servern på data när den är klar. Detta ger dig verkligen realtidsuppdateringar med minimal overhead.

Anslutningen förblir öppen, data flödar omedelbart, och din UI känner sig mycket mer lyhörd. Det är samma teknik som används i chattapplikationer, live-paneler och samarbetsverktyg där omedelbara uppdateringar spelar roll.

## Snabbstart: Kom igång i 5 minuter

Låt oss börja med den snabbaste vägen för att se detta fungerar. Jag ska visa dig en aktiemarknad data exempel.

**Steg 1: Starta ansökan**

```bash
dotnet run --project LLMApi/LLMApi.csproj
```

Navigera till `http://localhost:5116` (kontrollera konsolutmatningen för den faktiska porten).

**Steg 2: Använd ett snabbstartsexempel**

Du kommer att se fem förkonfigurerade exempel med gröna "Launch"-knappar. Klicka på "Stock Market" och du är klar. Sidan automatiskt:

- Skapar ett sammanhang för aktiemarknadens data
- Prenumererar din webbläsare för att få uppdateringar
- Börjar visa live lagerdata med priser, volymer och förändringar

**Steg 3: Titta på dataströmmen**

Var femte sekund visas nya data med syntaxmarkering. Varje uppdatering visar olika aktier med realistiska priser och handelsvolymer. LLM genererar nya data varje gång, så du ser variation samtidigt som du behåller en konsekvent struktur.

Det är allt! Du streamar nu mock aktiemarknad data. Känn dig fri att utforska de andra snabbstart exempel för att se olika datamönster.

## Skapa egna egna dataflöden

De snabba startknapparna är praktiska, men den verkliga kraften kommer från att beskriva exakt vad du behöver. Låt oss skapa ett anpassat exempel.

**Exempel: Kaffemaskin telemetri**

Säg att du bygger en IoT instrumentpanel och behöver simulerad kaffemaskin data. Så här:

```
Context Name: coffee-machines
Description: Coffee machine telemetry with machine ID, beans remaining percentage,
             water temperature in Celsius, cups brewed today, and last maintenance timestamp
```

Klicka på "Skapa & Prenumerera" och du är avstängd.

### Vad som händer bakom kulisserna

```mermaid
sequenceDiagram
    participant Browser
    participant API
    participant Manager
    participant BG as Background Service
    participant LLM
    participant Hub

    Browser->>API: POST /api/mock/contexts<br/>{name, description}
    API->>Manager: Store context config
    Manager-->>API: Context created ✓
    API-->>Browser: 200 OK

    Browser->>Hub: invoke('SubscribeToContext', 'coffee-machines')
    Hub->>Manager: Register subscription
    Manager-->>Hub: Subscription confirmed
    Hub-->>Browser: on('Subscribed')

    Note over BG,LLM: Every 5 seconds...
    BG->>LLM: Generate data for 'coffee-machines'<br/>Prompt includes description
    LLM-->>BG: JSON response
    BG->>Hub: Broadcast to 'coffee-machines' group
    Hub-->>Browser: on('DataUpdate', {data})
    Browser->>Browser: Display with syntax highlighting
```

Systemet:

1. Skapar sammanhanget i gränssnittet
2. Prenumererar din webbläsare för att få uppdateringar via SignalR
3. Börjar generera data baserat på din beskrivning
4. Trycker på uppdateringar var femte sekund

Du kommer att se utdata så här:

```json
{
  "machineId": "CM-2847",
  "beansRemaining": 67,
  "waterTemp": 94.5,
  "cupsBrewed": 142,
  "lastMaintenance": "2025-01-03T08:23:00Z"
}
```

Varje uppdatering har olika värden men bibehåller strukturen. LLM förstår "kaffemaskin telemetri" och genererar siffror som är vettiga i det sammanhanget.

## Förståelse för sammanhang

En förteckning över de behöriga myndigheter som avses i punkt 1 i denna artikel ska upprättas i enlighet med det förfarande som avses i artikel 4 i förordning (EU) nr 952/2013. **Bakgrund** är en namngiven dataströmskonfiguration. Se det som en kanal eller ett ämne.

När du skapar en, anger du:

- **Beteckning**: En unik identitetsbeteckning (t.ex. `weather`, `stock-market`, `sensors`)
- **Varuslag**: Den datastruktur du vill ha, på klar engelska

Gränssnittet då:

- Skapar en SignalR- grupp med det namnet
- Bygger en prompt för LLM baserat på din beskrivning
- Genererar färska data regelbundet (var femte sekund som standard)
- Sänder den till alla abonnenter

Flera webbläsare kan prenumerera på samma sammanhang och de får alla samma data samtidigt. Detta är bra för att testa instrumentpaneler som behöver visa synkroniserade uppdateringar över olika skärmar eller komponenter.

### Sammanhang Lifecycle State Machine

```mermaid
stateDiagram-v2
    [*] --> Created: Create Context<br/>(POST /contexts)

    Created --> Active: Start<br/>(auto or manual)
    Active --> Stopped: Stop<br/>(POST /stop)
    Stopped --> Active: Start<br/>(POST /start)

    Created --> Subscribed: Client Subscribes
    Active --> Subscribed: Client Subscribes
    Stopped --> Subscribed: Client Subscribes<br/>(no data sent)

    Subscribed --> Receiving: Data Push<br/>(if Active)
    Receiving --> Subscribed: Client Connected

    Subscribed --> Created: Unsubscribe
    Subscribed --> Active: Unsubscribe
    Subscribed --> Stopped: Unsubscribe

    Created --> [*]: Delete
    Active --> [*]: Delete
    Stopped --> [*]: Delete
    Subscribed --> [*]: Delete

    note right of Active
        Generates data
        Pushes to clients
        Shows "Active" badge
    end note

    note right of Stopped
        No data generation
        Clients stay connected
        Shows "Stopped" badge
    end note
```

## Förstå användargränssnittets layout

Gränssnittet har tre paneler för att hålla saker organiserade:

### Vänster: Skapa sammanhang

Här definierar du nya dataströmmar. Du behöver:

- **Sammanhangsnamn**: Gör det unikt och beskrivande. Använda smått-med-dashes fungerar bra.
- **Varuslag**: Var specifik om vad du vill. LLM fungerar bäst med tydliga beskrivningar som "användarprofiler med namn, e-post, ålder och premium status boolean."

Du behöver inte skriva JSON scheman eller förklara datatyper. LLM infer struktur från naturliga språkbeskrivningar förvånansvärt bra.

### Mitten: Aktiva sammanhang

Visar alla dina löpande sammanhang med:

- Namn och statusbricka (aktiv/stoppad)
- Anslutningsräkning (hur många klienter som för närvarande tecknas)
- Kontrollknappar: Ansluta, Koppla ner, Starta, Stoppa, Ta bort

**Anslut/koppla ner** styr din webbläsares prenumeration. Klicka på Anslut för att börja ta emot data, Koppla ner för att sluta utan att ta bort sammanhanget.

**Starta/stoppa** styr datagenerering i gränssnittet. Det är användbart när du vill pausa en ström utan att förstöra den sammanhangsberoende inställningen.

**Ta bort** tar bort sammanhanget helt och hållet. Använd det här för att rensa upp när du är klar med en viss dataström.

### Höger: Livedata

Här ser du uppdateringar i realtid:

- Indikator för anslutningsstatus (Ansluten/frånkopplad)
- För närvarande prenumererat sammanhangsnamn
- Senaste 10 meddelanden med tidsstämpel och syntaxfärgläggning

Data visas nyaste-först i toppen, så du ser alltid de senaste uppdateringarna utan att scrolla.

## Anslutningsmönstret för JavaScript

Sidan använder HTMX för formulärinlämning och SignalR för realtidsanslutning. Om du bygger din egen klient, här är SignalR mönstret du behöver:

### Kundanslutningsflöde

```mermaid
sequenceDiagram
    participant Page as Your Page
    participant SR as SignalR Client
    participant Hub as /hub/mock
    participant BG as Background Service

    Page->>SR: new HubConnectionBuilder()<br/>.withUrl('/hub/mock')
    Page->>SR: connection.start()
    SR->>Hub: WebSocket connection
    Hub-->>SR: Connected ✓
    SR-->>Page: Trigger 'connected' event

    Page->>SR: invoke('SubscribeToContext', 'weather')
    SR->>Hub: SubscribeToContext('weather')
    Hub->>Hub: Add to 'weather' group
    Hub-->>SR: on('Subscribed', {context: 'weather'})
    SR-->>Page: Display "Subscribed"

    loop Every 5 seconds
        BG->>Hub: Broadcast to 'weather' group
        Hub->>SR: on('DataUpdate', {data, timestamp})
        SR->>Page: Update UI with new data
    end

    Page->>SR: invoke('UnsubscribeFromContext', 'weather')
    SR->>Hub: UnsubscribeFromContext('weather')
    Hub->>Hub: Remove from 'weather' group
```

**Ställa in anslutningen:**

```javascript
const connection = new signalR.HubConnectionBuilder()
    .withUrl('/hub/mock')
    .withAutomaticReconnect()
    .build();

connection.on('DataUpdate', (message) => {
    // message.context: which context sent this
    // message.data: the actual JSON payload
    // message.timestamp: Unix timestamp in milliseconds
});

await connection.start();
```

**Att prenumerera på att ta emot data:**

```javascript
await connection.invoke('SubscribeToContext', 'my-context-name');
```

**Avsluta prenumerationen när den är klar:**

```javascript
await connection.invoke('UnsubscribeFromContext', 'my-context-name');
```

Demosidan hanterar allt detta automatiskt, men dessa tre mönster är allt du behöver för en anpassad implementering.

## Praktiska användningsfall

Här är några scenarier där detta verktyg verkligen lyser:

**1. Bygga användargränssnitt innan API:er finns**

Du arbetar på en instrumentpanel och backend teamet fortfarande utforma API schema. Istället för att blockera på deras arbete, beskriva den datastruktur du förväntar dig och bygga din UI mot mock ström. När den verkliga API är redo, du kommer bara byta slutpunkt.

**2. Kunddemonstrationer**

Du degraderar en live övervakning instrumentpanel till en klient, men den faktiska data pipeline är inte klar ännu. Skapa sammanhang som matchar din planerade datastruktur och visa realistiska, föränderliga data under presentationen. Det ser professionellt och hjälper kunden visualisera den slutliga produkten.

**3. Frontend utveckling och testning**

Du behöver realistiska, varierande data för att testa hur dina diagram, tabeller och komponenter hanterar uppdateringar. Skapa sammanhang med de strukturer du behöver och utveckla ditt användargränssnitt med tillförsikt om att det hanterar verkliga datamönster.

**4. Belastningstester i realtidsfunktioner**

Du vill se hur din användargränssnitt fungerar under snabba uppdateringar. Skapa en högfrekvent kontext och se hur dina komponenter hanterar dataflödet. Detta hjälper till att identifiera prestandaproblem före produktionen.

**5. Undervisning WebSockets och realtidskoncept**

Du undervisar SignalR eller WebSocket koncept och vill att studenterna ska se realtidsuppdateringar utan att bygga ett komplett backend. Demo ger ett fungerande exempel som de kan experimentera med och lära av.

## Snabbstartsexempel förklarade

De fem förkonfigurerade exemplen visar olika vanliga datamönster:

**IoT-sensorer**: Numeriska sensoravläsningar med enhetsmetadata
**Börs**: Finansiella uppgifter med priser, volymer och procentuella förändringar
**E-handelsorder**: Inbäddade objekt med beställningsmatriser
**Tröskelvärden för servern**: Systemövervakning med flera prestandamått
**Spelande leaderboard**: Spelarens ranking med statistik och status

Dessa exempel är klara att gå. Klicka på Starta, titta på data, och använda dem som mallar för dina egna sammanhang.

## API-slutpunkter för integration

Om du bygger en anpassad klient eller integrerar detta i ett annat program, här är HTTP-slutpunkter:

**Skapa ett sammanhang:**

```bash
curl -X POST http://localhost:5116/api/mock/contexts \
  -H "Content-Type: application/json" \
  -d '{"name": "sensors", "description": "Temperature sensors with device ID and readings"}'
```

**Lista alla sammanhang:**

```bash
curl http://localhost:5116/api/mock/contexts
```

**Få ett specifikt sammanhang:**

```bash
curl http://localhost:5116/api/mock/contexts/sensors
```

**Starta eller stoppa datagenerering:**

```bash
curl -X POST http://localhost:5116/api/mock/contexts/sensors/start
curl -X POST http://localhost:5116/api/mock/contexts/sensors/stop
```

**Stryk ett sammanhang:**

```bash
curl -X DELETE http://localhost:5116/api/mock/contexts/sensors
```

Efter att ha skapat ett sammanhang, ansluta till SignalR navet på `/hub/mock` och prenumerera för att börja ta emot uppdateringar.

## Hur LLM Generation fungerar

När du skapar ett sammanhang, systemet:

1. Tar din beskrivning
2. Bygger en snabb som inkluderar slumpmässighet (GUID utsäde + tidsstämpel för sort)
3. Be LLM att generera lämplig JSON som matchar din beskrivning
4. Validerar svaret är faktiskt JSON (strips markdown vid behov)
5. Caches flera svar för snabb leverans
6. Genererar mer i bakgrunden för att hålla cachen fylld

Temperaturen är inställd på 1,2 (relativt hög) för att säkerställa variation. När du ber om "användardata", får du olika namn och värden varje gång, inte samma få återvunna oändligt. Datan förblir strukturellt konsekvent medan varierande realistiskt.

## Prestanda och smart Caching

Datagenerering sker i bakgrunden, inte på begäran per push. Detta håller uppdateringar konsekvent och minskar LLM belastning.

Så här fungerar det:

- Vid start fyller systemet i en cache med svar för varje aktivt sammanhang
- Det mäter hur lång generation tar (säg, 500 ms per begäran)
- Den beräknar optimal batchstorlek: push intervall  på produktionstid (5000 ms 500 ms = 10 objekt)
- Det genererar satser i bakgrunden för att hålla cachen toppad
- När det är dags att trycka, drar det från cache omedelbart

Resultat: Ditt första meddelande anländer omedelbart, efterföljande meddelanden kommer konsekvent var femte sekund, och LLM trycks inte kontinuerligt.

### Det smarta cacheflödet

```mermaid
graph LR
    subgraph Startup
        A[App Starts] --> B[Pre-fill Cache]
        B --> C[Measure Gen Time<br/>500ms]
        C --> D[Calculate Batch<br/>5000ms / 500ms = 10]
    end

    subgraph Runtime Loop
        E[Timer Tick<br/>Every 5s] --> F{Cache > 50%?}
        F -->|Yes| G[Pop from Cache]
        F -->|No| H[Generate Batch<br/>in Background]
        G --> I[Push to Clients]
        H --> J[Refill Cache]
        J --> G
        I --> E
    end

    D --> E

    style B stroke:#10b981,stroke-width:3px
    style G stroke:#0ea5e9,stroke-width:3px
    style H stroke:#ef4444,stroke-width:3px
    style I stroke:#f59e0b,stroke-width:3px
```

## Felsökning av gemensamma frågor

**Anslutning visar "Disconnected" och kommer inte att ansluta igen**

- Kontrollera att din LLM-tjänst (Ollama/OpenAI) kör
- Förvald inställning förväntar sig Ollama vid `http://localhost:11434`
- Kör `ollama list` för att verifiera att du har modeller installerade
- Kontrollera webbläsarens konsol för SignalR-anslutningsfel

**Sammanhang skapas men inga data visas**

- Titta på panelen Active Contexts – är sammanhanget som visar "Active"?
- Klicka på knappen Anslut om du inte har prenumererat ännu
- Verifiera anslutningsstatusen visar grön (Ansluten) i panelen Live Data
- Kontrollera serverloggar för att se om LLM-generationen fungerar

**Datastrukturen stämmer inte med vad du förväntade dig.**

- Gör din beskrivning mer specifik och konkret
- Exempel: "temperatur som tal mellan 0 och 100" fungerar bättre än bara "temperatur"
- Försök att återskapa din beskrivning – detta är snabb ingenjörskonst på jobbet
- Kontrollera genererade data och förfina din beskrivning baserat på vad du ser

**Webbläsarens konsol visar SignalR-återkopplingsförsök**

- Gränssnittet kanske inte kör – kontrollera terminalen
- Du kan ha ändrat porten – uppdatera SignalR-hubbens URL om det behövs
- Kontrollera brandväggs- eller nätverksproblem (särskilt i Docker/WSL-miljöer)

## Inställningsalternativ

Du kan anpassa beteende i `appsettings.json`:

```json
{
  "MockLlmApi": {
    "SignalRPushIntervalMs": 5000,  // How often to push data (milliseconds)
    "ModelName": "llama3",           // Which LLM model to use
    "Temperature": 1.2,              // Creativity level (0.0-2.0, higher = more varied)
    "BaseUrl": "http://localhost:11434",  // LLM service URL
    "HubContexts": [                 // Optional: pre-configured contexts
      {
        "Name": "weather",
        "Description": "Weather data with temperature, humidity, wind speed",
        "IsActive": true
      }
    ]
  }
}
```

**SignalRPush IntervalMs**: Ställ in lägre för snabbare uppdateringar, högre för att minska LLM belastning
**Temperatur**: Högre värden ger mer kreativa/slumpmässiga data, lägre ger mer konsekventa resultat
**HubContexts (HubContexts)**: Definiera sammanhang som startar automatiskt när programmet startar

## Integrering med din ansökan

Om du bygger en riktig instrumentpanel och vill använda detta under utveckling, här är ett React exempel:

```javascript
import * as signalR from '@microsoft/signalr';

const connection = new signalR.HubConnectionBuilder()
  .withUrl('http://localhost:5116/hub/mock')
  .withAutomaticReconnect()
  .build();

connection.on('DataUpdate', (message) => {
  if (message.context === 'stock-market') {
    updateStockChart(message.data);
  }
});

await connection.start();
await connection.invoke('SubscribeToContext', 'stock-market');
```

När du är redo att byta till produktion, bara ändra nav URL. SignalR gränssnittet (`on()` och `invoke()`) fungerar på samma sätt med riktiga backends.

## Varför bygga upp detta?

Det finns bra databibliotek där ute. Faker.js är utmärkt. Mockaroo gör bra arbete. Så varför bygga ett annat verktyg?

Detta verktyg löser specifika utmaningar:

1. **streaming i realtid**: De flesta verktyg ger dig statiska datauppsättningar eller REST endpoints, inte live WebSocket strömmar
2. **Gränssnitt för naturligt språk**: Beskriv vad du vill istället för att skriva JSON scheman
3. **Sammanhangsmässigt lämpliga uppgifter**: LLMs genererar realistiska värden som är vettiga tillsammans, inte bara slumpmässiga strängar som råkar passa en typ
4. **Självdokumentering**: Beskrivningen är dokumentationen för din datastruktur
5. **Flexibel struktur**: Ändra din datamodell mid-development utan att uppdatera fixturer

Det är utformat för ett specifikt arbetsflöde: bygga realtids användargränssnitt när du behöver varierande, realistiska data utan konfiguration overhead.

## Komma igång

Det bästa sättet att förstå detta verktyg är att använda det:

1. Starta ansökan: `dotnet run --project LLMApi`
2. Öppna din webbläsare för att `http://localhost:5116`
3. Klicka på en av de gröna "Launch"-knapparna
4. Titta på dataströmmen i

Därifrån kan du prova att skapa ditt eget sammanhang med en beskrivning som motsvarar ditt projekts behov. Verktyget är mest värdefullt när du använder det för verkligt utvecklingsarbete.

Jag byggde detta eftersom jag fortsatte att stöta på samma problem: att behöva realistiska, ändra data för demos och utveckling. Om du står inför den utmaningen också, Jag hoppas att detta verktyg hjälper ditt arbetsflöde.

---


## Snabbreferens

**Börjar:**

```bash
dotnet run --project LLMApi
```

**Förvald webbadress:** `http://localhost:5116`

**Signal-Hub:** `/hub/mock`

**Nyckelmetoder:**

- `SubscribeToContext(name)` - Börja ta emot data
- `UnsubscribeFromContext(name)` - Sluta ta emot data

**Viktiga händelser:**

- `DataUpdate` - Nya uppgifter har kommit.
- `Subscribed` - Bekräftad prenumeration
- `Unsubscribed` - Uppsägning bekräftad

Resten är bara att utforska vad man kan bygga med den.