LESSON 30分

ストーリー

田中VPoE
サービング基盤が設計できた。次はモニタリングと可観測性だ。「計測できないものは改善できない」— まずはログ収集から始めよう
あなた
今はCloudWatchでエラー率を見ているだけです。何を追加で記録すべきですか?
田中VPoE
LLMのログは従来のアプリケーションログとは根本的に違う。プロンプトの内容、トークン数、コスト、応答品質…すべてを構造化して記録する必要がある。ただしPIIの取り扱いには細心の注意が必要だ

ログ設計の原則

LLMログに記録すべき情報

カテゴリ項目目的
識別情報リクエストID、トレースID、セッションIDリクエストの追跡とデバッグ
コンテキストサービス名、ユーザーID、環境(prod/staging)フィルタリングと分析
入力システムプロンプト、ユーザー入力、RAG取得コンテキスト品質改善、問題再現
出力モデル応答、finish_reason品質評価、ハルシネーション検出
メタデータモデル名、プロバイダ、温度、max_tokensパフォーマンス分析
パフォーマンスレイテンシ、TTFT、入力トークン数、出力トークン数性能監視
コストトークン単価、リクエストあたりコストコスト管理
セキュリティPII検出フラグ、インジェクション検出フラグセキュリティ監査

ログレベルの設計

レベル記録内容適用場面
Minimalメタデータ + パフォーマンス + コスト高トラフィック環境。コスト重視
StandardMinimal + 入出力の要約(先頭100文字)通常運用。品質監視
DetailedStandard + 入出力の全文デバッグ、品質分析。PII注意
DebugDetailed + 中間ステップ(RAG検索結果等)開発・調査時のみ

PII除去パイプライン

PII検出の対象

PII種別検出方法マスキング例
メールアドレス正規表現user@example.com[EMAIL]
電話番号正規表現090-1234-5678[PHONE]
クレジットカード番号正規表現 + Luhnチェック4111-1111-1111-1111[CARD]
マイナンバー正規表現123456789012[MY_NUMBER]
人名NERモデル田中太郎[PERSON]
住所NERモデル東京都渋谷区...[ADDRESS]

マスキングパイプラインの構成

ログ収集パイプライン:

リクエスト/レスポンス


┌──────────────────┐
│ 1. 構造化         │  JSON形式にパース
└────────┬─────────┘


┌──────────────────┐
│ 2. PII検出        │  正規表現 + NER
└────────┬─────────┘


┌──────────────────┐
│ 3. マスキング      │  検出されたPIIを置換
└────────┬─────────┘


┌──────────────────┐
│ 4. コスト計算      │  トークン × 単価
└────────┬─────────┘

         ├──→ Langfuse(モニタリング)
         └──→ S3(長期保存)

構造化ログの設計

トレースとスパン

LLMの呼び出しは複数のステップで構成されることが多く、トレーシングが重要です。

RAGチャットボットのトレース例:

Trace: req-abc123
├── Span: input_validation (5ms)
│   └── PII検出、入力サニタイズ
├── Span: rag_retrieval (150ms)
│   ├── Span: embedding_generation (30ms)
│   ├── Span: vector_search (80ms)
│   └── Span: reranking (40ms)
├── Span: prompt_construction (2ms)
│   └── システムプロンプト + RAG結果 + ユーザー入力
├── Span: llm_call (2800ms)
│   ├── model: gpt-4o
│   ├── input_tokens: 1500
│   ├── output_tokens: 350
│   └── cost: ¥12.5
├── Span: output_validation (10ms)
│   └── PIIフィルタ、有害性チェック
└── Span: response (1ms)
    └── ユーザーへの返却

Total: 2968ms

Langfuseへの送信例

from langfuse import Langfuse

langfuse = Langfuse()

# トレース開始
trace = langfuse.trace(
    name="cs-ai-chat",
    user_id="user-456",
    metadata={
        "service": "cs-ai",
        "environment": "production",
    },
)

# RAG検索スパン
retrieval_span = trace.span(
    name="rag_retrieval",
    input={"query": sanitized_query},
)

# ベクトル検索
results = vector_store.search(query_embedding, top_k=5)

retrieval_span.end(
    output={"num_results": len(results), "top_score": results[0].score},
)

# LLM呼び出しスパン(Generation)
generation = trace.generation(
    name="llm_call",
    model="gpt-4o",
    input=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": sanitized_query},
    ],
    model_parameters={"temperature": 0.3, "max_tokens": 1024},
)

response = openai.chat.completions.create(...)

generation.end(
    output=response.choices[0].message.content,
    usage={
        "input": response.usage.prompt_tokens,
        "output": response.usage.completion_tokens,
    },
)

ログの保存と管理

項目設計
短期保存(ホット)Langfuse(30日)。リアルタイム分析・ダッシュボード用
中期保存(ウォーム)S3 Standard(1年)。品質分析・トレンド分析用
長期保存(コールド)S3 Glacier(3年)。コンプライアンス・監査用
データ削除保持期間経過後に自動削除。GDPR対応の削除リクエスト処理

まとめ

ポイント内容
記録すべき情報識別情報、入出力、メタデータ、パフォーマンス、コスト、セキュリティ
PII除去正規表現 + NER で検出し、ログ保存前にマスキング
トレーシング複数スパンで構成されるトレースとして構造化
保存戦略ホット(Langfuse)→ ウォーム(S3)→ コールド(Glacier)の階層

チェックリスト

  • LLMログに記録すべき8カテゴリの情報を理解した
  • PII検出・マスキングパイプラインの設計を把握した
  • トレースとスパンの概念を説明できる
  • ログの保存戦略(ホット/ウォーム/コールド)を理解した

推定読了時間: 30分