ai

Text Generation WebUI กับ SaaS Architecture —

Text Generation WebUI กับ SaaS Architecture —

Text Generation WebUI คืออะไร

Text Generation WebUI กับ SaaS Architecture —

Text Generation WebUI เป็น Open-source Web Interface สำหรับรัน Large Language Model (LLM) แบบ Self-hosted พัฒนาโดย oobabooga รองรับ Model หลากหลายเช่น Llama 3, Mistral, Phi-3, Qwen และ Gemma ผ่าน Backend หลายตัวเช่น llama.cpp, ExLlamaV2, Transformers และ vLLM ผู้ใช้สามารถ Chat กับ AI, ปรับ Parameters, สลับ Model และใช้ Extensions ต่างๆผ่าน Browser

เนื้อหาเกี่ยวข้อง — อ่านต่อ: company web design — ข้อมูลครบถ้วน 2026

เมื่อต้องการให้บริการ Text Generation ให้ผู้ใช้หลายคน เช่น ภายในองค์กรหรือเป็น SaaS Product ต้องออกแบบ Architecture ที่รองรับ Multi-tenant, GPU Resource Management, Authentication, Rate Limiting และ Billing ซึ่งมีความซับซ้อนมากกว่าการรันบนเครื่องส่วนตัว

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง SSD PCIe M.2 คือ — เปรียบเทียบ NVMe SATA พร้อม

SaaS Architecture Overview

  • API Gateway (Kong/Nginx): จัดการ Authentication, Rate Limiting, Load Balancing
  • Auth Service: JWT Token, API Key Management, Tenant Isolation
  • Request Queue (Redis/RabbitMQ): จัดคิว Inference Requests ตาม Priority
  • GPU Scheduler: จัดสรร GPU ให้แต่ละ Request ตาม Tenant Plan
  • Inference Workers (vLLM/TGI): รัน LLM Inference จริง บน GPU Nodes
  • Model Registry: จัดการ Model Versions, Hot-swap Models
  • Usage Tracker: บันทึก Token Usage สำหรับ Billing
  • Billing Service: คำนวณค่าบริการตาม Token Usage

การตั้งค่า vLLM เป็น Inference Backend

# docker-compose.yml สำหรับ Text Generation SaaS
version: "3.8"

services:
  # API Gateway
  kong:
    image: kong:3.5
    environment:
      KONG_DATABASE: "off"
      KONG_DECLARATIVE_CONFIG: /kong/kong.yml
      KONG_PROXY_LISTEN: "0.0.0.0:8000, 0.0.0.0:8443 ssl"
    volumes:
      - ./kong.yml:/kong/kong.yml
    ports:
      - "8000:8000"
      - "8443:8443"

  # Redis สำหรับ Queue และ Rate Limiting
  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 2gb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data

  # vLLM Inference Server (GPU Node 1)
  vllm-worker-1:
    image: vllm/vllm-openai:latest
    command: >
      --model meta-llama/Llama-3.1-8B-Instruct
      --max-model-len 8192
      --gpu-memory-utilization 0.90
      --max-num-seqs 32
      --tensor-parallel-size 1
      --port 8080
      --api-key 
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    environment:
      HUGGING_FACE_HUB_TOKEN: 

  # vLLM Inference Server (GPU Node 2 — Model อื่น)
  vllm-worker-2:
    image: vllm/vllm-openai:latest
    command: >
      --model mistralai/Mistral-7B-Instruct-v0.3
      --max-model-len 8192
      --gpu-memory-utilization 0.90
      --max-num-seqs 32
      --port 8080
      --api-key 
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    environment:
      HUGGING_FACE_HUB_TOKEN: 

  # Auth + API Service
  api-server:
    build: ./api-server
    environment:
      REDIS_URL: redis://redis:6379
      DATABASE_URL: postgresql://app:@postgres:5432/saas
      JWT_SECRET: 
      VLLM_ENDPOINTS: "vllm-worker-1:8080, vllm-worker-2:8080"
    depends_on:
      - redis
      - postgres

  # PostgreSQL สำหรับ User/Billing Data
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: saas
      POSTGRES_USER: app
      POSTGRES_PASSWORD: 
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  redis_data:
  postgres_data:

---
# kong.yml — API Gateway Configuration
_format_version: "3.0"

services:
  - name: llm-api
    url: http://api-server:3000
    routes:
      - name: llm-route
        paths:
          - /v1/chat/completions
          - /v1/completions
          - /v1/models
        strip_path: false

plugins:
  - name: rate-limiting
    config:
      minute: 60
      policy: redis
      redis_host: redis
      redis_port: 6379

  - name: key-auth
    config:
      key_names:
        - Authorization
        - X-API-Key

  - name: cors
    config:
      origins:
        - "*"
      methods:
        - GET
        - POST
        - OPTIONS
      headers:
        - Authorization
        - Content-Type

API Server กับ Multi-tenant Logic

Text Generation WebUI กับ SaaS Architecture —
# api-server/main.py — FastAPI Server สำหรับ Multi-tenant LLM
from fastapi import FastAPI, HTTPException, Depends, Header
from pydantic import BaseModel
import httpx
import asyncio
import redis.asyncio as redis
import json
import time
from datetime import datetime

app = FastAPI(title="LLM SaaS API")

# Redis Connection
redis_client = redis.from_url("redis://redis:6379", decode_responses=True)

# vLLM Endpoints
VLLM_ENDPOINTS = {
    "llama-3.1-8b": "http://vllm-worker-1:8080",
    "mistral-7b": "http://vllm-worker-2:8080",
}

class ChatRequest(BaseModel):
    model: str = "llama-3.1-8b"
    messages: list[dict]
    max_tokens: int = 1024
    temperature: float = 0.7
    stream: bool = False

class TenantInfo:
    def __init__(self, tenant_id, plan, rate_limit, token_limit):
        self.tenant_id = tenant_id
        self.plan = plan
        self.rate_limit = rate_limit
        self.token_limit = token_limit

async def authenticate(authorization: str = Header(...)) -> TenantInfo:
    """Authenticate API Key และดึง Tenant Info"""
    api_key = authorization.replace("Bearer ", "")
    tenant_data = await redis_client.hgetall(f"apikey:{api_key}")
    if not tenant_data:
        raise HTTPException(status_code=401, detail="Invalid API key")
    return TenantInfo(
        tenant_id=tenant_data["tenant_id"],
        plan=tenant_data["plan"],
        rate_limit=int(tenant_data.get("rate_limit", 60)),
        token_limit=int(tenant_data.get("token_limit", 100000)),
    )

async def check_rate_limit(tenant: TenantInfo):
    """ตรวจสอบ Rate Limit ต่อนาที"""
    key = f"ratelimit:{tenant.tenant_id}:{int(time.time()) // 60}"
    count = await redis_client.incr(key)
    await redis_client.expire(key, 120)
    if count > tenant.rate_limit:
        raise HTTPException(status_code=429, detail="Rate limit exceeded")

async def track_usage(tenant_id: str, model: str, prompt_tokens: int, completion_tokens: int):
    """บันทึก Token Usage สำหรับ Billing"""
    today = datetime.now().strftime("%Y-%m-%d")
    usage_key = f"usage:{tenant_id}:{today}"
    await redis_client.hincrby(usage_key, "prompt_tokens", prompt_tokens)
    await redis_client.hincrby(usage_key, "completion_tokens", completion_tokens)
    await redis_client.hincrby(usage_key, "requests", 1)
    await redis_client.expire(usage_key, 86400 * 90)  # เก็บ 90 วัน

@app.post("/v1/chat/completions")
async def chat_completions(
    request: ChatRequest,
    tenant: TenantInfo = Depends(authenticate),
):
    await check_rate_limit(tenant)

    # เลือก vLLM Endpoint ตาม Model
    endpoint = VLLM_ENDPOINTS.get(request.model)
    if not endpoint:
        raise HTTPException(status_code=400, detail=f"Model {request.model} not available")

    # Forward Request ไป vLLM
    async with httpx.AsyncClient(timeout=120.0) as client:
        resp = await client.post(
            f"{endpoint}/v1/chat/completions",
            json=request.model_dump(),
            headers={"Authorization": f"Bearer {VLLM_API_KEY}"},
        )

    result = resp.json()

    # Track Usage
    usage = result.get("usage", {})
    await track_usage(
        tenant.tenant_id,
        request.model,
        usage.get("prompt_tokens", 0),
        usage.get("completion_tokens", 0),
    )

    return result

@app.get("/v1/models")
async def list_models(tenant: TenantInfo = Depends(authenticate)):
    """List Available Models ตาม Tenant Plan"""
    models = list(VLLM_ENDPOINTS.keys())
    if tenant.plan == "free":
        models = [m for m in models if "8b" in m.lower()]
    return {"data": [{"id": m, "object": "model"} for m in models]}

GPU Scheduling และ Autoscaling

# kubernetes/gpu-autoscaler.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-llama
  namespace: llm-saas
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vllm-llama
  template:
    metadata:
      labels:
        app: vllm-llama
    spec:
      containers:
        - name: vllm
          image: vllm/vllm-openai:latest
          args:
            - "--model"
            - "meta-llama/Llama-3.1-8B-Instruct"
            - "--max-model-len"
            - "8192"
            - "--gpu-memory-utilization"
            - "0.90"
            - "--max-num-seqs"
            - "32"
          resources:
            limits:
              nvidia.com/gpu: 1
              memory: 32Gi
            requests:
              nvidia.com/gpu: 1
              memory: 24Gi
          ports:
            - containerPort: 8000
          readinessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 120
            periodSeconds: 10
      nodeSelector:
        gpu-type: a100
      tolerations:
        - key: nvidia.com/gpu
          operator: Exists
          effect: NoSchedule
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: vllm-llama-hpa
  namespace: llm-saas
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: vllm-llama
  minReplicas: 1
  maxReplicas: 8
  metrics:
    - type: Pods
      pods:
        metric:
          name: vllm_num_requests_running
        target:
          type: AverageValue
          averageValue: "20"
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 2
          periodSeconds: 120
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Pods
          value: 1
          periodSeconds: 300

Monitoring และ Cost Management

  • GPU Utilization: ใช้ NVIDIA DCGM Exporter + Prometheus ติดตาม GPU Memory, Compute Utilization และ Temperature
  • Request Metrics: ติดตาม Requests/sec, Latency P50/P95/P99, Queue Length, Error Rate แยกตาม Model และ Tenant
  • Token Throughput: วัด Tokens/sec สำหรับทั้ง Input และ Output เพื่อ Capacity Planning
  • Cost per Token: คำนวณต้นทุนต่อ Token จาก GPU Cost + Infra Cost หารด้วย Total Tokens เพื่อกำหนดราคา
  • Tenant Usage Dashboard: แสดง Token Usage, Request Count และ Cost ต่อ Tenant ต่อวัน

Text Generation WebUI คืออะไร

Text Generation WebUI เป็น Open-source Web Interface สำหรับรัน LLM แบบ Local รองรับ Model เช่น Llama, Mistral, Phi ผ่าน Backend หลายตัว ให้ผู้ใช้ Chat กับ AI ผ่าน Browser โดยไม่ต้องส่งข้อมูลไป Cloud เหมาะสำหรับองค์กรที่ต้องการ Data Privacy

แนะนำเพิ่มเติม — อีบุ๊กการลงทุน SiamCafeBook

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน การสร้าง smart contract ข้อใดกล่าวถูกต้อง

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง