Skip to content

Latest commit

ย 

History

79 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

LLM-Quality-Observer

Release License Stars Docker Prometheus Grafana

Production-ready MLOps platform for LLM quality monitoring

๐Ÿ‡ฐ๐Ÿ‡ท KR | ๐Ÿ‡บ๐Ÿ‡ธ EN


๊ฐœ์š”

LLM-Quality-Observer๋Š” ๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ(LLM)์˜ ์‘๋‹ต ํ’ˆ์งˆ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ MLOps ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค. ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋˜์–ด LLM ์ƒํ˜ธ์ž‘์šฉ์„ ๋กœ๊น…ํ•˜๊ณ , ์ž๋™์œผ๋กœ ํ’ˆ์งˆ์„ ํ‰๊ฐ€ํ•˜๋ฉฐ, ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ

  • โœ… Gateway API: LLM ์š”์ฒญ ์ฒ˜๋ฆฌ ๋ฐ ์ž๋™ ๋กœ๊น…
  • โœ… ์ž๋™ ํ‰๊ฐ€: ๊ทœ์น™ ๊ธฐ๋ฐ˜ + LLM-as-a-Judge ์ด์ค‘ ํ‰๊ฐ€ ์‹œ์Šคํ…œ
  • โœ… ์Šค์ผ€์ค„๋Ÿฌ: ๋ฐฐ์น˜ ํ‰๊ฐ€ ์ž๋™ ์‹คํ–‰ (APScheduler)
  • โœ… ๋‹ค์ค‘ ์ฑ„๋„ ์•Œ๋ฆผ: Slack, Discord, Email ํ†ตํ•ฉ
  • โœ… ๋ชจ๋‹ˆํ„ฐ๋ง: Prometheus ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ + Grafana ๋Œ€์‹œ๋ณด๋“œ
  • โœ… ๊ณ ๊ธ‰ ์•Œ๋ฆผ: Alertmanager ํ†ตํ•ฉ (42๊ฐœ ํ”„๋กœ๋•์…˜ Alert Rules)
  • โœ… ๊ณ ๊ธ‰ ๋ถ„์„: ์‹œ๊ฐ„๋Œ€๋ณ„ ํ’ˆ์งˆ ํŠธ๋ Œ๋“œ + ๋ชจ๋ธ ์„ฑ๋Šฅ ๋น„๊ต API
  • โœ… ์›น ๋Œ€์‹œ๋ณด๋“œ: Next.js ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ํ’ˆ์งˆ ์‹œ๊ฐํ™”
  • โœ… ๋‹ค๊ตญ์–ด ์ง€์›: ์˜์–ด, ํ•œ๊ตญ์–ด, ์ผ๋ณธ์–ด, ์ค‘๊ตญ์–ด
  • โœ… CI/CD: GitHub Actions ์ž๋™ํ™” ํŒŒ์ดํ”„๋ผ์ธ

ํ˜„์žฌ ๋ฒ„์ „: v0.6.0 โ€” Alertmanager, Alert Rules, ๊ณ ๊ธ‰ ๋ถ„์„ API ์ถ”๊ฐ€ ์™„๋ฃŒ


๐Ÿ“Š ์•„ํ‚คํ…์ฒ˜

flowchart TB
    subgraph "ํด๋ผ์ด์–ธํŠธ"
        ClientApp[Client/Browser]
    end

    subgraph "ํ”„๋ก ํŠธ์—”๋“œ"
        WebDashboard["Next.js Dashboard<br/>:3000"]
        Grafana["Grafana<br/>:3001"]
    end

    subgraph "๋ฐฑ์—”๋“œ ์„œ๋น„์Šค"
        Gateway["Gateway API<br/>:18000"]
        Evaluator["Evaluator<br/>:18001"]
        Dashboard["Streamlit Dashboard<br/>:18002"]
    end

    subgraph "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค"
        Postgres["PostgreSQL<br/>:5432"]
    end

    subgraph "๋ชจ๋‹ˆํ„ฐ๋ง & ์•Œ๋ฆผ"
        Prometheus["Prometheus<br/>:9090"]
        Alertmanager["Alertmanager<br/>:9093"]
    end

    subgraph "์™ธ๋ถ€ ์„œ๋น„์Šค"
        OpenAI_Main["OpenAI GPT<br/>(Main Model)"]
        OpenAI_Judge["OpenAI GPT<br/>(Judge Model)"]
    end

    subgraph "์•Œ๋ฆผ ์ฑ„๋„"
        Slack["Slack"]
        Discord["Discord"]
        Email["Email<br/>(SMTP)"]
    end

    %% ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ
    ClientApp --> WebDashboard
    ClientApp --> Gateway

    %% Gateway ์—ฐ๊ฒฐ
    Gateway --> OpenAI_Main
    Gateway --> Postgres
    Gateway -.๋ฉ”ํŠธ๋ฆญ.-> Prometheus

    %% Evaluator ์—ฐ๊ฒฐ
    Postgres --> Evaluator
    Evaluator --> OpenAI_Judge
    Evaluator --> Slack
    Evaluator --> Discord
    Evaluator --> Email
    Evaluator -.๋ฉ”ํŠธ๋ฆญ.-> Prometheus

    %% Dashboard ์—ฐ๊ฒฐ
    Postgres --> Dashboard

    %% ๋ชจ๋‹ˆํ„ฐ๋ง ์—ฐ๊ฒฐ
    Prometheus --> Grafana
    Prometheus --> Alertmanager
    Alertmanager --> Slack
    Alertmanager --> Discord
    Alertmanager --> Email

    style Gateway fill:#4CAF50
    style Evaluator fill:#2196F3
    style Postgres fill:#FF9800
    style Prometheus fill:#E91E63
    style Alertmanager fill:#F44336
    style Grafana fill:#9C27B0
    style OpenAI_Main fill:#00BCD4
    style OpenAI_Judge fill:#00BCD4
Loading

์„œ๋น„์Šค ๊ตฌ์„ฑ

์„œ๋น„์Šค ํฌํŠธ ์„ค๋ช…
Gateway API 18000 LLM ์š”์ฒญ ์ฒ˜๋ฆฌ ๋ฐ ๋กœ๊น… (FastAPI)
Evaluator 18001 ์ž๋™ ํ‰๊ฐ€ ๋ฐ ์•Œ๋ฆผ (FastAPI)
Dashboard 18002 Streamlit ๋Œ€์‹œ๋ณด๋“œ (๋ ˆ๊ฑฐ์‹œ)
Web Dashboard 3000 Next.js ์›น ๋Œ€์‹œ๋ณด๋“œ
PostgreSQL 5432 ๋กœ๊ทธ ๋ฐ ํ‰๊ฐ€ ๊ฒฐ๊ณผ ์ €์žฅ
Prometheus 9090 ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ ๋ฐ Alert Rules
Alertmanager 9093 Alert ๋ผ์šฐํŒ… ๋ฐ ๊ทธ๋ฃนํ•‘
Grafana 3001 ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ (3๊ฐœ ๋Œ€์‹œ๋ณด๋“œ)

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ

  • Docker & Docker Compose
  • OpenAI API Key
  • (์„ ํƒ) Slack/Discord Webhook URL
  • (์„ ํƒ) Gmail SMTP ๊ณ„์ •

์„ค์น˜

  1. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํด๋ก 
git clone https://github.com/dongkoony/LLM-Quality-Observer.git
cd LLM-Quality-Observer
  1. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •
cp configs/env/.env.local.example configs/env/.env.local
# .env.local ํŒŒ์ผ ํŽธ์ง‘ํ•˜์—ฌ API ํ‚ค ์„ค์ •
  1. ์„œ๋น„์Šค ์‹œ์ž‘
cd infra/docker
docker compose -f docker-compose.local.yml up --build
  1. ์„œ๋น„์Šค ํ™•์ธ
# Gateway API
curl http://localhost:18000/health

# Evaluator
curl http://localhost:18001/health

# Prometheus
open http://localhost:9090

# Grafana
open http://localhost:3001  # admin/admin

๐Ÿ“– ์‚ฌ์šฉ ๊ฐ€์ด๋“œ

1. LLM ์š”์ฒญ ์ „์†ก

curl -X POST "http://localhost:18000/chat" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Explain quantum computing in simple terms",
    "user_id": "test-user",
    "model_version": "gpt-5-mini"
  }'

์‘๋‹ต ์˜ˆ์‹œ:

{
  "id": 1,
  "prompt": "Explain quantum computing...",
  "response": "Quantum computing is...",
  "model_version": "gpt-5-mini",
  "latency_ms": 1234,
  "status": "success"
}

2. ํ‰๊ฐ€ ์‹คํ–‰

์ˆ˜๋™ ํ‰๊ฐ€:

# ๊ทœ์น™ ๊ธฐ๋ฐ˜ ํ‰๊ฐ€
curl -X POST "http://localhost:18001/evaluate-once?limit=10&judge_type=rule"

# LLM-as-a-Judge ํ‰๊ฐ€
curl -X POST "http://localhost:18001/evaluate-once?limit=10&judge_type=llm"

์ž๋™ ํ‰๊ฐ€: ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์„ค์ •๋œ ๊ฐ„๊ฒฉ(๊ธฐ๋ณธ 60๋ถ„)๋งˆ๋‹ค ์ž๋™ ์‹คํ–‰

3. ๋Œ€์‹œ๋ณด๋“œ ํ™•์ธ

Grafana ๋Œ€์‹œ๋ณด๋“œ:

  1. http://localhost:3001 ์ ‘์†
  2. admin/admin์œผ๋กœ ๋กœ๊ทธ์ธ
  3. Dashboards โ†’ LLM Quality Observer ์„ ํƒ

ํฌํ•จ๋œ ๋ฉ”ํŠธ๋ฆญ:

  • HTTP ์š”์ฒญ ๋น„์œจ ๋ฐ ์ง€์—ฐ์‹œ๊ฐ„
  • LLM ๋ชจ๋ธ๋ณ„ ์„ฑ๋Šฅ
  • ํ‰๊ฐ€ ์ ์ˆ˜ ๋ถ„ํฌ
  • ์•Œ๋ฆผ ์ „์†ก ํ˜„ํ™ฉ
  • ์Šค์ผ€์ค„๋Ÿฌ ์‹คํ–‰ ์ƒํƒœ

4. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ

# PostgreSQL ์ ‘์†
docker exec -it llm-postgres psql -U llm_user -d llm_quality

# ์ตœ๊ทผ ๋กœ๊ทธ ํ™•์ธ
SELECT id, created_at, user_id,
       LEFT(prompt, 50) AS prompt,
       model_version, latency_ms, status
FROM llm_logs
ORDER BY id DESC
LIMIT 10;

# ํ‰๊ฐ€ ๊ฒฐ๊ณผ ํ™•์ธ
SELECT l.id, l.prompt,
       e.score_overall, e.score_instruction_following, e.score_truthfulness,
       e.judge_type, e.comments
FROM llm_logs l
JOIN llm_evaluations e ON l.id = e.log_id
ORDER BY e.created_at DESC
LIMIT 10;

๐Ÿ”ง ์ฃผ์š” ๊ธฐ๋Šฅ ์ƒ์„ธ

Gateway API (v0.1.0+)

์—”๋“œํฌ์ธํŠธ:

  • GET /health - ํ—ฌ์Šค ์ฒดํฌ
  • POST /chat - LLM ์š”์ฒญ ์ฒ˜๋ฆฌ
  • GET /docs - Swagger UI
  • GET /metrics - Prometheus ๋ฉ”ํŠธ๋ฆญ

๊ธฐ๋Šฅ:

  • OpenAI GPT ๋ชจ๋ธ ํ˜ธ์ถœ
  • ์ž๋™ ๋กœ๊น… (ํ”„๋กฌํ”„ํŠธ, ์‘๋‹ต, ์ง€์—ฐ์‹œ๊ฐ„, ์ƒํƒœ)
  • ๋ชจ๋ธ ๋ฒ„์ „ ์ถ”์ 
  • Prometheus ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ถœ

Evaluator Service (v0.2.0+)

ํ‰๊ฐ€ ๋ฐฉ์‹:

  1. ๊ทœ์น™ ๊ธฐ๋ฐ˜ ํ‰๊ฐ€ (๋น ๋ฆ„, ์ €๋ ด):

    • ์‘๋‹ต ๊ธธ์ด ๊ฒ€์‚ฌ
    • ํ‚ค์›Œ๋“œ ๊ฒ€์ฆ
    • ํฌ๋งท ์ค€์ˆ˜ ํ™•์ธ
  2. LLM-as-a-Judge (v0.3.0+, ์ •ํ™•, ๋น„์šฉ ๋ฐœ์ƒ):

    • GPT-4 ๊ธฐ๋ฐ˜ ํ’ˆ์งˆ ํ‰๊ฐ€
    • ๋‹ค์ฐจ์› ์ ์ˆ˜ (์ „์ฒด, ์ง€์‹œ์‚ฌํ•ญ ์ค€์ˆ˜, ์ง„์‹ค์„ฑ)
    • ์ƒ์„ธํ•œ ํ‰๊ฐ€ ์ฝ”๋ฉ˜ํŠธ

์ž๋™ ์Šค์ผ€์ค„๋Ÿฌ (v0.4.0+):

  • APScheduler๋กœ ์ฃผ๊ธฐ์  ํ‰๊ฐ€
  • ์„ค์ • ๊ฐ€๋Šฅํ•œ ๊ฐ„๊ฒฉ ๋ฐ ๋ฐฐ์น˜ ํฌ๊ธฐ
  • ์ž๋™ ์‹œ์ž‘/์ •์ง€

์•Œ๋ฆผ ์‹œ์Šคํ…œ (v0.4.0+, v0.5.0):

  • Slack: ์›นํ›… ํ†ตํ•ฉ
  • Discord: ์›นํ›… ํ†ตํ•ฉ
  • Email (v0.5.0): SMTP (Gmail ๋“ฑ)
  • ๋‚ฎ์€ ํ’ˆ์งˆ ์ฆ‰์‹œ ์•Œ๋ฆผ
  • ๋ฐฐ์น˜ ํ‰๊ฐ€ ์š”์•ฝ

๋ชจ๋‹ˆํ„ฐ๋ง (v0.5.0)

Prometheus ๋ฉ”ํŠธ๋ฆญ:

  • llm_gateway_http_requests_total - HTTP ์š”์ฒญ ์ˆ˜
  • llm_gateway_http_request_duration_seconds - ์š”์ฒญ ์ง€์—ฐ์‹œ๊ฐ„
  • llm_gateway_llm_requests_total - LLM ํ˜ธ์ถœ ์ˆ˜
  • llm_evaluator_evaluations_total - ํ‰๊ฐ€ ์ˆ˜
  • llm_evaluator_evaluation_scores - ์ ์ˆ˜ ๋ถ„ํฌ
  • llm_evaluator_notifications_sent_total - ์•Œ๋ฆผ ์ „์†ก ์ˆ˜
  • llm_evaluator_pending_logs - ํ‰๊ฐ€ ๋Œ€๊ธฐ ๋กœ๊ทธ ์ˆ˜

Grafana ๋Œ€์‹œ๋ณด๋“œ:

  • 14๊ฐœ ์‹œ๊ฐํ™” ํŒจ๋„
  • ์‹ค์‹œ๊ฐ„ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง
  • ํ’ˆ์งˆ ์ถ”์„ธ ๋ถ„์„
  • ์•Œ๋ฆผ ํ˜„ํ™ฉ ์ถ”์ 

โš™๏ธ ์„ค์ •

ํ™˜๊ฒฝ ๋ณ€์ˆ˜

# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
APP_ENV=local
LOG_LEVEL=DEBUG

# LLM ๋ชจ๋ธ
OPENAI_MODEL_MAIN=gpt-5-mini          # Gateway์—์„œ ์‚ฌ์šฉํ•  ๋ชจ๋ธ
OPENAI_MODEL_JUDGE=gpt-4o-mini        # ํ‰๊ฐ€์— ์‚ฌ์šฉํ•  ๋ชจ๋ธ
LLM_API_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-...

# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
DATABASE_URL=postgresql://llm_user:llm_password@postgres:5432/llm_quality

# ๋ฐฐ์น˜ ํ‰๊ฐ€ ์Šค์ผ€์ค„๋Ÿฌ (v0.4.0+)
ENABLE_AUTO_EVALUATION=true           # ์ž๋™ ํ‰๊ฐ€ ํ™œ์„ฑํ™”
EVALUATION_INTERVAL_MINUTES=60        # ํ‰๊ฐ€ ์ฃผ๊ธฐ (๋ถ„)
EVALUATION_BATCH_SIZE=10              # ๋ฐฐ์น˜ ํฌ๊ธฐ
EVALUATION_JUDGE_TYPE=rule            # ๊ธฐ๋ณธ ํ‰๊ฐ€ ๋ฐฉ์‹ (rule/llm)

# ์•Œ๋ฆผ ์„ค์ • (v0.4.0+)
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR/WEBHOOK/URL
NOTIFICATION_SCORE_THRESHOLD=3        # ์•Œ๋ฆผ ์ž„๊ณ„๊ฐ’ (โ‰ค 3์ )

# ์ด๋ฉ”์ผ ์•Œ๋ฆผ (v0.5.0+)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=your-email@gmail.com
SMTP_TO_EMAILS=recipient1@example.com,recipient2@example.com

๐Ÿ—๏ธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

LLM-Quality-Observer/
โ”œโ”€โ”€ services/
โ”‚   โ”œโ”€โ”€ gateway-api/           # Gateway API ์„œ๋น„์Šค
โ”‚   โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ main.py        # FastAPI ์•ฑ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ config.py      # ์„ค์ •
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ llm_client.py  # OpenAI ํด๋ผ์ด์–ธํŠธ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ db.py          # ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ models.py      # SQLAlchemy ๋ชจ๋ธ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ schemas.py     # Pydantic ์Šคํ‚ค๋งˆ
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ metrics.py     # Prometheus ๋ฉ”ํŠธ๋ฆญ
โ”‚   โ”‚   โ”œโ”€โ”€ tests/
โ”‚   โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ”‚   โ””โ”€โ”€ pyproject.toml
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ evaluator/             # Evaluator ์„œ๋น„์Šค
โ”‚   โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ main.py        # FastAPI ์•ฑ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ rules.py       # ๊ทœ์น™ ๊ธฐ๋ฐ˜ ํ‰๊ฐ€
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ llm_judge.py   # LLM-as-a-Judge
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ scheduler.py   # APScheduler
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ notifier.py    # ์•Œ๋ฆผ ์‹œ์Šคํ…œ
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ metrics.py     # Prometheus ๋ฉ”ํŠธ๋ฆญ
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ utils.py       # ์œ ํ‹ธ๋ฆฌํ‹ฐ
โ”‚   โ”‚   โ”œโ”€โ”€ tests/
โ”‚   โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ”‚   โ””โ”€โ”€ pyproject.toml
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ dashboard/             # Streamlit ๋Œ€์‹œ๋ณด๋“œ
โ”‚   โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ main.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ models.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ config.py
โ”‚   โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ”‚   โ””โ”€โ”€ pyproject.toml
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ web/                   # Next.js ์›น ๋Œ€์‹œ๋ณด๋“œ
โ”‚       โ””โ”€โ”€ dashboard/
โ”‚           โ”œโ”€โ”€ app/
โ”‚           โ”œโ”€โ”€ components/
โ”‚           โ”œโ”€โ”€ locales/       # ๋‹ค๊ตญ์–ด ์ง€์›
โ”‚           โ””โ”€โ”€ lib/
โ”‚
โ”œโ”€โ”€ infra/
โ”‚   โ”œโ”€โ”€ docker/
โ”‚   โ”‚   โ””โ”€โ”€ docker-compose.local.yml
โ”‚   โ”œโ”€โ”€ prometheus/
โ”‚   โ”‚   โ””โ”€โ”€ prometheus.yml
โ”‚   โ””โ”€โ”€ grafana/
โ”‚       โ”œโ”€โ”€ provisioning/
โ”‚       โ”œโ”€โ”€ dashboards/
โ”‚       โ””โ”€โ”€ DASHBOARD_GUIDE-ko.md
โ”‚
โ”œโ”€โ”€ configs/
โ”‚   โ””โ”€โ”€ env/
โ”‚       โ”œโ”€โ”€ .env.local.example
โ”‚       โ””โ”€โ”€ .env.local          # gitignored
โ”‚
โ”œโ”€โ”€ docs/
โ”‚   โ”œโ”€โ”€ release_notes/         # ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ
โ”‚   โ”‚   โ”œโ”€โ”€ RELEASE_NOTES_v0.1.0.md
โ”‚   โ”‚   โ”œโ”€โ”€ RELEASE_NOTES_v0.2.0.md
โ”‚   โ”‚   โ”œโ”€โ”€ RELEASE_NOTES_v0.3.0.md
โ”‚   โ”‚   โ”œโ”€โ”€ RELEASE_NOTES_v0.4.0.md
โ”‚   โ”‚   โ””โ”€โ”€ RELEASE_NOTES_v0.5.0.md
โ”‚   โ”œโ”€โ”€ RELEASE_NOTES_v0.5.0_ko.md
โ”‚   โ”œโ”€โ”€ METRICS.md
โ”‚   โ”œโ”€โ”€ EMAIL_SETUP.md
โ”‚   โ””โ”€โ”€ README-main-us.md
โ”‚
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ workflows/
โ”‚       โ””โ”€โ”€ ci.yml             # GitHub Actions CI/CD
โ”‚
โ”œโ”€โ”€ .flake8                    # Flake8 ์„ค์ •
โ””โ”€โ”€ README.md

๐Ÿงช ํ…Œ์ŠคํŠธ

ํ—ฌ์Šค ์ฒดํฌ ํ…Œ์ŠคํŠธ

# ๋ชจ๋“  ์„œ๋น„์Šค ํ—ฌ์Šค ์ฒดํฌ
curl http://localhost:18000/health  # Gateway API
curl http://localhost:18001/health  # Evaluator
curl http://localhost:9090/-/healthy # Prometheus
curl http://localhost:3001/api/health # Grafana

ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

# 1. LLM ์š”์ฒญ ์ „์†ก
curl -X POST "http://localhost:18000/chat" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Test", "user_id": "test"}'

# 2. ํ‰๊ฐ€ ์‹คํ–‰
curl -X POST "http://localhost:18001/evaluate-once?limit=1"

# 3. ๋ฉ”ํŠธ๋ฆญ ํ™•์ธ
curl http://localhost:18000/metrics | grep llm_gateway
curl http://localhost:18001/metrics | grep llm_evaluator

# 4. Grafana ๋Œ€์‹œ๋ณด๋“œ ํ™•์ธ
open http://localhost:3001

์ž๋™ํ™” ํ…Œ์ŠคํŠธ

# CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๋กœ์ปฌ ์‹คํ–‰
cd services/gateway-api
pytest tests/

cd ../evaluator
pytest tests/

# Lint ์ฒดํฌ
flake8 services/

๐Ÿ“ˆ ๋ชจ๋‹ˆํ„ฐ๋ง ๊ฐ€์ด๋“œ

Prometheus ์ฟผ๋ฆฌ ์˜ˆ์‹œ

# HTTP ์š”์ฒญ ๋น„์œจ
sum(rate(llm_gateway_http_requests_total[5m]))

# LLM ์ง€์—ฐ์‹œ๊ฐ„ p95
histogram_quantile(0.95, sum(rate(llm_gateway_llm_request_duration_seconds_bucket[5m])) by (le, model))

# ํ‰๊ฐ€ ์ ์ˆ˜ ์ค‘์•™๊ฐ’
histogram_quantile(0.50, sum(rate(llm_evaluator_evaluation_scores_bucket{score_type="overall"}[5m])) by (le))

# ํ‰๊ฐ€ ๋Œ€๊ธฐ ๋กœ๊ทธ ์ˆ˜
llm_evaluator_pending_logs

Grafana ๋Œ€์‹œ๋ณด๋“œ ์‚ฌ์šฉ

์ž์„ธํ•œ ๊ฐ€์ด๋“œ๋Š” Grafana ๋Œ€์‹œ๋ณด๋“œ ๊ฐ€์ด๋“œ ์ฐธ์กฐ


๐Ÿ“š ๋ฌธ์„œ

๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ

  • v0.5.0 (Latest) - Prometheus, Grafana, ์ด๋ฉ”์ผ ์•Œ๋ฆผ
  • v0.4.0 - ์Šค์ผ€์ค„๋Ÿฌ, Slack/Discord ์•Œ๋ฆผ, CI/CD
  • v0.3.0 - LLM-as-a-Judge, ๋‹ค๊ตญ์–ด ์ง€์›
  • v0.2.0 - Dashboard, CORS, ๊ทœ์น™ ๊ธฐ๋ฐ˜ ํ‰๊ฐ€
  • v0.1.0 - ์ดˆ๊ธฐ ๋ฆด๋ฆฌ์ฆˆ (Gateway + Evaluator)

๊ธฐ์ˆ  ๋ฌธ์„œ


๐Ÿ›ฃ๏ธ ๋กœ๋“œ๋งต

์™„๋ฃŒ๋œ ๊ธฐ๋Šฅ

  • โœ… v0.1.0: Gateway API + Evaluator ๊ธฐ๋ณธ ๊ตฌ์กฐ
  • โœ… v0.2.0: ์›น ๋Œ€์‹œ๋ณด๋“œ + ๊ทœ์น™ ๊ธฐ๋ฐ˜ ํ‰๊ฐ€
  • โœ… v0.3.0: LLM-as-a-Judge + ๋‹ค๊ตญ์–ด ์ง€์›
  • โœ… v0.4.0: ์ž๋™ ์Šค์ผ€์ค„๋Ÿฌ + Slack/Discord ์•Œ๋ฆผ
  • โœ… v0.5.0: Prometheus + Grafana + ์ด๋ฉ”์ผ ์•Œ๋ฆผ

ํ–ฅํ›„ ๊ณ„ํš (v0.6.0+)

  • Alertmanager ํ†ตํ•ฉ: ๊ณ ๊ธ‰ ์•Œ๋ฆผ ๊ทœ์น™ ๋ฐ ๋ผ์šฐํŒ…
  • ๋‹ค์ค‘ LLM ์ œ๊ณต์ž ์ง€์›: Anthropic Claude, Google Gemini ๋“ฑ
  • ๋น„์šฉ ์ถ”์ : ํ† ํฐ ์‚ฌ์šฉ๋Ÿ‰ ๋ฐ ๋น„์šฉ ๋ชจ๋‹ˆํ„ฐ๋ง
  • A/B ํ…Œ์ŠคํŠธ: ํ”„๋กฌํ”„ํŠธ ๋ฐ ๋ชจ๋ธ ๋น„๊ต
  • ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ: RLHF ์Šคํƒ€์ผ ์‚ฌ๋žŒ ํ‰๊ฐ€
  • Kubernetes ๋ฐฐํฌ: Helm ์ฐจํŠธ ๋ฐ ๋ฐฐํฌ ๊ฐ€์ด๋“œ
  • API ์ธ์ฆ: JWT ๊ธฐ๋ฐ˜ ๋ณด์•ˆ
  • Rate Limiting: ์š”์ฒญ ์ œํ•œ ๋ฐ ํ• ๋‹น๋Ÿ‰ ๊ด€๋ฆฌ

๐Ÿ”’ ๋ณด์•ˆ

์ฃผ์˜์‚ฌํ•ญ

  • .env.local ํŒŒ์ผ์„ ์ ˆ๋Œ€ ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ์„ธ์š” (gitignored)
  • OpenAI API ํ‚ค๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•˜์„ธ์š”
  • Slack/Discord ์›นํ›… URL์„ ๊ณต๊ฐœํ•˜์ง€ ๋งˆ์„ธ์š”
  • SMTP ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š” (Gmail)

๊ถŒ์žฅ์‚ฌํ•ญ

  • ํ”„๋กœ๋•์…˜์—์„œ๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‹œํฌ๋ฆฟ ๊ด€๋ฆฌ์ž์— ์ €์žฅ
  • API ์—”๋“œํฌ์ธํŠธ์— ์ธ์ฆ ์ถ”๊ฐ€ (v0.6.0+)
  • HTTPS/TLS ์‚ฌ์šฉ
  • ์ •๊ธฐ์ ์ธ ์˜์กด์„ฑ ์—…๋ฐ์ดํŠธ

๐Ÿค ๊ธฐ์—ฌ

๊ธฐ์—ฌ๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ๋‹ค์Œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ผ์ฃผ์„ธ์š”:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feat/amazing-feature)
  5. Open a Pull Request

๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ๋ผ์ธ

  • Python ์ฝ”๋“œ๋Š” Flake8 ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ ์ค€์ˆ˜
  • ๋ชจ๋“  PR์€ CI ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ํ•„์ˆ˜
  • ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋Š” Conventional Commits ํ˜•์‹ ์‚ฌ์šฉ
  • ์ƒˆ ๊ธฐ๋Šฅ์—๋Š” ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

๐Ÿ“„ ๋ผ์ด์„ ์Šค

์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ‘ฅ ์ œ์ž‘์ž

Dong-hyeon Shin (dongkoony)


๐Ÿ“ž ๋ฌธ์˜ ๋ฐ ์ง€์›


โญ ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ๋„์›€์ด ๋˜์…จ๋‹ค๋ฉด Star๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”!

About

Production-ready MLOps platform for monitoring and evaluating LLM response quality with automated alerts and real-time analytics

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages