ローカルLLMを使った設計書の自動生成の試作(ornith:9b)

はじめに

今回は、Discord ボットから送信されたコマンドを n8n のワークフロー経由で Google スプレッドシートに書き出す「コマンド型自動記録システム」について解説します。すべてのコンポーネントは Docker Compose で一元管理されており、要約・サマライズには Ollama を活用しています。

システム全体構成

まず全体の流れを把握しましょう。

sequenceDiagram
    participant User as ユーザー
    participant Bot as Discord Bot
    participant n8n as n8n Workflow
    participant Sheets as Google Sheets

    User->>Bot: /diary or /task or /memo
    Bot->>Bot: DISCORD_TOKEN 検証
    Bot->>n8n: POST Webhook (JSON)
    Note over n8n: body.type で分類<br/>diary/task/memo
    alt type == diary
        n8n->>Sheets: 「日記」シートに追加
    else type == task
        n8n->>Sheets: 「タスク」シートに追加
    else type == memo
        n8n->>Sheets: 「メモ」シートに追加
    end

Discord ボットの実装

Discord 側は Node.js(discord.js v14)で構築したスラッシュコマンドボットです。

Dockerfile

ベースイメージとして node:22-alpine を使用し、開発依存のみを省略して最小限にしています。

FROM node:22-alpine

WORKDIR /app

COPY package.json .
RUN npm install --omit=dev

COPY src/ ./src/

CMD ["node", "src/index.js"]

package.json

type: module を設定して ESM モジュールとして動作させています。外部依存は discord.js ^14.16.3 のみです。

{
  "name": "discord-bot",
  "version": "1.0.0",
  "type": "module",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js"
  },
  "dependencies": {
    "discord.js": "^14.16.3"
  }
}

コマンド処理ロジック(src/index.js)

ボットは起動時にグローバルスラッシュコマンド diarytaskmemo を登録します。ユーザーがこれらのコマンドを実行すると、それぞれのタイプに合わせて n8n の Webhook に JSON で送信されます。環境変数でトークンとクライアントIDを読み込み検証し、Webhook URL は .env ファイルから供給されます。

flowchart LR
    A[ボット起動] --> B[DISCORD_TOKEN 読み込み]
    C[DISCORD_CLIENT_ID 読み込み]
    D[N8N_WEBHOOK_URL 読み込み]
    B --> E[グローバルコマンド登録<br/>/diary /task /memo]
    F[ユーザーがスラッシュコマンドを実行] --> G[type 判定]
    G --> H[JSON を n8n Webhook に POST]

n8n ワークフローの設計

n8n 側は「コマンド型自動記録システム」として、Discord Webhook からの入力を Google スプレッドシートに書き出す役割を担います。

入力分類と出力先

body.type フィールドで 3 つのカテゴリに分岐し、それぞれ異なるシートの別タブに対応します。

| type | シート名 | 説明 |
|——–|———-|——|
| diary | 日記 | 日々の記録 |
| task | タスク | 作業タスク |
| memo | メモ | 自由メモ |

IF ノードによる分岐処理

ワークフローの中心には条件分岐(IF ノード)があり、入力された type に応じて 3 つのパイプラインを並行して管理しています。各パイプラインでは日時・投稿者・内容をマッピングし、対応するシートに追加する処理を一貫させています。

Docker Compose 構成

すべてのサービスを Docker Compose で一元管理します。

サービス連携とネットワーク

3 つのサービスが bridge ネットワーク bot-network を共有しています。Discord ボットは n8n の健康チェックが完了した後に起動される依存関係管理(depends_on)を採用しており、起動順序を保証しています。

flowchart TD
    subgraph Docker["Docker Compose 構成"]
        direction LR
        env[".env ファイル<br/>環境変数供給"]
        
        n8n["n8n サービス<br/>(公式イメージ)"]
        bot["Discord Bot<br/>(node:22-alpine)"]
        
        volume["永続化ボリューム<br/>(n8n 用命名ボリューム)"]
    end
    
    env --> n8n
    n8n --> bot
    n8n -.->|健康チェック完了後| bot

    n8n ---|"bot-network"| bot

タイムゾーン設定

n8n サービスは Asia/Tokyo タイムゾーンで動作するように設定されています。

環境変数構成(.env.example)

DISCORD_TOKEN=your_discord_bot_token_here
DISCORD_CLIENT_ID=your_application_id_here
N8N_WEBHOOK_URL=http://n8n:5678/webhook/discord

これらの変数は .env ファイルからサービスに供給され、ボットと n8n が共通して参照します。

まとめ

本システムでは、Discord ボットでスラッシュコマンドを受け付け → n8n ワークフローで body.type 別に分類 → Google スプレッドシートへ自動記録するパイプラインを構築しました。Ollama を活用した要約・サマライズ機能も Docker Compose の構成文書に組み込んでおり、全体の運用コストを抑えています。

flowchart LR
    subgraph Step1["Step 1: Discord ボット"]
        direction TB
        A[ユーザーコマンド] --> B[type 判定<br/>diary/task/memo]
        B --> C[n8n Webhook に JSON POST]
    end

    subgraph Step2["Step 2: n8n ワークフロー"]
        direction TB
        D[IF ノードで type 分岐] --> E{type == diary?}
        E -->|はい| F1["「日記」シートに追加<br/>日時・投稿者・内容"]
        E -->|いいえ| G{type == task?}
        G -->|はい| F2["「タスク」シートに追加"]
        G -->|いいえ| F3["「メモ」シートに追加"]
    end

    subgraph Step3["Step 3: Google Sheets 出力"]
        direction TB
        F1 --> H[自動記録完了]
        F2 --> H
        F3 --> H
    end

    Step1 --> Step2 --> Step3

コメント

タイトルとURLをコピーしました