Tsurugi 上に Ops Incident Ledger(OIL) という運用インシデント管理 Web アプリケーションを構築し、oil-oss として公開しました。インシデントといってもセキュリティ・インシデントに限定した対応ツールではなく、広く一般の運用障害・作業ミス・顧客影響などを記録し、過去事例や手順書へつなげることで、障害対応までの時間と手間を軽減するための AI 支援ツールです。
運用監視ネットワークはインターネットに直接接続できないことがほとんどであり、障害内容や顧客名を外部 API に送れない現場を主な想定としています。LLM 推論・埋め込み・RAG 索引(FAISS)まで Ollama 上のローカル LLM で完結するオンプレ構成を標準としています。もちろん API キーを指定することでクラウド LLM(OpenAI)への切り替えも可能です。本稿では全体構成と、AI チャットにおける RDB 検索と RAG(ベクトル検索)の二系統設計を中心に紹介します。
Ops Incident Ledger の位置づけ
IT サービス管理(ITSMS)では、ヘルプデスクを起点にインシデント管理・問題管理・変更管理・リリース管理などのプロセスが連なります。OIL はそのうち、ヘルプデスク周辺のインシデント記録と復旧対応、および対応手順書(KEDB)によるナレッジ再利用を担います。根本原因の恒久対策を扱う問題管理以降のプロセスは対象外です。
| プロセス | OIL での扱い |
|---|---|
| インシデント管理(記録・初動・復旧) | 台帳・AI トリアージ・対応履歴・チャット検索 |
| 対応手順書(KEDB) | 手順の蓄積・推奨・下書き生成 |
| 問題管理 | 対象外(根本原因分析・恒久対策の管理は行わない) |
| 変更管理・リリース管理 | 対象外 |
背景
運用インシデント管理の現場では、次のような課題がよく起きます。
| 課題 | 具体例 |
|---|---|
| 情報が散在する | チケット、チャット、個人メモに履歴が分かれる |
| 過去事例の検索が遅い | 「似た障害、前にどう対応した?」に時間がかかる |
| 初動の品質にばらつきがある | 重要度・分類の付け忘れ、記載漏れ |
| ナレッジが残らない | 解決後に手順書化されず、同種障害で再調査になる |
| 件数把握が手作業になる | 「先週の顧客 NW 障害は何件?」を都度 SQL や集計で調べる |
Ops Incident Ledger は、これらに対して 記録 → 再利用 → 改善 のループを 1 画面で回すプロダクトです。
| 価値 | 機能 |
|---|---|
| 一元記録 | インシデント・調査・対応履歴を 1 画面で管理 |
| ナレッジ循環 | 対応手順書(KEDB)の蓄積、類似事例・推奨手順の提示 |
| AI 支援 | 自然文検索、初動トリアージ、手順書下書き |
AI は最終判断の代替ではなく、検索・下書き・入力補助に特化しています。データの正は RDB(Tsurugi)に置き、ベクトル索引は検索と推奨を強化する層として併用します。
閉域網の運用監視向けに
運用系の台帳は、インシデント内容・顧客名・内部ホスト名を外部 SaaS に送信できないことが前提に近いです。NOC や監視セグメントがインターネット非接続であるケースも珍しくありません。OIL は次をすべてオンプレで回せるよう設計しています。
| 層 | オンプレの実装 |
|---|---|
| 台帳・検索 | Tsurugi(RDB) |
| 意味検索 | FAISS(同梱索引は nomic-embed-text / 768 次元) |
| 埋め込み | Ollama nomic-embed-text
|
| チャット・トリアージ・下書き | Ollama qwen3.6:27b クラス(26B パラメータ級) |
開発・評価では RTX 5090 クラス(VRAM 32GB)のワークステーション上で Ollama を用い、次の用途で実用に耐える応答を確認しています。
| 用途 | オンプレ LLM での体感 |
|---|---|
| チャット(RDB / RAG ツール呼び出し) | 1 ターン十数秒〜数十秒 |
| トリアージ・提案カード | 重要度・種類の提案が成立 |
| 手順書下書き | 解決済みインシデントから Markdown 下書きを生成可能 |
config.yaml の ai.provider / ai.llm_provider を openai に切り替えれば、インターネット経由のクラウド LLM でより短いレイテンシを狙えます。応答速度やツール選択の安定性はモデル・量子化・GPU に依存するため、本稿の体感は特定構成での参考値です。
システム概要
スタックとデータ規模
| 項目 | 内容 |
|---|---|
| バックエンド | FastAPI(Python 3.12) |
| フロントエンド | Vue.js + Quasar(SPA) |
| RDB | Tsurugi |
| ベクトル検索 | FAISS |
| AI エージェント | LangGraph(既定: Ollama。OpenAI 切替可) |
| オンプレ LLM | Ollama + qwen3.6:27b、埋め込み nomic-embed-text |
| RAG 索引(同梱) | FAISS / 2,896 文書 / nomic-embed-text(768 次元) |
| 配布 | Docker Compose |
同梱のサンプルデータは、架空の SaaS 事業者「株式会社ストッククラウド」が運用する Mercury / Venus サービスの障害対応記録です。
| データ | 件数 |
|---|---|
| インシデント | 304 |
| 対応履歴 | 449 |
| 対応手順書 | 51 |
| RAG 文書(障害報告・調査・対応) | 2,896 |
モジュール構成
利用者が触るのはブラウザのみです。バックエンドが Tsurugi・FAISS・オンプレ LLM(Ollama)を束ねます。クラウド LLM を使う場合は設定変更のみで、構成図の LLM ノードが外部 API に置き換わります。
| コンポーネント | 効果 |
|---|---|
| Tsurugi | 一覧・詳細・保存の即時反映 |
| FAISS | 類似インシデント・手順書・自然文検索(オンプレ埋め込みで構築) |
| Ollama | チャット応答、トリアージ提案、手順書下書き、ベクトル化 |
画面と業務フロー
5 領域の一体型ワークスペース
画面は次の 5 領域で構成されています。
| 領域 | 役割 |
|---|---|
| ヘッダ | タイトル、ログインユーザ、基準日、表示切替、ログアウト |
| 左サイドバー | クイックフィルタ(今月・先月・未解決)と手順書使用回数 Top5 |
| 中央 | インシデント / 手順書の一覧・詳細・編集 |
| 右 | AI チャット(幅リサイズ可) |
| 下部 | LLM 処理ログパネル(任意表示) |
インシデント対応中に一覧・詳細・チャット・ログを行き来せず同時に見られる設計です。詳細を開くと、そのインシデントが AI チャットのコンテキストとして渡されます。
検知からナレッジ化まで
| フェーズ | 人手 | AI / 自動 |
|---|---|---|
| 1. 検知・登録 | 新規インシデント入力 | 保存後トリアージ自動開始 |
| 2. トリアージ | 提案の受入・却下 | 重要度・分類の提案、追加質問 |
| 3. 対応 | 手順適用、対応履歴記録 | 推奨手順・類似事例、チャット検索 |
| 4. ナレッジ化 | 手順書確認・保存 | 対応履歴から下書き生成 |
RDB 検索と RAG の二系統
AI チャットの中心は LangGraph エージェントです。ユーザーの自然文に対し、事前定義の RDB ツールと FAISS ベクトル検索を使い分けます。ローカル LLM でも安全・確実に実行するために、任意の Text-to-SQL は採用していません。
質問に応じて経路を分ける理由
| 質問の種類 | 経路 | 理由 |
|---|---|---|
| 条件付き一覧・件数集計 | LangGraph ツール → Tsurugi(事前定義 SQL / 集計 API) | 再現性と安全性を確保。LLM が SQL を自由生成しない |
| 自然文・類似事例・手順探索 | FAISS ベクトル検索 | タイトル・説明・対応文の意味的類似を拾う |
| 週次件数など定型サマリ | 事前生成の集計サマリ文書(RAG) | 毎回 SQL を組まず、自然文クエリでヒットさせる |
エージェントが利用する主なツールは次のとおりです。
| ツール | 役割 |
|---|---|
search_incidents |
状態・重要度・日付・キーワードで RDB から明細一覧 |
aggregate_incidents |
GROUP BY による件数集計(発生個所別・状態別など) |
search_documents_rag |
FAISS で障害報告・調査・対応・集計サマリ・手順書を検索 |
get_incident_detail |
特定インシデントの詳細取得 |
get_context_incident |
画面表示中インシデントの詳細(コンテキスト付き質問用) |
get_current_datetime |
アプリの現在日時・タイムゾーン・基準日の取得 |
get_system_context |
企業・サービス・顧客・インシデント種類など運用背景マスタの取得 |
システムプロンプトでツールの使い分けを明示しています。例えば status には DB 値(OPEN / IN_PROGRESS / RESOLVED)を指定するよう指示し、画面表示の日本語ラベル(未着手・対応中・解決済み)との対応表も LLM に渡します。
質問例
| 種別 | 質問例 | 主に使われるツール |
|---|---|---|
| RDB のみで足りる | 「未完了のうち、顧客ネットワークに関わるインシデントを教えて」 |
search_incidents(keyword でタイトル・説明を検索) |
| RDB 集計 | 「発生個所別の件数を教えて」 | aggregate_incidents |
| RAG | 「棚卸の突合エラーで過去にどう対応した?」 |
search_documents_rag → 必要なら get_incident_detail
|
| RDB + RAG 併用 | 「未完了のインシデントを一覧して、顧客ネットワーク障害の過去の対応内容も参考に教えて」 |
search_incidents → search_documents_rag
|
ツールの選択は LLM が行います。「未完了 × 顧客ネットワーク」のようにタイトル・説明のキーワード検索だけで足りる質問では search_incidents のみが呼ばれ、ai_rag ログは出ません。対応内容・調査記録・手順書など RDB の一覧では取れない情報を求めると、RAG ツールが追加で呼ばれやすくなります。
RDB と RAG の併用実行例
Docker Compose 上のサンプルデータで、オンプレ LLM(Ollama qwen3.6:27b)に次の質問を投げたときの実測例です。
質問
未完了のインシデントを一覧して、顧客ネットワーク障害の過去の対応内容も参考に教えて
ツール実行の流れ
| 順序 | イベント | 内容 |
|---|---|---|
| 1 | chat_request |
上記メッセージを受信(llm_provider: ollama, model: qwen3.6:27b) |
| 2 |
mcp_tool → search_incidents
|
status: ["OPEN", "IN_PROGRESS"] で未完了一覧(total: 22、先頭 20 件を返却) |
| 3 | ai_sql |
status IN ('OPEN','IN_PROGRESS') 等の事前定義 SQL |
| 4 | ai_rag |
クエリ "顧客ネットワーク障害 対応内容 事例" で FAISS 検索(10 件、約 3.07 秒) |
| 5 |
mcp_tool → search_documents_rag
|
同一クエリのツール返却(対応履歴・調査記録が中心) |
| 6 | chat_timing |
全体約 34.9 秒(うち、ツール約 13.0 秒) |
RAG でヒットした文書の例(doc_ids より):
| doc_id | 種別 | 回答での参照例 |
|---|---|---|
DOC-INV-00576 |
調査記録 | 監視ダッシュボード不表示の初期調査 |
DOC-RSP-00746 |
対応履歴 | 拠点 API 失敗時の情報収集・連絡体制 |
DOC-RSP-00831 |
対応履歴 | DNS 設定点検・キャッシュクリア |
DOC-RSP-00960 他 |
対応履歴 | 類似のネットワーク系障害パターン |
LLM の回答
現在未完了(OPEN / IN_PROGRESS)のインシデントは計 22 件。そのうち顧客ネットワーク障害に関連する進行中事象と、RAG から得た過去の対応パターンを次のように整理しました。
1. 未完了インシデント一覧
【顧客ネットワーク障害】関連(4 件)
incident_id タイトル 状態 重要度 発生日 INC-2026-00327 【障害報告】【顧客ネットワーク障害】拠点限定API失敗 対応中 LOW 2026-06-18 INC-2026-00148 【障害報告】【顧客ネットワーク障害】拠点限定API失敗 対応中 LOW 2026-03-27 INC-2024-00026 【障害報告】【顧客ネットワーク障害】代理サーバー502 対応中 LOW 2024-08-19 INC-2022-00303 【障害報告】【顧客ネットワーク障害】TLS握手切断 対応中 LOW 2022-06-05 【他カテゴリ】代表的な未完了(抜粋):
INC-2026-00039合成監視失敗 (HIGH・未着手)、INC-2026-00283ブルートフォース誤検知 (CRITICAL)、INC-2026-00504WALアーカイブ滞留 (HIGH) など。2. 過去の「顧客ネットワーク障害」関連の対応内容事例(RAG 由来)
- パターン A(拠点 API 失敗) — 障害発生 30 分以内の情報収集と影響拠点への連絡、社内エラーログの確認・原因特定会議の設定(
DOC-RSP-00746)- パターン B(DNS・接続切断) — DNS 設定の点検・更新、キャッシュクリア、影響店舗への復旧状況の逐次報告(
DOC-RSP-00831)- パターン C(再発防止) — テスト環境での連携テスト、定例リリース前検証の強化
一覧の件数・ID は Tsurugi の search_incidents が担保し、対応パターンの文脈は FAISS 上の DOC-RSP-* / DOC-INV-* から補われています。1 ターン約 35 秒で外部 API に本文を送らずに統合回答が得られる例です。
実際のサーバログ
2026-07-03T22:16:10.599+09:00chat_request{"seq":3,"event":"chat_request","ts":"2026-07-03T22:16:10.599+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","user_message":"未完了のインシデントを一覧して、顧客ネットワーク障害の過去の対応内容も参考に教えて","turn":2,"history_messages":3,"context_incident_id":null,"llm_provider":"ollama","model":"qwen3.6:27b"}
2026-07-03T22:16:20.379+09:00ai_sql{"seq":4,"event":"ai_sql","ts":"2026-07-03T22:16:20.379+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","sql":"SELECT COUNT(*) FROM oil_incidents i WHERE i.company_id = ? AND i.status IN (?,?)","params":["COMP-001","OPEN","IN_PROGRESS"],"duration_ms":9.02,"row_count":1}
2026-07-03T22:16:20.388+09:00ai_sql{"seq":5,"event":"ai_sql","ts":"2026-07-03T22:16:20.388+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","sql":"SELECT i.incident_id, i.occurred_at, i.title, i.status, i.severity FROM oil_incidents i WHERE i.company_id = ? AND i.status IN (?,?) ORDER BY i.occurred_at DESC LIMIT 20","params":["COMP-001","OPEN","IN_PROGRESS"],"duration_ms":8.49,"row_count":20}
2026-07-03T22:16:20.411+09:00ai_sql{"seq":6,"event":"ai_sql","ts":"2026-07-03T22:16:20.411+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","sql":"SELECT incident_id, COUNT(*) FROM oil_incident_responses GROUP BY incident_id","params":[],"duration_ms":22.27,"row_count":818}
2026-07-03T22:16:20.412+09:00mcp_tooltool=search_incidents params={"status":["OPEN","IN_PROGRESS"]} response={"total": 22, "items": [{"incident_id": "INC-2026-00039", "occurred_at": "2026-06-24 12:48:38+00:00"… (4147文字)
2026-07-03T22:16:24.865+09:00ai_rag{"seq":8,"event":"ai_rag","ts":"2026-07-03T22:16:24.865+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","query":"顧客ネットワーク障害 対応内容 事例","top_k":10,"duration_ms":3067.28,"result_count":10,"doc_ids":["DOC-INV-00576","DOC-RSP-00960","DOC-RSP-00256","DOC-RSP-00628","DOC-RSP-00607","DOC-RSP-00831","DOC-RSP-00746","DOC-RSP-00705","DOC-RSP-00123","DOC-RSP-00656"],"scores":[0.728,0.709,0.702,0.6962,0.6932,0.6921,0.6907,0.6898,0.6895,0.6875]}
2026-07-03T22:16:24.866+09:00mcp_tooltool=search_documents_rag params={"query":"顧客ネットワーク障害 対応内容 事例"} response=[{"doc_id": "DOC-INV-00576", "score": 0.7280425429344177, "text": "初期調査の結果、運用コンソール内の監視ダッシュボードが表示されない… (2929文字)
2026-07-03T22:16:46.777+09:00chat_timing{"seq":10,"event":"chat_timing","ts":"2026-07-03T22:16:46.777+09:00","service":"oil","env":"docker","version":"0.1.0","request_id":"82caa2da-68ae-4db8-9507-ebdc6958866e","duration_ms":34884.14,"llm_ms":34882.84,"tool_ms":12972.97,"turn":2,"response_chars":1366,"llm_provider":"ollama","model":"qwen3.6:27b","status":"ok"}
対比:RDB のみで終わる質問
同じ「未完了 × 顧客ネットワーク」でも、
未完了のうち、顧客ネットワークに関わるインシデントを教えて
のように一覧だけを求めると、search_incidents に keyword: "顧客ネットワーク" が渡され 4 件に絞り込まれ、search_documents_rag は呼ばれません(ai_rag ログなし)。
画面表示との連携
インシデント詳細を開くと、チャットを使わなくても 推奨手順書と類似インシデントが FAISS 類似検索で自動提示されます。一覧画面ではキーワード検索に加え、意味検索(RAG)オプションでベクトル検索結果を一覧表示できます。
データの正と RAG の鮮度
| トリガー | 動作 |
|---|---|
| インシデント保存 | タイトル+説明の差分 upsert、集計サマリ再生成 |
| 対応保存 | 関連文書・集計サマリ更新 |
| 手順書保存 | 手順書ベクトルの upsert(無効時は削除) |
いずれも HTTP 応答は RDB 確定後に即返却し、RAG 更新は BackgroundTasks で非同期実行します。公開リポジトリ同梱の data/faiss/ は Ollama nomic-embed-text でビルド済みであり、Docker 起動後すぐオンプレ RAG 検索が利用できます(manifest.json の embedding_model を参照)。
AI と DB 更新の境界
エージェントは原則として RDB を直接更新しません。トリアージで重要度や種類を提案しても、ユーザーがチャット内の提案カードで「受け入れる」ボタンを押したときに初めて REST API 経由で保存されます。保存操作の権限はロール(VIEWER / OPERATOR / ADMIN)で制御します。
Dockerで試す
本記事の手順は oil-oss リポジトリの Docker Compose を想定しています。
| 項目 | 内容 |
|---|---|
| 実行環境 | Docker / Docker Compose v2 |
| GPU ワークステーション(推奨) | RTX 5090 クラス、Ollama で qwen3.6:27b |
| AI(標準) | ホスト上の Ollama(LLM + 埋め込み) |
| AI(オプション) |
OPENAI_API_KEY を設定し config.yaml で provider / llm_provider を openai に変更 → より高速な応答 |
| データベース | Tsurugi(compose に同梱) |
| RAG 索引 | 同梱 data/faiss/(nomic-embed-text、2,896 文書) |
| サンプルデータ | 架空SaaS「Mercury」「Venus」障害対応(2020年4月~2026年6月) |
1. Ollama の準備
必要なモデルをPULLします。
ollama pull qwen3.6:27b
ollama pull nomic-embed-text
2. oil コンテナの起動
git clone https://github.com/septigram/oil-oss.git
cd oil-oss
cp .env.example .env
docker compose up --build
既定の docker/config/config.yaml は Ollama オンプレ向けです。
ai:
provider: ollama
llm_provider: ollama
ollama_base_url: http://host.docker.internal:11434
ollama_llm_model: qwen3.6:27b
ollama_embedding_model: nomic-embed-text
oil コンテナからホスト上の Ollama に接続します(Windows / macOS の Docker Desktop では host.docker.internal)。Linux では extra_hosts 等でホストゲートウェイを設定してください。バックエンドをホスト上で直接起動する場合は http://localhost:11434 で構いません(BUILD.md 参照)。
3. ブラウザで開く
ブラウザで http://localhost:8000/oil/ にアクセスしてください。
| 項目 | 値 |
|---|---|
| ログイン ID | admin |
| パスワード |
.env の OIL_BOOTSTRAP_PASSWORD(未設定時は admin) |
クラウド LLM を使う場合
.env に OPENAI_API_KEY を設定し、ai.provider / ai.llm_provider を openai に変更します。
FAISS 索引を OpenAI 埋め込みで作り直す場合は python tools/build_faiss_index.py を実行してください(次元が変わるため必須)。
4. チャットの動作確認
- 左サイドバー「未解決」→ 一覧を確認(RDB 系の画面操作)
- 「発生個所別の件数を教えて」→
aggregate_incidentsの応答を確認 - 「棚卸の突合エラーで過去にどう対応した?」→ RAG のみの応答を確認
- 「未完了のインシデントを一覧して、顧客ネットワーク障害の過去の対応内容も参考に教えて」→
search_incidentsとsearch_documents_ragの併用 - 下部ログパネルで
mcp_tool(ツール名)とai_ragの有無を確認
成果物
参考リンク
| リンク | 説明 |
|---|---|
| Tsurugi | トランザクション処理向け OSS データベース |
| Ollama | オンプレ LLM・埋め込み |
| user-manual.md | OILの利用者向け操作ガイド |
| BUILD.md | OILのビルドと設定 |
| SECURITY.md | OILの脆弱性報告 |
まとめ
Ops Incident Ledger プロダクトは、次の 4 点を実現します。
- 閉域の運用監視網でも、台帳・RAG・AI チャットをオンプレで回せること
- データの正は Tsurugi、FAISS はオンプレ埋め込みで構築した検索・推奨層であること
- RDB ツールと RAG の役割分担が、エージェント型運用ツールの実装パターンとして参考になること
- クラウド LLM はより高速な応答のためのオプションであり、標準は Ollama 上の qwen3.6:27b クラスで実用可能であること
応答時間ログや Prometheus メトリクスなど、本番運用を想定した計測・可観測性も備えています。外部 Webhook によるインシデント受信や Slack Bot 連携、一覧画面の意味検索オプションなどは、公開リポジトリの release-notes に記載されています。
本稿の構成や数値は特定環境・サンプルデータに基づく参考情報です。ご利用にはご注意ください。
