概要
「3号機の主軸温度はいま何度か」「この搬送ロボットを出荷口へ回して」。こうした指示を自然言語で出せるようになると、設備の状態確認や段取りの手間は大きく減ります。PLCや設備のデータをLLMから扱う仕組み自体は、OPC UAやModbusといった既存の産業プロトコルとMCP(Model Context Protocol)を組み合わせれば実現できます。
一方で、工場設備は業務システムと違い、誤った書き込みが物理的な動作になって現れます。表計算の値を書き間違えるのとは影響の大きさが違います。本記事では、設備とLLMをつなぐときに分けて考えるべき点として、読み取りと書き込みの違い、書き込みに承認が必要な理由、非常停止をLLMの経路から切り離す理由、そしてMCP経由の操作で発生する往復とトークン消費を整理します。
工場で使われる主な産業プロトコル
まず、設備との接続に使われる代表的なプロトコルを整理します。LLMから見るとどれも「値を読む・値を書く」操作ですが、アドレスの指定方法やデータ型の扱いがそれぞれ異なります。
| プロトコル | 主な用途 | 値の指定方法 | 注意点 |
|---|---|---|---|
| OPC UA | 設備・SCADAの標準的な情報モデル | ノードID(ns=2;s=Temperature など) | セキュリティポリシーを使う場合は証明書と秘密鍵が必要 |
| Modbus TCP | 計測器・インバータ・小型PLC | 種別(保持レジスタ・入力レジスタ・コイル・入力接点)とアドレス | 書けるのは保持レジスタとコイルのみ。1回の要求で読めるレジスタ数に上限がある |
| MQTT | センサーやゲートウェイからのイベント配信 | トピック(ワイルドカード可) | 購読は「一定時間受信して終わる」形にする。QoSとretainの扱いを決める |
| SLMP(MCプロトコル) | 三菱電機製PLC | デバイス(D100、M0 など) | 32ビット値は下位ワードが先頭になる機種が多い |
| FINS | オムロン製PLC | メモリ領域(DM・CIO・W・H・A)とアドレス | UDPでの通信が一般的。応答の照合が必要 |
32ビット以上の数値はレジスタ2つ以上にまたがるため、バイト順とワード順が機器によって異なります。ここを取り違えると、温度が「1億度」のような値で読めてしまいます。LLMはその値をもっともらしく説明してしまうことがあるので、型と並び順は接続設定の段階で確定させ、LLMには推測させないようにします。
OPC UAのように設備側がノードの一覧を返せるプロトコルでは、まずノードを辿って一覧(ノードID・表示名・データ型・書き込み可否)を取得し、その結果を読み取り対象として渡す流れにすると、LLMがアドレスを推測する余地がなくなります。
読み取りと書き込みは別のものとして設計する
読み取り:失敗しても全体を止めない
読み取りは、複数の点を1回で取得して1行のスナップショットにするか、点ごとに1行にする形が扱いやすいです。読み取り時刻を列として付けておくと、LLMが「いつの値か」を取り違えません。
ある点の読み取りに失敗しても、他の点は返し、失敗した点は値を空にしてエラーを添えます。全体を失敗にすると、LLMは同じ呼び出しを繰り返しがちです。
書き込み:曖昧な値は書かない
書き込みでは、値の変換を厳密にします。LLMが生成する値は、"ON"、1、"true"、"有効" のように表記が揺れるためです。
- 真偽値は
true/false、1/0、on/off、yes/noだけを受け付け、それ以外は書かずにエラーにする - 整数型の範囲外の値はエラーにする。整数型に小数が来た場合は切り捨て、警告を返す
- レジスタに書く文字列はASCIIに限り、長さの上限を超えたらエラーにする
def to_coil_value(value) -> bool: """曖昧な表記を推測で丸めず、受け付ける表記を限定する""" accepted = {"true": True, "1": True, "on": True, "yes": True, "false": False, "0": False, "off": False, "no": False} key = str(value).strip().lower() if key not in accepted: raise ValueError(f"cannot write {value!r} as a boolean") return accepted[key]
もう1つ重要なのは、書き込みは冪等(何度実行しても結果が同じ)とは限らないという点です。起動トリガーのビットやカウンタへの書き込みは、2回送れば2回動作します。通信エラー時の自動リトライは読み取りだけに限定し、書き込みでは無効にします。動作確認のためのテスト実行でも、副作用がある処理は明示的に許可したときだけ走らせるようにします。
なぜ書き込みに承認が必要か
書き込みに人の承認を挟むべき理由は、LLMの性能の問題だけではありません。
- 指示の解釈がずれる:「設定温度を5上げて」が摂氏なのか、どの号機なのか、現在値からの差なのか。人なら確認する曖昧さを、LLMはそのまま解釈して実行することがあります
- 入力データに指示が紛れ込む:設備のコメント欄や読み込んだ文書の中に命令文があると、LLMがそれに従ってしまう可能性があります(プロンプトインジェクション)
- 出力は確率的に揺れる:同じ指示でも、毎回同じツールを同じ引数で呼ぶとは限りません
- 物理的な結果は取り消せない:データベースのように巻き戻すことができません
承認画面には「どの接続の、どのアドレスに、どの値を書くか」をそのまま表示し、承認者が実際の操作内容を見て判断できるようにします。また、設備への書き込みは承認の有無にかかわらず、誰が・どの設備に・何件書き、成功したかを監査ログに残します。
DigitalBaseでは、設備との接続ごとに「LLMからの利用を許可」を有効にしない限り、その接続はLLMに見えない仕組みにしています。LLMから設備接続を呼び出す操作は、読み取りも含めて最も強い権限区分として扱うため、標準の承認モードでは実行前に必ず確認が入ります。承認する人がいない外部連携の経路では、キーの権限上限を読み取りや書き込みまでに絞ると、設備を呼ぶツールそのものが一覧に出なくなります。
非常停止をLLMの経路に載せてはいけない理由
搬送ロボットや設備を操作できるようになると、「止めて」もLLMで扱いたくなります。しかし、非常停止はLLMの経路から完全に切り離すべきです。
LLMを経由した操作には、次のような処理が順番に挟まります。
[ 人の発話・入力 ] ↓ 推論サーバーでの生成(GPUの混雑状況で待ち時間が変わる) [ ツールの選択と引数の生成 ] ↓ 権限判定・承認待ち [ ツール呼び出し ] ↓ ネットワーク・ゲートウェイ・設備側の応答 [ 停止 ]
この経路のどこにも、応答時間の保証がありません。推論サーバーが高負荷であれば生成は遅れ、停止していれば応答そのものが返りません。LLMが「止めて」を一時停止と解釈するか、別の設備を指していると解釈するかも確率的です。承認待ちが入ればさらに遅れます。
非常停止の役割は、どの状態からでも、決まった時間内に、確実に危険を取り除くことです。そのため、非常停止ボタンや安全PLC、ロボット自身の安全センサーといった、制御系とは独立した安全回路に任せます(機械の非常停止機能の設計原則はISO 13850、停止カテゴリはIEC 60204-1で定められています)。
| 操作 | LLM経由 | 推奨する扱い |
|---|---|---|
| 状態・アラームの読み取り | 可 | 読み取り区分として承認なしで提供 |
| 設定値の変更・移動指示 | 条件付き | 承認を経て実行。外部連携の経路では提示しない |
| 実行中の動作の取り消し | 補助的に可 | 通常運転の操作として扱う。安全機能とはみなさない |
| 非常停止 | 不可 | 独立した安全回路で実現する。LLMには非常停止中かどうかの読み取りだけを許す |
設備側のMCPサーバーに「停止」のツールを用意することはありますが、それは通常運転の中で動作を取り消すための便利機能です。安全機能の代わりにはなりません。
MCPでは1つの指示が何往復にもなる
搬送ロボットの例
工場内の搬送ロボットをMCPサーバーとして公開し、「状態の取得」「登録地点の一覧」「棚の一覧」「地点への移動」「棚の搬送」「充電場所へ戻る」といったツールを持たせたとします。ここに「棚2を出荷口へ運んで、終わったら充電に戻して」と指示すると、LLMは次のように何度もツールを呼びます。
- 登録地点の一覧を取得し、「出荷口」が存在するか確かめる
- 棚の一覧を取得し、「棚2」を特定する
- 状態を取得し、バッテリー残量や実行中の動作を確かめる
- 棚の搬送を指示する(承認待ち)
- 完了を待ち、状態を再取得する
- 充電場所へ戻す指示を出す(承認待ち)
- 最終状態を取得して報告する
自然言語では1文の指示でも、LLMとツールの往復は7回前後になります。
トークンは往復ごとに積み上がる
この往復で問題になるのがトークン消費です。LLMは状態を持たないため、ツールを呼んで結果を受け取るたびに、システムプロンプト、すべてのツール定義、それまでの会話とツール結果をまとめて再送します。システムプロンプトとツール定義の合計を 、1往復で増える会話とツール結果を とすると、 往復での入力トークンの合計はおおよそ次のようになります。
ツール定義が多いほど が大きくなり、ツールが大きな結果を返すほど が大きくなります。往復回数 に対して、後半の項は2乗で増えます。設備の一覧や長い履歴をそのまま返すツールが1つあるだけで、以降の往復すべてにその分のトークンが上乗せされます。
往復を減らす設計
往復とトークンを抑えるには、次の方法が有効です。
- 決まった手順はワークフローにする:巡回ルートや段取り替えの手順のように順序が決まっている処理は、LLMに毎回組み立てさせず、ワークフローのステップとして固定します。LLMは「どの手順を実行するか」だけを選びます
- 提示するツールを絞る:その業務で使うツールだけを一覧に出し、 を小さくします
- ツールの結果を小さくする:返す行数や文字数に上限を設け、必要な列だけを返します
- 往復回数に上限を設ける:1回の応答でツールを呼び直す回数に上限を設け、同じツールを同じ引数で繰り返し呼ぶ場合は打ち切ります。小さいモデルが同じ呼び出しを繰り返して止まらなくなるのを防ぐためです
DigitalBaseでは、決まった走行順序のような処理を、ワークフローのステップからMCPツールを行ごとに呼び出す形で組めるようにしています。会話側には、ツールを呼び直す回数の上限と、同じ引数での繰り返し呼び出しを打ち切る仕組みを持たせています。
まとめ
工場設備とLLMをつなぐときは、LLMに任せる範囲と、任せない範囲を最初に線引きすることが要点です。
- 読み取り:型と並び順を接続設定で確定させ、一部の失敗で全体を止めない
- 書き込み:曖昧な値は書かず、自動リトライをせず、承認を経て実行し、記録を残す
- 非常停止:LLMの経路に載せず、独立した安全回路で実現する
- 往復とトークン:決まった手順はワークフローにし、ツールと結果を絞り、往復回数に上限を設ける
この線引きをしておけば、状態確認や段取りの指示といった、LLMが得意な部分の効果を安全に引き出せます。