Session 4: Bygning af produktionsklare chatapplikationer med Chainlit

January 29, 2026 · View on GitHub

Oversigt

Denne session fokuserer på at bygge produktionsklare chatapplikationer ved hjælp af Chainlit og Microsoft Foundry Local. Du vil lære at skabe moderne webgrænseflader til AI-samtaler, implementere streaming-svar og udrulle robuste chatapplikationer med korrekt fejlhåndtering og brugeroplevelsesdesign.

Hvad du vil bygge:

  • Chainlit Chat App: Moderne web-UI med streaming-svar
  • WebGPU Demo: Browserbaseret inferens for privatlivsfokuserede applikationer
  • Open WebUI Integration: Professionel chatgrænseflade med Foundry Local
  • Produktionsmønstre: Fejlhåndtering, overvågning og udrulningsstrategier

Læringsmål

  • Bygge produktionsklare chatapplikationer med Chainlit
  • Implementere streaming-svar for forbedret brugeroplevelse
  • Mestre Foundry Local SDK integrationsmønstre
  • Anvende korrekt fejlhåndtering og elegant nedgradering
  • Udrulle og konfigurere chatapplikationer til forskellige miljøer
  • Forstå moderne web-UI-mønstre for samtale-AI

Forudsætninger

  • Foundry Local: Installeret og kørende (Installationsvejledning)
  • Python: Version 3.10 eller nyere med mulighed for virtuelle miljøer
  • Model: Mindst én model indlæst (foundry model run phi-4-mini)
  • Browser: Moderne webbrowser med WebGPU-support (Chrome/Edge)
  • Docker: Til Open WebUI integration (valgfrit)

Del 1: Forstå moderne chatapplikationer

Arkitekturoversigt

User Browser ←→ Chainlit UI ←→ Python Backend ←→ Foundry Local ←→ AI Model
      ↓              ↓              ↓              ↓            ↓
   Web UI      Event Handlers   OpenAI Client   HTTP API    Local GPU

Nøgleteknologier

Foundry Local SDK Mønstre:

  • FoundryLocalManager(alias): Automatisk tjenestestyring
  • manager.endpoint og manager.api_key: Forbindelsesdetaljer
  • manager.get_model_info(alias).id: Modelidentifikation

Chainlit Framework:

  • @cl.on_chat_start: Initialiser chatsessioner
  • @cl.on_message: Håndter indkommende brugermeddelelser
  • cl.Message().stream_token(): Realtidsstreaming
  • Automatisk UI-generering og WebSocket-styring

Del 2: Lokal vs Cloud beslutningsmatrix

Ydelseskarakteristika

AspektLokal (Foundry)Cloud (Azure OpenAI)
Latens🚀 50-200ms (ingen netværk)⏱️ 200-2000ms (netværksafhængig)
Privatliv🔒 Data forlader aldrig enheden⚠️ Data sendes til skyen
Omkostninger💰 Gratis efter hardware💸 Betal pr. token
Offline✅ Fungerer uden internet❌ Kræver internet
Modelstørrelse⚠️ Begrænset af hardware✅ Adgang til de største modeller
Skalering⚠️ Hardwareafhængig✅ Ubegrænset skalering

Hybridstrategimønstre

Lokal først med fallback:

async def hybrid_completion(prompt: str, complexity_threshold: int = 100):
    if len(prompt.split()) < complexity_threshold:
        return await local_completion(prompt)  # Fast, private
    else:
        return await cloud_completion(prompt)   # Complex reasoning

Opgavebaseret routing:

async def smart_routing(prompt: str, task_type: str):
    routing_rules = {
        "code_generation": "local",     # Privacy-sensitive
        "creative_writing": "cloud",    # Benefits from larger models
        "data_analysis": "local",       # Fast iteration needed
        "research": "cloud"             # Requires broad knowledge
    }
    
    if routing_rules.get(task_type) == "local":
        return await foundry_completion(prompt)
    else:
        return await azure_completion(prompt)

Del 3: Eksempel 04 - Chainlit Chat Applikation

Hurtig start

# Navigate to Module08 directory  
cd Module08

# Start your preferred model
foundry model run phi-4-mini

# Run the Chainlit application (avoiding port conflicts)
chainlit run samples\04\app.py -w --port 8080

Applikationen åbner automatisk på http://localhost:8080 med en moderne chatgrænseflade.

Kerneimplementering

Eksempel 04-applikationen demonstrerer produktionsklare mønstre:

Automatisk tjenesteopdagelse:

import chainlit as cl
from openai import OpenAI
from foundry_local import FoundryLocalManager

# Global variables for client and model
client = None
model_name = None

async def initialize_client():
    global client, model_name
    alias = os.environ.get("MODEL", "phi-4-mini")
    
    try:
        # Use FoundryLocalManager for proper service management
        manager = FoundryLocalManager(alias)
        model_info = manager.get_model_info(alias)
        
        client = OpenAI(
            base_url=manager.endpoint,
            api_key=manager.api_key or "not-required"
        )
        model_name = model_info.id if model_info else alias
        return True
    except Exception as e:
        # Fallback to manual configuration
        base_url = os.environ.get("BASE_URL", "http://localhost:51211")
        client = OpenAI(base_url=f"{base_url}/v1", api_key="not-required")
        model_name = alias
        return True

Streaming chat-håndtering:

@cl.on_message
async def main(message: cl.Message):
    # Create streaming response
    msg = cl.Message(content="")
    await msg.send()
    
    stream = client.chat.completions.create(
        model=model_name,
        messages=[
            {"role": "system", "content": "You are a helpful AI assistant."},
            {"role": "user", "content": message.content}
        ],
        stream=True
    )
    
    # Stream tokens in real-time
    for chunk in stream:
        if chunk.choices[0].delta.content:
            await msg.stream_token(chunk.choices[0].delta.content)
    
    await msg.update()

Konfigurationsmuligheder

Miljøvariabler:

VariabelBeskrivelseStandardEksempel
MODELModelalias der skal brugesphi-4-miniqwen2.5-7b
BASE_URLFoundry Local endpointAuto-detekterethttp://localhost:51211
API_KEYAPI-nøgle (valgfri for lokal)""your-api-key

Avanceret brug:

# Use different model
set MODEL=qwen2.5-7b
chainlit run samples\04\app.py -w --port 8080

# Use different ports (avoid 51211 which is used by Foundry Local)
chainlit run samples\04\app.py -w --port 3000
chainlit run samples\04\app.py -w --port 5000

Del 4: Oprettelse og brug af Jupyter Notebooks

Oversigt over Notebook-support

Eksempel 04 inkluderer en omfattende Jupyter notebook (chainlit_app.ipynb), der tilbyder:

  • 📚 Uddannelsesindhold: Trinvise læringsmaterialer
  • 🔬 Interaktiv udforskning: Kør og eksperimenter med kodeceller
  • 📊 Visuelle demonstrationer: Diagrammer, grafer og outputvisualisering
  • 🛠️ Udviklingsværktøjer: Test- og fejlsøgningsmuligheder

Oprettelse af dine egne notebooks

Trin 1: Opsæt Jupyter-miljø

# Ensure you're in the Module08 directory
cd Module08

# Activate your virtual environment
.venv\Scripts\activate

# Install Jupyter and dependencies
pip install jupyter notebook jupyterlab ipykernel
pip install -r requirements.txt

# Register the kernel for VS Code
python -m ipykernel install --user --name=foundry-local --display-name="Foundry Local"

Trin 2: Opret en ny notebook

Brug af VS Code:

  1. Åbn VS Code i Module08-mappen
  2. Opret en ny fil med .ipynb-udvidelse
  3. Vælg "Foundry Local"-kernen, når du bliver bedt om det
  4. Begynd at tilføje celler med dit indhold

Brug af Jupyter Lab:

# Start Jupyter Lab
jupyter lab

# Navigate to samples/04/ and create new notebook
# Choose Python 3 kernel

Notebook-struktur bedste praksis

Celleorganisering

# Cell 1: Imports and Setup
import os
import sys
import chainlit as cl
from openai import OpenAI
from foundry_local import FoundryLocalManager

print("✅ Libraries imported successfully")
# Cell 2: Configuration and Client Setup
class FoundryClientManager:
    def __init__(self, model_name="phi-4-mini"):
        self.model_name = model_name
        self.client = None
        
    def initialize_client(self):
        # Client initialization logic
        pass

# Initialize and test
client_manager = FoundryClientManager()
result = client_manager.initialize_client()
print(f"Client initialized: {result}")

Interaktive eksempler og øvelser

Øvelse 1: Test af klientkonfiguration

# Test different configuration methods
configurations = [
    {"method": "foundry_sdk", "model": "phi-4-mini"},
    {"method": "manual", "base_url": "http://localhost:51211", "model": "qwen2.5-7b"},
]

for config in configurations:
    print(f"\n🧪 Testing {config['method']} configuration...")
    # Implementation here
    result = test_configuration(config)
    print(f"Result: {'✅ Success' if result['status'] == 'ok' else '❌ Failed'}")

Øvelse 2: Simulering af streaming-svar

import asyncio

async def simulate_streaming_response(text, delay=0.1):
    """Simulate how streaming works in Chainlit."""
    print("🌊 Simulating streaming response...")
    
    for char in text:
        print(char, end='', flush=True)
        await asyncio.sleep(delay)
    
    print("\n✅ Streaming complete!")

# Test the simulation
sample_text = "This is how streaming responses work in Chainlit applications!"
await simulate_streaming_response(sample_text)

Del 5: WebGPU Browser Inferens Demo

Oversigt

WebGPU gør det muligt at køre AI-modeller direkte i browseren for maksimal privatliv og nul-installationsoplevelser. Dette eksempel demonstrerer ONNX Runtime Web med WebGPU-udførelse.

Trin 1: Tjek WebGPU-support

Browserkrav:

  • Chrome/Edge 113+ med WebGPU aktiveret
  • Tjek: chrome://gpu → bekræft "WebGPU"-status
  • Programmatisk tjek: if (!('gpu' in navigator)) { /* no WebGPU */ }

Trin 2: Opret WebGPU Demo

Opret mappe: samples/04/webgpu-demo/

index.html:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>WebGPU + ONNX Runtime Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.webgpu.min.js"></script>
    <style>
        body { font-family: system-ui, sans-serif; margin: 2rem; }
        pre { background: #f5f5f5; padding: 1rem; overflow: auto; }
        .status { padding: 1rem; background: #e3f2fd; border-radius: 4px; }
    </style>
</head>
<body>
    <h1>🚀 WebGPU + Foundry Local Integration</h1>
    <div id="status" class="status">Initializing...</div>
    <pre id="output"></pre>
    <script type="module" src="./main.js"></script>
</body>
</html>

main.js:

const statusEl = document.getElementById('status');
const outputEl = document.getElementById('output');

function log(msg) {
    outputEl.textContent += `${msg}\n`;
    console.log(msg);
}

(async () => {
    try {
        if (!('gpu' in navigator)) {
            statusEl.textContent = '❌ WebGPU not available';
            return;
        }
        
        statusEl.textContent = '🔍 WebGPU detected. Loading model...';
        
        // Use a small ONNX model for demo
        const modelUrl = 'https://huggingface.co/onnx/models/resolve/main/vision/classification/mnist-12/mnist-12.onnx';
        
        const session = await ort.InferenceSession.create(modelUrl, {
            executionProviders: ['webgpu']
        });
        
        log('✅ ONNX Runtime session created with WebGPU');
        log(`📊 Input names: ${session.inputNames.join(', ')}`);
        log(`📊 Output names: ${session.outputNames.join(', ')}`);
        
        // Create dummy input (MNIST expects 1x1x28x28)
        const inputData = new Float32Array(1 * 1 * 28 * 28).fill(0.1);
        const input = new ort.Tensor('float32', inputData, [1, 1, 28, 28]);
        
        const feeds = {};
        feeds[session.inputNames[0]] = input;
        
        const results = await session.run(feeds);
        const output = results[session.outputNames[0]];
        
        // Find prediction (argmax)
        let maxIdx = 0;
        for (let i = 1; i < output.data.length; i++) {
            if (output.data[i] > output.data[maxIdx]) maxIdx = i;
        }
        
        statusEl.textContent = '✅ WebGPU inference complete!';
        log(`🎯 Predicted class: ${maxIdx}`);
        log(`📈 Confidence scores: [${Array.from(output.data).map(x => x.toFixed(3)).join(', ')}]`);
        
    } catch (error) {
        statusEl.textContent = `❌ Error: ${error.message}`;
        log(`Error: ${error.message}`);
        console.error(error);
    }
})();

Trin 3: Kør demoen

# Create demo directory
mkdir samples\04\webgpu-demo
cd samples\04\webgpu-demo

# Save HTML and JS files, then serve
python -m http.server 5173

# Open browser to http://localhost:5173

Del 6: Open WebUI Integration

Oversigt

Open WebUI tilbyder en professionel ChatGPT-lignende grænseflade, der forbinder til Foundry Locals OpenAI-kompatible API.

Trin 1: Forudsætninger

# Verify Foundry Local is running
foundry service status

# Start a model
foundry model run phi-4-mini

# Confirm API endpoint is accessible
curl http://localhost:51211/v1/models

Trin 2: Docker-opsætning (anbefalet)

# Pull Open WebUI image
docker pull ghcr.io/open-webui/open-webui:main

# Run with Foundry Local connection
docker run -d --name open-webui -p 3000:8080 ^
  -e OPENAI_API_BASE_URL=http://host.docker.internal:51211/v1 ^
  -e OPENAI_API_KEY=foundry-local-key ^
  -v open-webui-data:/app/backend/data ^
  ghcr.io/open-webui/open-webui:main

Bemærk: host.docker.internal giver Docker-containere adgang til værtsmaskinen på Windows.

Trin 3: Konfiguration

  1. Åbn browser: Naviger til http://localhost:3000
  2. Initial opsætning: Opret admin-konto
  3. Modelkonfiguration:
    • Indstillinger → Modeller → OpenAI API
    • Base URL: http://host.docker.internal:51211/v1
    • API-nøgle: foundry-local-key (enhver værdi fungerer)
  4. Test forbindelse: Modeller bør vises i dropdown-menuen

Fejlfinding

Almindelige problemer:

  1. Forbindelse nægtet:

    # Check Foundry Local status
    foundry service ps
    netstat -ano | findstr :51211
    
  2. Modeller vises ikke:

    • Bekræft, at modellen er indlæst: foundry model list
    • Tjek API-svar: curl http://localhost:51211/v1/models
    • Genstart Open WebUI-containeren

Del 7: Produktionsudrulningsovervejelser

Miljøkonfiguration

Udviklingsopsætning:

# Development with auto-reload and debugging
chainlit run samples\04\app.py -w --port 8080 --debug

Produktionsudrulning:

# Production mode with optimizations
chainlit run samples\04\app.py --host 0.0.0.0 --port 8080 --no-cache

Almindelige portproblemer og løsninger

Forebyggelse af port 51211-konflikt:

# Check what's using Foundry Local port
netstat -ano | findstr :51211

# Use different port for Chainlit
chainlit run samples\04\app.py -w --port 8080

Ydelsesovervågning

Implementering af sundhedstjek:

@cl.on_chat_start
async def health_check():
    try:
        # Test model availability
        response = client.chat.completions.create(
            model=model_name,
            messages=[{"role": "user", "content": "test"}],
            max_tokens=1
        )
        return {"status": "healthy", "model": model_name}
    except Exception as e:
        return {"status": "unhealthy", "error": str(e)}

Opsummering

Session 4 dækkede opbygning af produktionsklare Chainlit-applikationer til samtale-AI. Du lærte om:

  • Chainlit Framework: Moderne UI og streaming-support til chatapplikationer
  • Foundry Local Integration: SDK-brug og konfigurationsmønstre
  • WebGPU Inferens: Browserbaseret AI for maksimal privatliv
  • Open WebUI Opsætning: Udrulning af professionel chatgrænseflade
  • Produktionsmønstre: Fejlhåndtering, overvågning og skalering

Eksempel 04-applikationen demonstrerer bedste praksis for at bygge robuste chatgrænseflader, der udnytter lokale AI-modeller via Microsoft Foundry Local, samtidig med at den leverer fremragende brugeroplevelser.

Referencer


Ansvarsfraskrivelse:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten Co-op Translator. Selvom vi bestræber os på nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.