Chuyển đến nội dung chính

レッスン 2: プラットフォーム アーキテクチャの概要 — マイクロサービス、イベント駆動型、DDD

高レベルのシステム アーキテクチャ、限定されたコンテキスト (会話、ナレッジ、エージェント、チャネル、分析、請求)、イベント駆動型アーキテクチャ、テクノロジー スタックの選択、C4 図、展開トポロジ。

🏗️ アーキテクチャ — レッスン 2 レッスン 2: プラットフォーム アーキテクチャの概要 — マイクロサービス、イベント駆動型、DDD

エンタープライズ AI チャットボット プラットフォームのアーキテクチャ — プロトタイプから本番まで

パート 1: 基盤とプラットフォームの概要

xdev.asia

1. 建築哲学

エンタープライズAIチャットボットプラットフォームは、単に「OpenAI APIを呼び出して応答を返す」だけではありません。それは一つです 分散システム リアルタイムの調整を必要とする多くのコンポーネントを含む複雑なシステム。 3 つのアーキテクチャ原則:

  • モジュール性 — 各機能は独立した境界付きコンテキストであり、個別に置き換え/アップグレードできます。
  • イベント駆動型 — サービスはイベントを介して通信し、結合を軽減し、監査証跡をサポートします
  • AIファースト — AI ワークロードのアーキテクチャの最適化: ストリーミング、長時間実行推論、GPU 対応スケーリング

2. 境界付きコンテキスト — AI チャットボットの DDD

ドメイン駆動設計を適用してプラットフォームを分割します。 8 つの境界付きコンテキスト:


┌───────────────────────────────────────────────────────────────────┐
│                    AI CHATBOT PLATFORM                             │
├───────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐             │
│  │ CONVERSATION │  │  KNOWLEDGE   │  │    AGENT     │             │
│  │   CONTEXT    │  │   CONTEXT    │  │   CONTEXT    │             │
│  │              │  │              │  │              │             │
│  │ • Session    │  │ • Documents  │  │ • Tools      │             │
│  │ • Messages   │  │ • Embeddings │  │ • Functions  │             │
│  │ • Memory     │  │ • Search     │  │ • Workflows  │             │
│  │ • Context    │  │ • Sync       │  │ • Planning   │             │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘             │
│         │                 │                 │                      │
│  ┌──────┴───────┐  ┌──────┴───────┐  ┌──────┴───────┐             │
│  │   CHANNEL    │  │  AI ENGINE   │  │  GUARDRAIL   │             │
│  │   CONTEXT    │  │   CONTEXT    │  │   CONTEXT    │             │
│  │              │  │              │  │              │             │
│  │ • Web Widget │  │ • LLM Router │  │ • Input Gate │             │
│  │ • Slack Bot  │  │ • Streaming  │  │ • Output Gate│             │
│  │ • WhatsApp   │  │ • Prompt Eng │  │ • PII Mask   │             │
│  │ • Mobile SDK │  │ • Model Mgmt │  │ • Toxicity   │             │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘             │
│         │                 │                 │                      │
│  ┌──────┴───────┐  ┌──────┴───────┐                               │
│  │  ANALYTICS   │  │   BILLING    │                               │
│  │   CONTEXT    │  │   CONTEXT    │                               │
│  │              │  │              │                               │
│  │ • Metrics    │  │ • Usage      │                               │
│  │ • Tracing    │  │ • Plans      │                               │
│  │ • Feedback   │  │ • Invoicing  │                               │
│  │ • Evals      │  │ • Quotas     │                               │
│  └──────────────┘  └──────────────┘                               │
│                                                                    │
└───────────────────────────────────────────────────────────────────┘

3. コンテキスト マップ — サービス インタラクション


// Domain Events flowing between bounded contexts
type DomainEvent =
  | { type: 'conversation.started'; payload: { sessionId: string; channelType: string; tenantId: string } }
  | { type: 'message.received'; payload: { sessionId: string; content: string; role: 'user' | 'assistant' } }
  | { type: 'knowledge.searched'; payload: { query: string; results: number; latencyMs: number } }
  | { type: 'tool.invoked'; payload: { toolName: string; params: Record<string, unknown>; success: boolean } }
  | { type: 'agent.planned'; payload: { plan: string[]; model: string } }
  | { type: 'guardrail.triggered'; payload: { type: string; severity: 'low' | 'medium' | 'high' | 'critical' } }
  | { type: 'response.generated'; payload: { sessionId: string; tokensUsed: number; latencyMs: number } }
  | { type: 'human.escalated'; payload: { sessionId: string; reason: string } }
  | { type: 'feedback.submitted'; payload: { messageId: string; rating: 'positive' | 'negative'; comment?: string } };

4. 高レベルのアーキテクチャ — C4 レベル 1 (システム コンテキスト)


                    ┌─────────────┐
                    │   End User  │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────▼────┐ ┌────▼─────┐ ┌───▼──────┐
        │ Web Chat │ │  Slack   │ │ WhatsApp │
        │  Widget  │ │   Bot    │ │   Bot    │
        └─────┬────┘ └────┬─────┘ └───┬──────┘
              │            │            │
              └────────────┼────────────┘
                           │
                   ┌───────▼───────┐
                   │  API Gateway  │
                   │  (Kong/Nginx) │
                   └───────┬───────┘
                           │
              ┌────────────┼────────────┐
              │                         │
     ┌────────▼─────────┐    ┌─────────▼──────────┐
     │  Chatbot Platform │    │   Admin Dashboard  │
     │     (Core API)    │    │   (Management UI)  │
     └────────┬─────────┘    └─────────┬──────────┘
              │                         │
    ┌─────────┼──────────┐             │
    │         │          │             │
┌───▼──┐ ┌───▼──┐ ┌────▼───┐  ┌─────▼─────┐
│OpenAI│ │Claude│ │ Self-  │  │PostgreSQL │
│ API  │ │ API  │ │ Hosted │  │  Qdrant   │
│      │ │      │ │ (vLLM) │  │  Redis    │
└──────┘ └──────┘ └────────┘  └───────────┘

5. C4 レベル 2 — コンテナ図


┌─────────────────────────────────────────────────────────────────────┐
│                        CHATBOT PLATFORM                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────┐    ┌──────────────────┐    ┌────────────────┐  │
│  │  Channel Gateway │───▶│ Conversation Svc │───▶│ AI Engine Svc  │  │
│  │  (NestJS)        │    │  (NestJS)        │    │ (Python/FastAPI│  │
│  │                  │    │                  │    │  + TypeScript) │  │
│  │  • WebSocket     │    │  • Session mgmt  │    │  • LLM Router  │  │
│  │  • REST API      │    │  • Context build │    │  • RAG Pipeline│  │
│  │  • Webhook recv  │    │  • Memory mgmt   │    │  • Prompt Eng  │  │
│  └─────────────────┘    └──────────────────┘    │  • Streaming   │  │
│                                                  └────────────────┘  │
│  ┌─────────────────┐    ┌──────────────────┐    ┌────────────────┐  │
│  │  Agent Service   │    │ Knowledge Service│    │ Guardrail Svc  │  │
│  │  (Python)        │    │  (Python)        │    │ (Python)       │  │
│  │                  │    │                  │    │                │  │
│  │  • Tool Registry │    │  • Doc Ingestion │    │  • Input check │  │
│  │  • Executor      │    │  • Embedding     │    │  • Output check│  │
│  │  • Planner       │    │  • Search        │    │  • PII masking │  │
│  └─────────────────┘    └──────────────────┘    └────────────────┘  │
│                                                                      │
│  ┌─────────────────┐    ┌──────────────────┐    ┌────────────────┐  │
│  │ Analytics Svc    │    │  Billing Service │    │ Admin API      │  │
│  │  (Python)        │    │  (NestJS)        │    │ (NestJS)       │  │
│  │                  │    │                  │    │                │  │
│  │  • Tracing       │    │  • Usage meter   │    │  • Tenant mgmt │  │
│  │  • Metrics       │    │  • Subscription  │    │  • Config      │  │
│  │  • Evals         │    │  • Invoicing     │    │  • Prompt mgmt │  │
│  └─────────────────┘    └──────────────────┘    └────────────────┘  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

6. イベント駆動型アーキテクチャ

AI チャットボットになぜイベント駆動型なのか?

  • 監査証跡 — すべての会話イベントがログに記録され、コンプライアンスにとって重要です
  • 非同期処理 — ナレッジの取り込み、分析、請求は非同期で実行されます
  • デカップリング — AI エンジンは請求について知る必要はありません。トークン使用状況イベントのみを発行する
  • リプレイ — イベントを再生して会話フローをデバッグし、モデルを再トレーニングします

// Event Bus implementation với Kafka
import { Kafka, Producer, Consumer } from 'kafkajs';

interface EventBus {
  publish(topic: string, event: DomainEvent): Promise<void>;
  subscribe(topic: string, handler: (event: DomainEvent) => Promise<void>): Promise<void>;
}

class KafkaEventBus implements EventBus {
  private producer: Producer;
  private consumers: Map<string, Consumer> = new Map();

  constructor(private kafka: Kafka) {
    this.producer = kafka.producer();
  }

  async publish(topic: string, event: DomainEvent): Promise<void> {
    await this.producer.send({
      topic,
      messages: [{
        key: event.payload.sessionId ?? crypto.randomUUID(),
        value: JSON.stringify({
          ...event,
          timestamp: new Date().toISOString(),
          eventId: crypto.randomUUID(),
        }),
        headers: {
          'event-type': event.type,
          'tenant-id': event.payload.tenantId ?? 'system',
        },
      }],
    });
  }

  async subscribe(
    topic: string,
    handler: (event: DomainEvent) => Promise<void>,
  ): Promise<void> {
    const consumer = this.kafka.consumer({ groupId: `${topic}-consumer` });
    await consumer.connect();
    await consumer.subscribe({ topic, fromBeginning: false });
    await consumer.run({
      eachMessage: async ({ message }) => {
        const event = JSON.parse(message.value!.toString()) as DomainEvent;
        await handler(event);
      },
    });
    this.consumers.set(topic, consumer);
  }
}

7. リクエスト フロー — ユーザー メッセージから応答まで


User Message
     │
     ▼
┌──────────┐     ┌──────────┐     ┌──────────┐
│ Channel  │────▶│ Input    │────▶│Conversa- │
│ Gateway  │     │ Guardrail│     │tion Svc  │
└──────────┘     └──────────┘     └────┬─────┘
                                       │
                    ┌──────────────────┤
                    │                  │
                    ▼                  ▼
              ┌──────────┐      ┌──────────┐
              │ Memory   │      │ Knowledge│
              │ Retrieve │      │ Search   │
              └────┬─────┘      └────┬─────┘
                   │                  │
                   └────────┬─────────┘
                            │
                            ▼
                      ┌──────────┐
                      │  Prompt  │
                      │ Assembly │
                      └────┬─────┘
                           │
                           ▼
                      ┌──────────┐
                      │ AI Engine│──── Tool Calls? ───▶ Agent Svc
                      │ (LLM)   │◀──── Results ──────┘
                      └────┬─────┘
                           │
                           ▼
                      ┌──────────┐     ┌──────────┐
                      │  Output  │────▶│ Channel  │──▶ User
                      │ Guardrail│     │ Delivery │
                      └──────────┘     └──────────┘
                           │
                           ▼
                    ┌──────────────┐
                    │ Event Bus    │
                    │ (Analytics,  │
                    │  Billing,    │
                    │  Logging)    │
                    └──────────────┘

8. コアデータモデル


// Core domain entities
interface Tenant {
  id: string;
  name: string;
  plan: 'free' | 'pro' | 'enterprise';
  config: TenantConfig;
  createdAt: Date;
}

interface TenantConfig {
  defaultModel: string;               // e.g., 'gpt-4o'
  fallbackModels: string[];            // e.g., ['claude-3-sonnet', 'gpt-4o-mini']
  maxTokensPerRequest: number;         // e.g., 4096
  maxConversationsPerDay: number;      // e.g., 10000
  enabledChannels: ChannelType[];      // e.g., ['web', 'slack']
  guardrailConfig: GuardrailConfig;
  ragConfig: RAGConfig;
}

interface Conversation {
  id: string;
  tenantId: string;
  channelType: ChannelType;
  channelUserId: string;
  status: 'active' | 'closed' | 'escalated';
  metadata: Record<string, unknown>;
  startedAt: Date;
  lastMessageAt: Date;
}

interface Message {
  id: string;
  conversationId: string;
  role: 'user' | 'assistant' | 'system' | 'tool';
  content: string;
  toolCalls?: ToolCall[];
  metadata: {
    model?: string;
    tokensUsed?: { input: number; output: number };
    latencyMs?: number;
    sources?: Citation[];
  };
  createdAt: Date;
}

interface Citation {
  documentId: string;
  chunkId: string;
  content: string;
  score: number;
  metadata: Record<string, unknown>;
}

type ChannelType = 'web' | 'slack' | 'teams' | 'whatsapp' | 'discord' | 'email' | 'api';

9. 導入トポロジ


┌─────────────────────────── Kubernetes Cluster ──────────────────────┐
│                                                                      │
│  ┌─── Namespace: chatbot-platform ──────────────────────────────┐   │
│  │                                                               │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │   │
│  │  │Channel   │ │Conversa- │ │AI Engine │ │Agent Svc │        │   │
│  │  │Gateway   │ │tion Svc  │ │(2 replicas│ │          │        │   │
│  │  │(3 rep.)  │ │(2 rep.)  │ │+ GPU pod)│ │(2 rep.)  │        │   │
│  │  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │   │
│  │                                                               │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │   │
│  │  │Knowledge │ │Guardrail │ │Analytics │ │Billing   │        │   │
│  │  │  Svc     │ │  Svc     │ │  Svc     │ │  Svc     │        │   │
│  │  │(2 rep.)  │ │(2 rep.)  │ │(1 rep.)  │ │(1 rep.)  │        │   │
│  │  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │   │
│  └───────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌─── Namespace: data ──────────────────────────────────────────┐   │
│  │  PostgreSQL (HA) │ Qdrant │ Redis Cluster │ Kafka │ MinIO    │   │
│  └───────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌─── Namespace: monitoring ────────────────────────────────────┐   │
│  │  Langfuse │ Prometheus │ Grafana │ AlertManager │ Loki       │   │
│  └───────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

10. API 設計原則


// REST API structure
// POST /api/v1/conversations                    — Start conversation
// POST /api/v1/conversations/:id/messages       — Send message (returns stream)
// GET  /api/v1/conversations/:id/messages       — Get message history
// POST /api/v1/conversations/:id/feedback       — Submit feedback
// POST /api/v1/conversations/:id/escalate       — Escalate to human
// GET  /api/v1/conversations/:id                — Get conversation details

// WebSocket for real-time
// ws://api/v1/ws?token=xxx

// Admin API
// POST /api/v1/admin/knowledge-bases             — Create knowledge base
// POST /api/v1/admin/knowledge-bases/:id/documents — Upload document
// GET  /api/v1/admin/analytics/conversations      — Analytics dashboard
// PUT  /api/v1/admin/prompts/:id                  — Update prompt template
// POST /api/v1/admin/tools                        — Register tool

レッスン 2 のまとめ

  • 8 つの境界付きコンテキスト: 会話、ナレッジ、エージェント、チャネル、AI エンジン、ガードレール、分析、請求
  • イベント駆動型 監査証跡 + 非同期処理 + デカップリングのための Kafka を使用したアーキテクチャ
  • リクエストのフロースルー 7段階: チャネル → 入力ガード → コンテキスト ビルド → RAG + メモリ → プロンプト → LLM → 出力ガード
  • それぞれのサービスは、 独立して展開可能 Kubernetes 上で
  • コアエンティティ: テナント → 会話 → メッセージ → 引用

次の記事: マルチモデル ゲートウェイ — OpenAI/Claude/Gemini/セルフホスト モデル間でリクエストをルーティングする方法、フォールバック チェーン、コストの最適化、トークンの予算管理。