315 lines
20 KiB
Markdown
315 lines
20 KiB
Markdown
# 📊 OpenAI Costs API - Visual Integration Overview
|
|
|
|
## System Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ FRONTEND (React) │
|
|
│ /frontend/src/App.js │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
│ │ 🤖 AI Budget Tab │ │
|
|
│ ├──────────────────────────────────────────────────────────┤ │
|
|
│ │ │ │
|
|
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
|
|
│ │ │ 💰 Aktuelle │ │ 📊 Antal │ │ │
|
|
│ │ │ Omkostninger │ │ Requests │ │ │
|
|
│ │ │ $0.50 │ │ 42 │ │ │
|
|
│ │ └─────────────────┘ └─────────────────┘ │ │
|
|
│ │ │ │
|
|
│ │ ┌──────────────────────────────────────┐ │ │
|
|
│ │ │ 📊 Budget Status [████░░░░░░] 83%│ ⚠️ WARNING │ │
|
|
│ │ │ Budget: $9.00 Brugt: $7.50 │ │ │
|
|
│ │ │ Tilbage: $1.50 Dage tilbage: 6 │ │ │
|
|
│ │ └──────────────────────────────────────┘ │ │
|
|
│ │ │ │
|
|
│ │ ┌──────────────────────────────────────┐ │ │
|
|
│ │ │ 💸 Omkostningsfordeling fra API │ │ │
|
|
│ │ │ Language models: $0.35 │ │ │
|
|
│ │ │ Image models: $0.15 │ │ │
|
|
│ │ │ (fra OpenAI API hvis admin key sat) │ │ │
|
|
│ │ └──────────────────────────────────────┘ │ │
|
|
│ │ │ │
|
|
│ └──────────────────────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌─────────────────┼─────────────────┐ │
|
|
│ │ │ │ │
|
|
│ Call │ Call │ Call │ │
|
|
│ │ │ │ │
|
|
│ ▼ ▼ ▼ │
|
|
│ /stats /costs /budget/status │
|
|
│ (DB + API) (OpenAI API) (OpenAI API) │
|
|
└──────────┬──────────┬─────────────┬──────────┬─────────────────┘
|
|
│ │ │ │
|
|
│ HTTP GET │ │ │ HTTP GET
|
|
│ │ │ │
|
|
┌──────────▼──────────▼─────────────▼──────────▼─────────────────┐
|
|
│ BACKEND (Node.js/Express) │
|
|
│ /backend/src/routes/quotes.js │
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Route: GET /api/quotes/openai/stats │ │
|
|
│ │ └─ Service: openaiService.getTokenUsageStats() │ │
|
|
│ │ └─ Source: Database (openai_usage_stats table) │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Route: GET /api/quotes/openai/costs │ │
|
|
│ │ └─ Service: openaiService.fetchOpenAICosts() │ │
|
|
│ │ ├─ Call: https://api.openai.com/v1/organization/ │ │
|
|
│ │ │ costs?start_time=XXX&end_time=XXX │ │
|
|
│ │ └─ Auth: Bearer OPENAI_ADMIN_KEY (from .env) │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Route: GET /api/quotes/openai/costs/breakdown │ │
|
|
│ │ └─ Service: openaiService.getDetailedCostBreakdown() │ │
|
|
│ │ ├─ Call: https://api.openai.com/v1/organization/ │ │
|
|
│ │ │ costs?group_by=line_item&group_by=... │ │
|
|
│ │ ├─ Support: Pagination with cursor │ │
|
|
│ │ └─ Cache: 5 minutes to reduce API calls │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Route: GET /api/quotes/openai/budget/status │ │
|
|
│ │ └─ Service: Combines stats + costs data │ │
|
|
│ │ ├─ Calculates: % usage, days remaining, rates │ │
|
|
│ │ └─ Returns: Budget status with warning level │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
└──────────────┬───────────────────────────┬──────────────────────┘
|
|
│ │
|
|
│ Database Queries │ OpenAI API Calls
|
|
│ │
|
|
▼ ▼
|
|
┌────────────┐ ┌──────────────────────┐
|
|
│ MariaDB │ │ OpenAI API │
|
|
│ │ │ /v1/organization/ │
|
|
│ openai_ │ │ costs │
|
|
│ usage_stats│ │ │
|
|
│ table │ │ Admin API Access │
|
|
└────────────┘ │ (Costs Tracking) │
|
|
└──────────────────────┘
|
|
```
|
|
|
|
## Data Flow Diagram
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
│ User clicks "🤖 AI Budget" in frontend │
|
|
└────────────────────────┬─────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────┐
|
|
│ loadOpenaiUsage() triggered │
|
|
│ - Parallel Promise.all() │
|
|
└───┬──────────┬──────────┬───────┘
|
|
│ │ │
|
|
┌─────▼──┐ ┌───▼──┐ ┌───▼─────┐
|
|
│ /stats │ │/costs│ │/budget/│
|
|
│ │ │ │ │ status │
|
|
└─────┬──┘ └───┬──┘ └───┬─────┘
|
|
│ │ │
|
|
└─────────┼─────────┘
|
|
│
|
|
┌─────────▼──────────┐
|
|
│ Wait for all 3 │
|
|
│ responses │
|
|
└─────────┬──────────┘
|
|
│
|
|
┌─────────────┼──────────────┐
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌───────┐ ┌────────┐ ┌──────────────┐
|
|
│setOpen │ │setOpen │ │setBudgetStatus
|
|
│aiUsage│ │aiCosts │ │ │
|
|
│ (DB) │ │(API) │ │(API) │
|
|
└───┬───┘ └────┬───┘ └──────┬──────┘
|
|
│ │ │
|
|
└───────────┼─────────────┘
|
|
│
|
|
┌──────────▼──────────┐
|
|
│ Re-render React │
|
|
│ components with new │
|
|
│ state │
|
|
└──────────┬──────────┘
|
|
│
|
|
┌───────────┴──────────┐
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────┐ ┌──────────────────┐
|
|
│ Token Stats │ │ Budget Status & │
|
|
│ from DB: │ │ Cost Breakdown │
|
|
│ │ │ from OpenAI API: │
|
|
│ - Total: 150k │ │ │
|
|
│ - Cost: $7.50 │ │ - Budget: $9.00 │
|
|
│ - Requests: 42│ │ - Used: $7.50 │
|
|
│ │ │ - Status: ⚠️ │
|
|
└─────────────┘ │ - Line items breakdown
|
|
│ - Project breakdown
|
|
└──────────────────┘
|
|
```
|
|
|
|
## Warning Level Colors
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ Budget Usage Alert System │
|
|
├────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 0% ─────────────────────────────────────────────────── 100% │
|
|
│ ▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
|
|
│ 🟢 OK 🟡 NOTICE 🟠 WARNING 🔴 CRITICAL │
|
|
│ 0-60% 60-80% 80-95% 95-100% │
|
|
│ │
|
|
│ ├─────────┤ ├─────────────┤ ├──────────┤ ├────────┤ │
|
|
│ │
|
|
│ Message: "Budget i orden" / "Monitor" / "Overvej udvidelse" │
|
|
│ / "Forbered budgetudvidelse" │
|
|
└────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## API Response Time
|
|
|
|
```
|
|
Timeline for loadOpenaiUsage():
|
|
|
|
Request sent (t=0)
|
|
│
|
|
├─► GET /api/quotes/openai/stats (fast, ~50ms from DB)
|
|
│
|
|
├─► GET /api/quotes/openai/costs (medium, ~200ms OpenAI API)
|
|
│
|
|
└─► GET /api/quotes/openai/budget/status (medium, ~200ms combined)
|
|
|
|
All 3 run in parallel (Promise.all)
|
|
│
|
|
▼
|
|
Total time: ~200-300ms (limited by slowest = OpenAI API)
|
|
|
|
React state updated
|
|
│
|
|
▼
|
|
UI re-renders with all data
|
|
│
|
|
▼
|
|
User sees complete budget dashboard
|
|
```
|
|
|
|
## Configuration Hierarchy
|
|
|
|
```
|
|
┌─────────────────────────────────────────┐
|
|
│ Environment Variables (.env) │
|
|
├─────────────────────────────────────────┤
|
|
│ OPENAI_API_KEY=sk-proj-xxxxx │
|
|
│ ├─ For: Quote generation (GPT-4) │
|
|
│ └─ Used in: generateQuote(), refineQuote
|
|
│ │
|
|
│ OPENAI_ADMIN_KEY=sk-org-xxxxx (NEW) │
|
|
│ ├─ For: Cost tracking (Costs API) │
|
|
│ └─ Used in: fetchOpenAICosts() │
|
|
└─────────────────────────────────────────┘
|
|
|
|
┌─────────────────────────────────────────┐
|
|
│ Service Configuration │
|
|
│ (openaiService.js) │
|
|
├─────────────────────────────────────────┤
|
|
│ monthlyBudget: $9.00 │
|
|
│ monthlyLimit: 160,000 tokens │
|
|
│ cacheTimeout: 5 minutes │
|
|
│ requestTimeout: 30 seconds │
|
|
└─────────────────────────────────────────┘
|
|
```
|
|
|
|
## Error Handling Flow
|
|
|
|
```
|
|
Request to OpenAI Costs API
|
|
│
|
|
├─ Success (200)
|
|
│ │
|
|
│ ▼
|
|
│ Parse response
|
|
│ │
|
|
│ ├─ Valid JSON
|
|
│ │ │
|
|
│ │ ▼
|
|
│ │ Save to state
|
|
│ │ │
|
|
│ │ ▼
|
|
│ │ Display in UI ✓
|
|
│ │
|
|
│ └─ Invalid JSON
|
|
│ │
|
|
│ ▼
|
|
│ Log error
|
|
│ │
|
|
│ ▼
|
|
│ Fallback to DB stats
|
|
│
|
|
└─ Error (401, 503, timeout, etc.)
|
|
│
|
|
▼
|
|
Log error
|
|
│
|
|
├─ 401 Unauthorized
|
|
│ └─ "OPENAI_ADMIN_KEY not valid"
|
|
│
|
|
├─ 503 Service Unavailable
|
|
│ └─ "OpenAI API unavailable"
|
|
│
|
|
└─ Timeout
|
|
└─ "Request timeout"
|
|
│
|
|
▼
|
|
Return success: false
|
|
│
|
|
▼
|
|
Frontend shows "OpenAI Costs API utilgængelig"
|
|
│
|
|
▼
|
|
Fallback to token stats from DB only
|
|
```
|
|
|
|
## Token Usage vs Cost Tracking
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ TWO SOURCES OF TRUTH │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 1. DATABASE (openai_usage_stats) │
|
|
│ ├─ Source: Logged when API call is made │
|
|
│ ├─ Accuracy: 100% for tracked requests │
|
|
│ ├─ Latency: Stored in DB │
|
|
│ ├─ What tracked: token counts, request types │
|
|
│ └─ Availability: Always works │
|
|
│ │
|
|
│ 2. OPENAI API (Costs endpoint) │
|
|
│ ├─ Source: Official OpenAI billing data │
|
|
│ ├─ Accuracy: Official ground truth │
|
|
│ ├─ Latency: From OpenAI's systems (delayed ~24h) │
|
|
│ ├─ What tracked: Actual dollar costs │
|
|
│ └─ Availability: Requires OPENAI_ADMIN_KEY │
|
|
│ │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ RECONCILIATION: │
|
|
│ - Database gives real-time token count │
|
|
│ - OpenAI API gives actual billing cost │
|
|
│ - Together: Complete picture of usage + cost │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
This comprehensive integration allows you to:
|
|
|
|
✅ **Monitor costs in real-time** from OpenAI's official data
|
|
✅ **Track token usage** in your own database
|
|
✅ **Set budget alerts** based on actual spending
|
|
✅ **Analyze cost breakdown** by line items and projects
|
|
✅ **Plan budget** with accurate daily/weekly/monthly trends
|
|
✅ **Optimize model selection** based on cost data
|
|
|