連載: NMS開発者がLLMブートキャンプで学んだこと
次回 →
ネットワーク監視システム、いわゆる NMS(Network Management System) の開発に関わっていると、毎日のように大量のアラート、ログ、SNMP Trap、障害チケットに向き合うことになります。
もちろん、監視システムはすでに多くのことを自動化しています。しきい値を超えればアラートを出し、装置から Trap が飛んでくればイベントとして保存し、障害が起きれば担当者に通知します。
それでも、現場では最後に人間が読んで判断しなければならない場面が多く残っています。
たとえば、ある夜に複数のルータから同時にアラートが上がったとします。CPU 使用率、インターフェース Down、BGP セッション断、SNMP timeout、監視サーバ側の polling failed。画面上にはイベントが並びますが、実際に知りたいことはもう少し別のところにあります。
- これは本当に障害なのか、一時的な揺らぎなのか
- 影響を受けている顧客やサービスはどれか
- 過去にも似た障害があったのか
- 一次対応として何を確認すべきか
- チケットにはどう要約すればよいか
ログはある。アラートもある。ダッシュボードもある。
しかし、人間が状況を理解するまでには、まだ時間がかかる。
私が LLM に興味を持った理由は、まさにこのギャップでした。
最初は「便利なチャット」だと思っていた
正直に言うと、最初の頃は LLM をかなり単純に見ていました。
「ChatGPT に聞けば、だいたい答えてくれる」
そのくらいの理解でした。調べものを手伝ってくれるチャット UI、文章を整えてくれるツール、コードの書き方を教えてくれる補助役。もちろんそれだけでも便利です。
ただ、NMS や業務システムの開発者として見ると、それだけでは少し遠い存在にも感じていました。
ブラウザで ChatGPT を開き、ログを貼り付けて質問する。これは個人作業としては便利ですが、既存の監視システムやチケットシステムにそのまま組み込めるわけではありません。運用フローに入れるなら、API として呼び出し、入力と出力を制御し、失敗したときの扱いも考える必要があります。
LLM ブートキャンプに参加しようと思ったのは、この「便利なチャット」と「業務システムに組み込める部品」の間にある距離を、自分の手で確かめたかったからです。
1週目で見えたもの
ブートキャンプの最初の週では、OpenAI API を Python から呼び出すところから始まりました。
授業では、OpenAI クライアントを作り、messages に role と content を入れてモデルへ渡し、返ってきた response.choices[0].message.content から回答本文を取り出す、という基本の流れを確認しました。
最初はとても小さなコードです。
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "このログを短く要約してください"}
],
)
print(response.choices[0].message.content)
ただ、この小さなコードを見たときに、私の中ではかなり見え方が変わりました。
LLM は、チャット画面の中だけにあるものではない。
Java/Spring のバックエンドから呼んでもいいし、Node.js の API サーバから呼んでもいい。FastAPI で小さな分析サービスとして切り出してもいい。既存の NMS が持っているアラート情報、装置情報、チケット情報を入力として渡せば、LLM を「推論する処理部品」として扱える可能性がある。
この感覚は、ブラウザで ChatGPT を使っているだけでは得られませんでした。
ここで考えている LLM 活用は、監視システムを置き換えるものではありません。
NMS が集めたアラート、SNMP Trap、syslog を LLM に渡し、運用者が最初に読むべき形へ整理する、という位置づけです。
左側にあるのは、これまで通り NMS が収集するイベントです。中央の LLM は、その情報を解釈し、右側のように JSON や障害チケット草案へ変換します。最終判断は運用者が行いますが、状況理解までの時間を短くする補助線として使えます。
いきなり実務投入できるほど甘くはない
一方で、1週目からすぐに分かったこともあります。
LLM は API で呼べるようになった瞬間に、すぐ業務で安全に使えるわけではありません。
まず API Key の管理があります。授業では .env ファイルと load_dotenv() を使って、キーをコードに直接書かない方法を扱いました。これは地味ですが、実務ではかなり重要です。
監視システムのコードに API Key を直書きして Git に push してしまう。考えただけで嫌な汗が出ます。
次に、出力形式の問題があります。
人間が読むだけなら自然文の回答でも十分です。しかし、既存システムに連携するなら、出力はできるだけ構造化されていた方が扱いやすい。たとえば障害ログを要約する場合でも、単に文章で返すより、次のような JSON にしたくなります。
{
"severity": "high",
"summary": "Core router で BGP セッション断が発生しています。",
"impact": "外部接続の一部に影響する可能性があります。",
"suspected_cause": "回線断または対向装置側の問題が疑われます。",
"first_actions": [
"対象インターフェースの状態を確認する",
"直近の設定変更履歴を確認する",
"対向装置のアラート有無を確認する"
]
}
1週目の内容では、JSON、辞書、リスト、role、content、system / user / assistant のメッセージ構造を扱いました。最初は基礎文法に見えますが、あとから考えると、これは LLM を業務システムへ組み込むための土台でした。
LLM の回答を人間が読むだけなら、多少ゆらいでも許容できます。
しかし、後続処理が JSON を parse するなら、余計な説明文が混ざるだけで失敗します。チケット自動作成、障害分類、通知文生成、ダッシュボード連携まで考えると、出力形式の安定性は単なる見た目の問題ではありません。
NMS の現場で考えた小さな例
ブートキャンプの最初の実習を見ながら、私は NMS の障害ログを LLM に渡すならどうするかを考えていました。
たとえば、次のようなログがあるとします。
2026-03-10 21:14:03 CRITICAL router-core-01 BGP neighbor 10.10.0.2 Down
2026-03-10 21:14:08 WARNING router-core-01 Interface Gi0/1 input errors increased
2026-03-10 21:14:15 CRITICAL nms-poller SNMP timeout router-core-01
これをそのまま担当者に通知しても、経験の浅い運用者には少し読みづらいかもしれません。そこで、LLM に次のように依頼します。
あなたはネットワーク運用担当者です。
以下の障害ログを、NOC 担当者が初動対応できる形に要約してください。
出力は JSON のみ。
項目は severity, summary, impact, first_actions にしてください。
この時点では、まだ本格的な RAG も Agent も使っていません。単純にログを渡して、読みやすく整理するだけです。
それでも、現場目線では価値があります。
大量のアラートを人間が一つずつ読む前に、LLM が「これは何が起きていそうか」「何から確認すべきか」を仮説としてまとめる。もちろん最終判断は人間が行いますが、最初の理解にかかる時間を短くできるかもしれません。
ここで大事なのは、LLM に障害対応を丸投げすることではありません。
まずは、人間が読むための形に整える。判断材料を並べる。チケットに貼れる要約を作る。そういう小さな補助から始める方が、現実的だと感じました。
小さな実習: NMS障害ログをJSONチケット草案に変換する
ここでは、NMS の障害ログを OpenAI API に渡し、NOC 担当者が初動対応に使える JSON へ変換する最小例を試します。
目的は、完成した障害対応システムを作ることではありません。LLM を既存の NMS 処理パイプラインに組み込むと、どのような出力が得られるのかを小さく確認することです。
準備
必要な Python パッケージをインストールします。
pip install openai
同じディレクトリに .env ファイルを作り、OpenAI API Key を設定します。
OPENAI_API_KEY=sk-...
コード
#nms_log_to_ticket.py
import json
import os
import sys
from pathlib import Path
try:
from openai import OpenAI
except ImportError:
print("openai package is not installed. Run: pip install openai")
sys.exit(1)
def load_env_file(path=".env"):
env_path = Path(path)
if not env_path.exists():
return
for line in env_path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
os.environ.setdefault(key.strip(), value.strip().strip('"').strip("'"))
SAMPLE_NMS_LOG = """\
2026-03-10 21:14:03 CRITICAL router-core-01 BGP neighbor 10.10.0.2 Down
2026-03-10 21:14:08 WARNING router-core-01 Interface Gi0/1 input errors increased
2026-03-10 21:14:15 CRITICAL nms-poller SNMP timeout router-core-01
"""
SYSTEM_PROMPT = """\
あなたはNMS(Network Management System)を運用するネットワークエンジニアです。
入力された障害ログを読み、NOC担当者が初動対応に使えるJSONだけを返してください。
必ず次のキーを含めてください:
- severity: low, medium, high, critical のいずれか
- summary: 1文の要約
- suspected_cause: 推定原因
- impact: 想定される影響
- first_actions: 最初に確認する作業を3つの配列で返す
- ticket_draft: 障害チケットに貼れる短い本文
余計な説明文、Markdown、コードフェンスは出力しないでください。
"""
def main():
load_env_file()
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("OPENAI_API_KEY is missing. Set it in .env or environment variables.")
sys.exit(1)
client = OpenAI(api_key=api_key)
model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
response = client.chat.completions.create(
model=model,
temperature=0,
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": SAMPLE_NMS_LOG},
],
)
content = response.choices[0].message.content
data = json.loads(content)
print(json.dumps(data, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()
実行
python nms_log_to_ticket.py
出力例
モデルの応答なので完全に同じ文章になるとは限りませんが、次のような JSON が返ります。
{
"severity": "critical",
"summary": "router-core-01でBGPセッション断とSNMP timeoutが発生しています。",
"suspected_cause": "対向装置または回線障害、もしくはrouter-core-01側のインターフェース異常が疑われます。",
"impact": "外部接続または経路制御に影響し、一部通信断が発生している可能性があります。",
"first_actions": [
"router-core-01のGi0/1インターフェース状態とエラーカウンタを確認する",
"BGP neighbor 10.10.0.2の対向装置状態を確認する",
"NMSからrouter-core-01へのSNMP疎通と監視経路を確認する"
],
"ticket_draft": "router-core-01にてBGP neighbor 10.10.0.2 Down、Gi0/1 input errors増加、SNMP timeoutを検知しました。回線または対向装置、対象装置のインターフェース異常が疑われるため、インターフェース状態、BGP状態、監視経路を確認します。"
}
この例では、LLM に自動復旧や最終判断を任せていません。
役割は、NMS が集めた生ログを、運用者が読みやすい構造化情報へ変換することです。severity や impact は NMS の画面に表示できますし、ticket_draft は障害チケットの初期本文として使えます。first_actions は NOC 担当者向けの一次対応チェックリストになります。
バックエンド開発との違い
Java/Spring や Node.js、FastAPI で通常の業務 API を作るときは、入力と出力の仕様をかなり明確に決めます。
リクエスト DTO があり、バリデーションがあり、DB のスキーマがあり、レスポンスの型があります。バグはもちろん起きますが、プログラムは基本的に決めた通りに動きます。
LLM は少し違います。
同じ質問でも、プロンプトや temperature、文脈、モデルによって出力が変わります。メッセージ履歴をどこまで渡すかで回答が変わります。長いログを全部入れればよいわけでもありません。出力トークンを制限すれば、回答が途中で切れることもあります。
この性質は、最初は少し扱いづらく感じました。
でも、見方を変えると、LLM は「決められた処理だけをする関数」ではなく、「曖昧な情報を読み、整理し、仮説を出す部品」だと言えます。
NMS の世界には、この曖昧さがたくさんあります。
同じ Interface Down でも、物理障害、設定変更、対向装置の問題、監視経路の問題、単なる一時的な flap など、背景はさまざまです。ログだけでは判断しきれないことも多い。過去のチケット、構成情報、メンテナンス予定、監視除外設定など、周辺情報を合わせて読む必要があります。
だからこそ、LLM をうまく使えれば、ネットワーク運用との相性は悪くないのではないかと思いました。
業務で使うなら、どこから始めるか
もし NMS の現場で LLM 活用を始めるなら、私はいきなり自動復旧や完全自律型 Agent から始めるべきではないと思っています。
最初の一歩としては、次のような用途が現実的です。
- SNMP Trap や syslog の短い要約
- 複数アラートを一つの障害候補としてまとめる
- 障害チケットの初期説明文を生成する
- 過去チケットに似た表現へ整える
- 一次対応チェックリストを作る
- 運用者向けと顧客向けで説明文を出し分ける
特にチケット要約は、既存業務に組み込みやすい領域です。
障害発生時、担当者はログを確認し、影響範囲を見て、チケットに状況を書きます。この文章作成は必要ですが、毎回ゼロから書くのは負担です。LLM が下書きを作り、人間が確認して修正する形なら、導入のハードルは比較的低いはずです。
また、出力を JSON にしておけば、NMS 側で severity や impact だけを取り出して表示することもできます。将来的には、CMDB、チケットシステム、監視メトリクス、過去障害ナレッジとつなげる余地もあります。
この連載でやりたいこと
この連載では、LLM ブートキャンプで学んだ内容を、単なる授業メモとしてではなく、NMS 開発者の視点で整理していきます。
OpenAI API、プロンプト、JSON 出力、トークン、Embedding、RAG、Tool Calling、LangGraph、文書処理、マルチモーダル、GraphRAG。
どれも単体で見ると技術トピックですが、私の関心は一貫しています。
AI でネットワーク運用をどこまで楽にできるのか。
障害対応の現場で、人間が本当に見るべき情報に早くたどり着くにはどうすればよいのか。
LLM を「すごいチャット」として終わらせず、既存の業務システムにどう組み込めるのか。
まだ試行錯誤の途中ですが、だからこそ現場開発者として書けることがあると思っています。
まとめ
LLM ブートキャンプを始めた理由は、AI の流行に乗りたかったからではありません。
NMS の現場で長く感じていた「ログはあるのに、状況理解に時間がかかる」という問題に対して、LLM が何かしらの補助線になるのではないかと思ったからです。
1週目に学んだ OpenAI API、.env による API Key 管理、messages の構造、JSON 出力の考え方は、どれも小さな基礎に見えます。
しかし実務システムに LLM を組み込むなら、その小さな基礎こそが出発点になります。
次回は、OpenAI API を使って最初の AI プログラムを作りながら、障害ログを JSON 形式で要約する小さな例をもう少し具体的に試してみます。
