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
LLMAPI: Real-Time Mock Data med LLMs och SignalR: En praktisk guide
Tuesday, 04 November 2025
Inledning
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 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 för projektet, alla offentliga domäner etc...
Det blev snabbt ett riktigt fint verktyg!

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.
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:
- Du skapar en "context" (en namngiven dataström)
- Du beskriver vilken typ av data du vill ha på engelska
- En LLM genererar lämplig JSON baserat på din beskrivning
- SignalR skickar nya data till din webbläsare var femte sekund
- 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
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
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
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:
- Skapar sammanhanget i gränssnittet
- Prenumererar din webbläsare för att få uppdateringar via SignalR
- Börjar generera data baserat på din beskrivning
- Trycker på uppdateringar var femte sekund
Du kommer att se utdata så här:
{
"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
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
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:
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:
await connection.invoke('SubscribeToContext', 'my-context-name');
Avsluta prenumerationen när den är klar:
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:
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:
curl http://localhost:5116/api/mock/contexts
Få ett specifikt sammanhang:
curl http://localhost:5116/api/mock/contexts/sensors
Starta eller stoppa datagenerering:
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:
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:
- Tar din beskrivning
- Bygger en snabb som inkluderar slumpmässighet (GUID utsäde + tidsstämpel för sort)
- Be LLM att generera lämplig JSON som matchar din beskrivning
- Validerar svaret är faktiskt JSON (strips markdown vid behov)
- Caches flera svar för snabb leverans
- 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
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 listfö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:
{
"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:
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:
- streaming i realtid: De flesta verktyg ger dig statiska datauppsättningar eller REST endpoints, inte live WebSocket strömmar
- Gränssnitt för naturligt språk: Beskriv vad du vill istället för att skriva JSON scheman
- 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
- Självdokumentering: Beskrivningen är dokumentationen för din datastruktur
- 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:
- Starta ansökan:
dotnet run --project LLMApi - Öppna din webbläsare för att
http://localhost:5116 - Klicka på en av de gröna "Launch"-knapparna
- 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:
dotnet run --project LLMApi
Förvald webbadress: http://localhost:5116
Signal-Hub: /hub/mock
Nyckelmetoder:
SubscribeToContext(name)- Börja ta emot dataUnsubscribeFromContext(name)- Sluta ta emot data
Viktiga händelser:
DataUpdate- Nya uppgifter har kommit.Subscribed- Bekräftad prenumerationUnsubscribed- Uppsägning bekräftad
Resten är bara att utforska vad man kan bygga med den.