AI Agent を本番環境に展開する際、最大の問題の一つが複数のLLM API を一元管理することです。私のチームでは以前、GPT-4.1・Claude Sonnet 4.5・Gemini 2.5 Flash・DeepSeek V3.2 を個別に管理していましたが、認証情報の散在、レート制限の競合、ログ管理の困難さ、成本可視性の欠如という4つの壁にぶつかりました。本稿では、HolySheep AI の統一APIゲートウェイを活用し、これらの課題を一気に解決したアーキテクチャ設計と実装コードを詳解します。
なぜ統一APIゲートウェイが必要か
AI Agent の本番運用において、API ゲートウェイは以下の4つの層で критическую роль を果たします。
- 認証・認可層:APIキーの集中管理と Rotational Security
- レート制限層:provider ごとの TPM/RPM クォータ管理
- ログ・モニタリング層:リクエスト/レスポンスの追跡とコスト分析
- コスト予算管理層:日次/月次の支出上限とアラート
HolySheep はこれら4層を1つのエンドポイント(https://api.holysheep.ai/v1)で提供し、最大85%のコスト削減(¥1=$1 vs 公式¥7.3=$1)を実現します。
アーキテクチャ設計
システム構成図
┌─────────────────────────────────────────────────────────────┐
│ AI Agent Application │
│ (LangChain / LlamaIndex / 自作オーケストレーター) │
└─────────────────────────┬───────────────────────────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────────┐
│ HolySheep API Gateway │
│ https://api.holysheep.ai/v1 │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Auth Layer│ │Rate Limit│ │ Logging │ │ Budget │ │
│ │ │ │ Layer │ │ Layer │ │ Layer │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└───────┼─────────────┼─────────────┼─────────────┼─────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ GPT-4.1 │ │ Claude │ │ Gemini │ │ DeepSeek
│ $8/MTok │ │ 4.5 $15/MTok│ │2.5 $2.50/MTok│ │ V3.2 $0.42
└──────────────┘ └──────────────┘ └──────────────┘ └──────────
コスト比較表
| モデル | 公式価格 ($/MTok出力) | HolySheep ($/MTok出力) | 節約率 | 推奨ユースケース |
|---|---|---|---|---|
| GPT-4.1 | $60.00 | $8.00 | 87% OFF | 複雑な推論・コード生成 |
| Claude Sonnet 4.5 | $75.00 | $15.00 | 80% OFF | 長文生成・分析タスク |
| Gemini 2.5 Flash | $10.00 | $2.50 | 75% OFF | 高速応答・了大量処理 |
| DeepSeek V3.2 | $2.80 | $0.42 | 85% OFF | コスト重視の通常処理 |
実装コード:統一認証とモデル選択
まず、HolySheep API への接続を確立する基本クライアントを実装します。HolySheep は OpenAI 互換の API 構造を採用しているため、既存の LangChain や LlamaIndex との統合が容易です。
"""
HolySheep AI - 統一APIゲートウェイクライアント
Production-ready AI Agent 用基盤クラス
"""
import os
from typing import Optional, Dict, Any, List
from dataclasses import dataclass
from datetime import datetime
import hashlib
import hmac
import json
import httpx
@dataclass
class ModelConfig:
"""モデル別の設定"""
name: str
provider: str # openai, anthropic, google, deepseek
max_tokens: int
temperature: float
cost_per_1k_output: float # USD
class HolySheepGateway:
"""
HolySheep API Gateway クライアント
特徴:
- 統一エンドポイント(api.holysheep.ai/v1)
- 自動モデルルーティング
- コスト追跡機能
- 予算アラート対応
"""
BASE_URL = "https://api.holysheep.ai/v1"
# 対応モデル定義
MODELS = {
"gpt-4.1": ModelConfig(
name="gpt-4.1",
provider="openai",
max_tokens=128000,
temperature=0.7,
cost_per_1k_output=0.008 # $8/MTok
),
"claude-sonnet-4.5": ModelConfig(
name="claude-sonnet-4.5",
provider="anthropic",
max_tokens=200000,
temperature=0.7,
cost_per_1k_output=0.015 # $15/MTok
),
"gemini-2.5-flash": ModelConfig(
name="gemini-2.5-flash",
provider="google",
max_tokens=128000,
temperature=0.7,
cost_per_1k_output=0.0025 # $2.50/MTok
),
"deepseek-v3.2": ModelConfig(
name="deepseek-v3.2",
provider="deepseek",
max_tokens=128000,
temperature=0.7,
cost_per_1k_output=0.00042 # $0.42/MTok
),
}
def __init__(self, api_key: str):
"""
初期化
Args:
api_key: HolySheep APIキー
"""
self.api_key = api_key
self.client = httpx.Client(
base_url=self.BASE_URL,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
timeout=60.0
)
# コスト追跡
self.total_spent = 0.0
self.request_count = 0
def chat_completion(
self,
model: str,
messages: List[Dict[str, str]],
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
**kwargs
) -> Dict[str, Any]:
"""
チャット補完リクエスト
Args:
model: モデル名(gpt-4.1, claude-sonnet-4.5, etc.)
messages: メッセージリスト
temperature: 生成温度
max_tokens: 最大トークン数
**kwargs: 追加パラメータ
Returns:
APIレスポンス(OpenAI互換形式)
"""
if model not in self.MODELS:
raise ValueError(f"Unknown model: {model}")
config = self.MODELS[model]
payload = {
"model": model,
"messages": messages,
"temperature": temperature or config.temperature,
"max_tokens": max_tokens or config.max_tokens,
**kwargs
}
response = self.client.post("/chat/completions", json=payload)
response.raise_for_status()
result = response.json()
# コスト計算
usage = result.get("usage", {})
output_tokens = usage.get("completion_tokens", 0)
cost = (output_tokens / 1000) * config.cost_per_1k_output
self.total_spent += cost
self.request_count += 1
return result
def get_cost_report(self) -> Dict[str, Any]:
"""コストレポート取得"""
return {
"total_spent_usd": round(self.total_spent, 4),
"total_requests": self.request_count,
"avg_cost_per_request": round(
self.total_spent / self.request_count, 6
) if self.request_count > 0 else 0,
"timestamp": datetime.now().isoformat()
}
def close(self):
"""クライアント終了"""
self.client.close()
===== 使用例 =====
if __name__ == "__main__":
# 初期化(YOUR_HOLYSHEEP_API_KEY を実際のキーに置換)
gateway = HolySheepGateway(api_key="YOUR_HOLYSHEEP_API_KEY")
# DeepSeek V3.2 での低コスト処理
response = gateway.chat_completion(
model="deepseek-v3.2",
messages=[
{"role": "system", "content": "あなたは有用なアシスタントです。"},
{"role": "user", "content": "こんにちは!"}
],
temperature=0.7
)
print(f"Response: {response['choices'][0]['message']['content']}")
print(f"Cost Report: {gateway.get_cost_report()}")
gateway.close()
実装コード:レート制限とコスト予算管理
本番環境では、レート制限とコスト予算の厳格な管理が不可欠です。以下のクラスは、TPM(Tokens Per Minute)ベースのスロットリングと、日次/月次のコスト上限を管理します。
"""
HolySheep AI - レート制限・コスト予算管理モジュール
Production AI Agent 向け:高精度トラフィック制御
"""
import asyncio
import time
from typing import Dict, Optional, Callable, Any
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from collections import deque
from enum import Enum
import threading
import logging
logger = logging.getLogger(__name__)
class BudgetAlertLevel(Enum):
"""予算アラートレベル"""
SAFE = "safe"
WARNING = "warning" # 80%到達
CRITICAL = "critical" # 95%到達
EXCEEDED = "exceeded"
@dataclass
class RateLimitConfig:
"""レート制限設定"""
tpm_limit: int # Tokens Per Minute
rpm_limit: int # Requests Per Minute
rph_limit: int # Requests Per Hour
@classmethod
def from_model(cls, model: str) -> "RateLimitConfig":
"""モデル別のデフォルト制限"""
limits = {
"gpt-4.1": cls(tpm_limit=150000, rpm_limit=500, rph_limit=10000),
"claude-sonnet-4.5": cls(tpm_limit=200000, rpm_limit=400, rph_limit=8000),
"gemini-2.5-flash": cls(tpm_limit=1000000, rpm_limit=1500, rph_limit=50000),
"deepseek-v3.2": cls(tpm_limit=500000, rpm_limit=2000, rph_limit=100000),
}
return limits.get(model, cls(tpm_limit=100000, rpm_limit=1000, rph_limit=50000))
@dataclass
class BudgetConfig:
"""コスト予算設定"""
daily_limit_usd: float
monthly_limit_usd: float
alert_threshold: float = 0.8 # 80%で警告
def get_alert_level(self, spent: float) -> BudgetAlertLevel:
ratio = spent / self.daily_limit_usd
if ratio >= 1.0:
return BudgetAlertLevel.EXCEEDED
elif ratio >= 0.95:
return BudgetAlertLevel.CRITICAL
elif ratio >= 0.8:
return BudgetAlertLevel.WARNING
return BudgetAlertLevel.SAFE
class TokenBucket:
"""トークンバケット方式のレギュレーター"""
def __init__(self, rate: int, capacity: int):
self.rate = rate # 秒間補充量
self.capacity = capacity
self.tokens = capacity
self.last_update = time.time()
self._lock = threading.Lock()
def consume(self, tokens: int, blocking: bool = True) -> bool:
"""
トークン消費
Args:
tokens: 消費するトークン数
blocking: True=利用可能まで待機
Returns:
True=成功, False=制限超過
"""
while True:
with self._lock:
now = time.time()
elapsed = now - self.last_update
self.tokens = min(
self.capacity,
self.tokens + elapsed * self.rate
)
self.last_update = now
if self.tokens >= tokens:
self.tokens -= tokens
return True
if not blocking:
return False
wait_time = (tokens - self.tokens) / self.rate
time.sleep(min(wait_time, 1.0))
class CostBudgetManager:
"""コスト予算管理クラス"""
def __init__(self, config: BudgetConfig):
self.config = config
self.daily_spent = 0.0
self.monthly_spent = 0.0
self.last_reset = datetime.now()
self._lock = threading.Lock()
# コールバック
self._alert_callbacks: list[Callable] = []
def add_alert_callback(self, callback: Callable[[BudgetAlertLevel, float], None]):
"""アラートコールバック登録"""
self._alert_callbacks.append(callback)
def record_cost(self, amount_usd: float) -> BudgetAlertLevel:
"""コスト記録とアラート判定"""
with self._lock:
self.daily_spent += amount_usd
self.monthly_spent += amount_usd
# 日次リセット
if (datetime.now() - self.last_reset).days >= 1:
self.daily_spent = 0.0
self.last_reset = datetime.now()
level = self.config.get_alert_level(self.daily_spent)
if level != BudgetAlertLevel.SAFE:
for callback in self._alert_callbacks:
try:
callback(level, self.daily_spent)
except Exception as e:
logger.error(f"Alert callback error: {e}")
return level
def check_budget(self) -> bool:
"""予算残余チェック"""
with self._lock:
return self.daily_spent < self.config.daily_limit_usd
class HolySheepRateLimitedClient:
"""
レート制限・予算管理付きHolySheepクライアント
特徴:
- モデル別のTPM/RPM制限
- トークンバケット方式の流量制御
- 日次/月次コスト予算管理
- アラートコールバック対応
"""
def __init__(
self,
api_key: str,
rate_limits: Optional[Dict[str, RateLimitConfig]] = None,
budget_config: Optional[BudgetConfig] = None
):
from .gateway import HolySheepGateway
self.gateway = HolySheepGateway(api_key)
self.rate_limits = rate_limits or {
model: RateLimitConfig.from_model(model)
for model in ["gpt-4.1", "claude-sonnet-4.5", "gemini-2.5-flash", "deepseek-v3.2"]
}
self.budget_manager = CostBudgetManager(
budget_config or BudgetConfig(
daily_limit_usd=100.0,
monthly_limit_usd=2000.0
)
)
# トークンバケット(モデル別)
self.token_buckets: Dict[str, TokenBucket] = {}
for model, config in self.rate_limits.items():
self.token_buckets[model] = TokenBucket(
rate=config.tpm_limit // 60, # 秒間レート
capacity=config.tpm_limit // 2 # バケット容量
)
# リクエスト履歴(rpm/rph計算用)
self.request_history: Dict[str, deque] = {
model: deque(maxlen=1000) for model in self.rate_limits.keys()
}
def _check_request_limit(self, model: str) -> bool:
"""リクエスト数制限チェック"""
now = time.time()
history = self.request_history[model]
# 1分以内のリクエスト数を計算
cutoff_1m = now - 60
rpm = sum(1 for ts in history if ts > cutoff_1m)
# 1時間以内のリクエスト数を計算
cutoff_1h = now - 3600
rph = sum(1 for ts in history for _ in [ts] if ts > cutoff_1h)
config = self.rate_limits[model]
return rpm < config.rpm_limit and rph < config.rph_limit
def chat_completion(
self,
model: str,
messages: list,
estimated_tokens: int = 1000,
**kwargs
) -> dict:
"""
レート制限・予算管理付きチャット補完
Args:
model: モデル名
messages: メッセージリスト
estimated_tokens: 推定出力トークン数
**kwargs: 追加パラメータ
"""
# 1. 予算チェック
if not self.budget_manager.check_budget():
raise RuntimeError(
f"Daily budget exceeded: "
f"${self.budget_manager.daily_spent:.2f} / "
f"${self.budget_manager.config.daily_limit_usd:.2f}"
)
# 2. レート制限チェック(トークンバケット)
bucket = self.token_buckets.get(model)
if bucket and not bucket.consume(estimated_tokens, blocking=True):
raise RuntimeError(f"Token rate limit exceeded for {model}")
# 3. リクエスト数制限チェック
if not self._check_request_limit(model):
raise RuntimeError(f"Request rate limit exceeded for {model}")
# 4. API呼び出し
response = self.gateway.chat_completion(model, messages, **kwargs)
# 5. コスト記録
usage = response.get("usage", {})
output_tokens = usage.get("completion_tokens", 0)
cost = (output_tokens / 1000) * self.gateway.MODELS[model].cost_per_1k_output
alert_level = self.budget_manager.record_cost(cost)
# 6. リクエスト履歴更新
self.request_history[model].append(time.time())
# 7. レスポンスにメタ情報付与
response["_meta"] = {
"cost_usd": cost,
"total_daily_spent": self.budget_manager.daily_spent,
"budget_alert_level": alert_level.value,
"latency_ms": response.get("latency_ms", 0)
}
return response
def get_status(self) -> Dict[str, Any]:
"""システムステータス取得"""
return {
"budget": {
"daily_spent": self.budget_manager.daily_spent,
"daily_limit": self.budget_manager.config.daily_limit_usd,
"monthly_spent": self.budget_manager.monthly_spent,
"monthly_limit": self.budget_manager.config.monthly_limit_usd,
},
"rate_limits": {
model: {
"tpm_limit": config.tpm_limit,
"rpm_limit": config.rpm_limit,
"current_bucket_tokens": bucket.tokens
}
for model, (config, bucket) in enumerate(
zip(self.rate_limits.values(), self.token_buckets.values())
)
}
}
===== 使用例 =====
if __name__ == "__main__":
# Slack通知コールバック例
def slack_alert(level: BudgetAlertLevel, spent: float):
print(f"[ALERT] {level.value.upper()}: ${spent:.2f} spent")
# 本番環境では slack_sdk.WebhookClient 等を使用
# クライアント初期化
client = HolySheepRateLimitedClient(
api_key="YOUR_HOLYSHEEP_API_KEY",
budget_config=BudgetConfig(
daily_limit_usd=50.0, # 日次$50
monthly_limit_usd=1000.0 # 月次$1000
)
)
client.budget_manager.add_alert_callback(slack_alert)
# 低コストモデルで処理
response = client.chat_completion(
model="deepseek-v3.2", # $0.42/MTok
messages=[
{"role": "user", "content": "簡単な質問への回答を50文字以内で"}
],
estimated_tokens=100
)
print(f"Response: {response['choices'][0]['message']['content']}")
print(f"Cost: ${response['_meta']['cost_usd']:.4f}")
print(f"Status: {client.get_status()}")
実装コード:分散AI Agent向けのログ収集システム
複数のAI Agentが協調動作する本番環境では、统一的なログ収集が運用監視の鍵となります。以下のロガーは、リクエスト・レスポンス・コスト・レイテンシを包括的に記録します。
"""
HolySheep AI - 分散AI Agent向けログ収集システム
本番環境の包括的なモニタリング
"""
import json
import logging
import sqlite3
from datetime import datetime, timedelta
from typing import Optional, Dict, Any, List
from pathlib import Path
from dataclasses import dataclass, asdict
from contextlib import contextmanager
import threading
from queue import Queue, Empty
import atexit
@dataclass
class RequestLog:
"""リクエストログ"""
request_id: str
timestamp: str
model: str
provider: str
messages_hash: str # メッセージのハッシュ(機密情報保護)
messages_tokens: int
response_tokens: int
total_tokens: int
cost_usd: float
latency_ms: float
status: str # success, error, rate_limited, budget_exceeded
error_message: Optional[str] = None
metadata: Optional[Dict[str, Any]] = None
class SQLiteLogStore:
"""SQLite永続化ログストア"""
def __init__(self, db_path: str = "holy_sheep_logs.db"):
self.db_path = db_path
self._init_db()
def _init_db(self):
"""データベース初期化"""
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS request_logs (
request_id TEXT PRIMARY KEY,
timestamp TEXT NOT NULL,
model TEXT NOT NULL,
provider TEXT NOT NULL,
messages_hash TEXT NOT NULL,
messages_tokens INTEGER,
response_tokens INTEGER,
total_tokens INTEGER,
cost_usd REAL,
latency_ms REAL,
status TEXT NOT NULL,
error_message TEXT,
metadata TEXT
)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_timestamp
ON request_logs(timestamp)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_model
ON request_logs(model)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_status
ON request_logs(status)
""")
def insert(self, log: RequestLog):
"""ログ挿入"""
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
INSERT OR REPLACE INTO request_logs
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
log.request_id,
log.timestamp,
log.model,
log.provider,
log.messages_hash,
log.messages_tokens,
log.response_tokens,
log.total_tokens,
log.cost_usd,
log.latency_ms,
log.status,
log.error_message,
json.dumps(log.metadata) if log.metadata else None
))
def query(
self,
start_time: Optional[str] = None,
end_time: Optional[str] = None,
model: Optional[str] = None,
status: Optional[str] = None,
limit: int = 100
) -> List[RequestLog]:
"""クエリ"""
query = "SELECT * FROM request_logs WHERE 1=1"
params = []
if start_time:
query += " AND timestamp >= ?"
params.append(start_time)
if end_time:
query += " AND timestamp <= ?"
params.append(end_time)
if model:
query += " AND model = ?"
params.append(model)
if status:
query += " AND status = ?"
params.append(status)
query += f" ORDER BY timestamp DESC LIMIT {limit}"
with sqlite3.connect(self.db_path) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.execute(query, params)
return [RequestLog(**dict(row)) for row in cursor.fetchall()]
def get_cost_summary(
self,
start_date: Optional[str] = None,
end_date: Optional[str] = None
) -> Dict[str, Any]:
"""コストサマリー取得"""
query = """
SELECT
COUNT(*) as total_requests,
SUM(cost_usd) as total_cost,
AVG(cost_usd) as avg_cost,
AVG(latency_ms) as avg_latency,
model,
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN status != 'success' THEN 1 ELSE 0 END) as error_count
FROM request_logs
"""
where_clauses = []
params = []
if start_date:
where_clauses.append("timestamp >= ?")
params.append(start_date)
if end_date:
where_clauses.append("timestamp <= ?")
params.append(end_date)
if where_clauses:
query += " WHERE " + " AND ".join(where_clauses)
query += " GROUP BY model"
with sqlite3.connect(self.db_path) as conn:
cursor = conn.execute(query, params)
return {"breakdown": [dict(row) for row in cursor.fetchall()]}
class AsyncLogWriter:
"""非同期ログライター(バックグラウンドflush)"""
def __init__(self, store: SQLiteLogStore, batch_size: int = 100, flush_interval: float = 5.0):
self.store = store
self.batch_size = batch_size
self.flush_interval = flush_interval
self.queue: Queue = Queue()
self.buffer: List[RequestLog] = []
self._running = True
self._lock = threading.Lock()
self._flush_thread = threading.Thread(target=self._flush_loop, daemon=True)
self._flush_thread.start()
atexit.register(self.flush)
def log(self, request_log: RequestLog):
"""ログ追加"""
self.queue.put(request_log)
def _flush_loop(self):
"""バックグラウンドflushループ"""
while self._running:
try:
# キューからバッファへ
while len(self.buffer) < self.batch_size:
try:
log = self.queue.get(timeout=0.1)
self.buffer.append(log)
except Empty:
break
# バッファflush
if self.buffer:
self.flush()
except Exception as e:
logging.error(f"Flush error: {e}")
def flush(self):
"""バッファをDBにflush"""
with self._lock:
if not self.buffer:
return
for log in self.buffer:
self.store.insert(log)
self.buffer.clear()
class HolySheepLogger:
"""
包括的ログ収集システム
特徴:
- SQLite永続化(ローカル)または外部ログシステム対応
- 非同期write(高負荷環境対応)
- コスト・レイテンシ追跡
- 異常検知対応
"""
def __init__(
self,
db_path: str = "holy_sheep_logs.db",
log_level: int = logging.INFO
):
self.logger = logging.getLogger("HolySheepLogger")
self.logger.setLevel(log_level)
# コンソールハンドラー
if not self.logger.handlers:
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s"
))
self.logger.addHandler(handler)
# ログストア
self.store = SQLiteLogStore(db_path)
self.writer = AsyncLogWriter(self.store)
# リクエスト追跡
self._request_counter = 0
self._lock = threading.Lock()
def _generate_request_id(self) -> str:
"""リクエストID生成"""
with self._lock:
self._request_counter += 1
return f"req_{datetime.now().strftime('%Y%m%d%H%M%S')}_{self._request_counter:06d}"
@contextmanager
def log_request(
self,
model: str,
provider: str,
messages: List[Dict],
metadata: Optional[Dict] = None
):
"""
リクエストログコンテキスト
Usage:
with logger.log_request("deepseek-v3.2", "deepseek", messages) as ctx:
response = api.call(...)
ctx.success(response, latency_ms=150)
"""
request_id = self._generate_request_id()
start_time = datetime.now()
class RequestContext:
def __init__(ctx_self):
ctx_self.cost = 0.0
ctx_self.latency_ms = 0
ctx_self.status = "pending"
ctx_self.error_message = None
def success(ctx_self, response: Dict, latency_ms: float):
usage = response.get("usage", {})
ctx_self.cost = (usage.get("completion_tokens", 0) / 1000) * (
{"deepseek": 0.00042, "openai": 0.008, "anthropic": 0.015, "google": 0.0025}.get(provider, 0.001)
)
ctx_self.latency_ms = latency_ms
ctx_self.status = "success"
def error(ctx_self, message: str, latency_ms: float):
ctx_self.status = "error"
ctx_self.error_message = message
ctx_self.latency_ms = latency_ms
def rate_limited(ctx_self, latency_ms: float):
ctx_self.status = "rate_limited"
ctx_self.latency_ms = latency_ms
def budget_exceeded(ctx_self, latency_ms: float):
ctx_self.status = "budget_exceeded"
ctx_self.latency_ms = latency_ms
ctx = RequestContext()
try:
yield ctx
except Exception as e:
ctx.error(str(e), (datetime.now() - start_time).total_seconds() * 1000)
raise
finally:
# ログ書き込み
import hashlib
messages_hash = hashlib.sha256(
json.dumps(messages, ensure_ascii=False).encode()
).hexdigest()[:16]
log = RequestLog(
request_id=request_id,
timestamp=start_time.isoformat(),
model=model,
provider=provider,
messages_hash=messages_hash,
messages_tokens=metadata.get("input_tokens", 0) if metadata else 0,
response_tokens=metadata.get("output_tokens", 0) if metadata else 0,
total_tokens=(
(metadata.get("input_tokens", 0) + metadata.get("output_tokens", 0))
if metadata else 0
),
cost_usd=ctx.cost,
latency_ms=ctx.latency_ms,
status=ctx.status,
error_message=ctx.error_message,
metadata=metadata
)
self.writer.log(log)
self.logger.info(
f"[{request_id}] {model} | "
f"cost=${ctx.cost:.4f} | "
f"latency={ctx.latency_ms:.0f}ms | "
f"status={ctx.status}"
)
===== 使用例 =====
if __name__ == "__main__":
# ロガー初期化
logger = HolySheepLogger(log_level=logging.DEBUG)
# リクエストログ
messages = [
{"role": "user", "content": "テストメッセージ"}
]
with logger.log_request(
model="deepseek-v3.2",
provider="deepseek",
messages=messages,
metadata={"agent_id": "agent-001"}
) as ctx:
# API呼び出し(疑似)
import time
time.sleep(0.1)
response = {
"usage": {
"completion_tokens": 150,
"prompt_tokens": 50
}
}
ctx.success(response, latency_ms=95)
# コストサマリー取得
summary = logger.store.get_cost_summary(
start_date=(datetime.now() - timedelta(days=1)).isoformat()
)
print(f"Cost Summary: {summary}")
向いている人・向いていない人
| 向いている人 | 向いていない人 |
|---|---|
|