はじめに
2026年8月29日に開催された Machine Learning 15minutes! で、「LLMアプリ、雰囲気で運用してませんか? 〜LLMOpsの現在地〜」というタイトルで15分お話ししました。
2026年4月に共著で『MLflowで実践するLLMOps』を出したのですが、この領域は書籍の脱稿から登壇までの数ヶ月だけでもかなり動いています。そこで今回は、書籍で整理した骨格を土台にしつつ、その後に何が変わったのかを中心に構成しました。
LTの内容と、当日デモに使ったDatabricks Free Editionでのトレーシングのコードも含めて書いていきます。
「雰囲気で運用」というテーマにした理由
タイトルを決めるとき、最初は書籍名そのままにしようかと考えました。ただ、15分で話せるのは書籍の一部だけですし、そもそもMLflowという特定ツール名をタイトルに置くと、他のツールを使っている方や、まだ観測基盤を選定していない方には「自分向けではない」と映ってしまいます。
そこで主役を「LLMアプリ運用の課題」に置き、MLflowはそれを具体的に見せる実装例という位置づけにしました。
「雰囲気で運用」という言葉を選んだのは、多くの人に心当たりがあると思ったからです。実際、LLMアプリの運用でよく聞くのはこのあたりです。
- プロンプトを変えたら良くなった "気がする"。でも何がどれだけ良くなったのか、数字で答えられない
- エージェントが中で何をしているのか謎。ツール呼び出しが何回走ったのか、どこで時間を食っているのかわからない
- コストが気づいたら増えている。請求書を見て初めて気づく
なぜ「雰囲気」になってしまうのか
ここで強調したかったのは、これが担当者の頑張りや注意力の問題ではないということです。LLMアプリには、勘に頼らざるを得なくなる構造的な理由があります。
第一に、出力が非決定的です。同じ入力でも毎回答えが変わるので、1回試して「動いた」は何の保証にもなりません。第二に、品質が多次元です。正確さ・網羅性・安全性・トーン・コスト・レイテンシと、従来の機械学習のように単一の "精度" では測れません。第三に、変更の影響範囲が読めません。プロンプトの一語、モデルのバージョン、RAGの1ドキュメント。小さな変更が思わぬ場所を壊します。
仕組みがないと勘に頼るしかない。だからこそLLMOpsが必要になる、という流れで本題に入りました。
LLMOpsの4本柱
LLMOpsを一言でいうと、雰囲気を「計測と根拠」に変える営みです。書籍でも骨格にしている整理ですが、大きく4つの柱で捉えています。
- トレーシング: アプリ・エージェントの全ステップを記録し、挙動を可視化する
- 評価: 出力品質を定量化し、変更の良し悪しを数字で判断する
- プロンプト管理: プロンプトをバージョン管理し、変更を追跡可能にする
- 監視: 本番の品質・コスト・レイテンシを継続的に見張る
従来のMLOpsと何が違うのか
MLOpsを実践してきた方ほど、この違いを意識しておく価値があると思っています。
| 従来のMLOps | LLMOps | |
|---|---|---|
| 評価指標 | 精度という単一指標で評価できる | 品質・安全性・コスト・速度の多目標 |
| 挙動の安定性 | モデルは学習済みで挙動が固定 | プロンプト・RAG・ツールで挙動が変わる |
| 品質保証 | テストセットで品質を事前保証 | 事前保証だけでは足りず、本番の観測が必須 |
| デプロイ後 | 劣化は主にデータドリフト | モデル更新・プロンプト変更で挙動が動き続ける |
特に「事前保証だけでは足りない」という点が本質だと考えています。テストを通ったから安心、ではなく、本番で何が起きているかを見続けないと品質を語れないのがLLMアプリです。
2026年、LLMOpsの景色はこの1年で変わった
ここからが今回の本編です。3つのトレンドに絞ってお話ししました。
トレンド1: トレーシングは「業界標準」の時代へ
一番大きな変化は、トレース形式がOpenTelemetryのGenAIセマンティック規約に収斂しつつあることだと思っています。
- v1.39でMCPツール呼び出しのセマンティック規約が導入され、エージェント側とMCPサーバー側のトレースが接続できるようになった
- v1.41で
invoke_agentがCLIENTとINTERNALに分割され、リモート呼び出しと内部フレームワーク実行が区別されるようになった - OSS・商用ツールともにネイティブ対応が進んでいる
MLflowも3.11でOpenTelemetry GenAI対応が入っています。
これが実務的に何を意味するか。トレース形式のベンダーロックインから解放されるということです。今トレーシングを入れておけば、後でツールを乗り換えても資産が生きます。エージェントの推論ステップやMCPツール呼び出しまで標準の語彙で記録できますし、APMなど既存の可観測性基盤とLLMトレースが同じ土俵に乗ってきます。
「まだツール選定が終わっていないから様子見」という判断をよく聞くのですが、標準化が進んだ今は、様子見のコストの方が高くなってきたと感じています。
トレンド2: 評価の民主化 — 勘から数字へ
評価まわりも、この1年で「専門チームの仕事」から「全員の日常」に近づきました。
MLflow 3.9ではJudge Builder UIが入り、LLM-as-a-JudgeをコードなしでUIから構築・改善できるようになりました。同じく3.9のMemAlignは、人間のフィードバックからJudgeを自動整合させる仕組みです。「Judge自体が信用できないのでは」という、LLM-as-a-Judgeに必ず向けられる疑問への回答になっています。
個人的に一番重要だと思っているのはマルチターン評価です。3.7から段階的に強化されていますが、単発の出力評価から会話・セッション全体の評価へと軸が移っています。エージェントの品質保証はこちらが本丸で、1回の応答が良かったかどうかではなく、一連のやり取りでユーザーの目的が達成されたかを見る必要があります。
トレンド3: 監視対象は「アプリ」から「エージェント」へ
3つ目は、可観測性の守備範囲そのものが広がっているという話です。
コストの可視化は3.10でトレース単位のコスト追跡が入り、ゲートウェイでの予算管理と合わせて「気づいたら増えている」を防げるようになりました。3.9のエージェント性能ダッシュボード、3.11の自動問題検出のように、監視の自動化も進んでいます。ゲートウェイも単なるルーティング係から、ガードレールを効かせる統制点へと役割が変わってきました。
そして2026年らしいと感じたのが、Claude CodeやCodexといったコーディングエージェントの行動もトレース対象になったことです。3.12から3.13にかけて対応が進んでいます。LLMOpsの守備範囲が、プロダクトのLLMアプリだけでなく開発現場のエージェントにまで拡大したことになります。
Databricks Free Editionでトレースを見せる
LTでは、スライドで語るだけでなく実際のトレース画面をお見せしました。Databricks Free Editionでもオープンモデルのサービングエンドポイントが使えるので、無料で試せます。
デモ用に、RAG風の検索とツール呼び出しを含むサポートエージェントを用意しました。以下、そのままノートブックで実行できる形で載せておきます。
セットアップ
まずはライブラリのインストールです。
%pip install -U mlflow openai databricks-sdk
dbutils.library.restartPython()
エクスペリメントの設定と、OpenAI互換クライアントの取得を行います。mlflow.openai.autolog() を呼んでおくと、LLM呼び出しが自動でトレースされ、トークン数まで記録されます。
import mlflow
from databricks.sdk import WorkspaceClient
MODEL = "databricks-gpt-oss-120b" # Servingタブのエンドポイント名に合わせる
w = WorkspaceClient()
user_name = w.current_user.me().user_name
mlflow.set_experiment(f"/Users/{user_name}/llmops-lt-demo")
openai_client = w.serving_endpoints.get_open_ai_client()
mlflow.openai.autolog()
エンドポイント名はワークスペースのServingタブで確認してください。Free Editionでも gpt-oss-120b や meta-llama-3-3-70b-instruct といったオープンモデルが並んでいるはずです。
エージェントの実装
検索とツール呼び出しは、@mlflow.trace デコレータにスパンタイプを指定するだけでトレースに乗ります。ここではデモ用に、社内ドキュメントの簡易検索と注文DBの照会を用意しました。
DOCS = [
{"id": "doc-001", "title": "返品ポリシー", "text": "未開封の商品は到着後30日以内であれば返品可能です。"},
{"id": "doc-002", "title": "配送について", "text": "通常配送は3-5営業日、お急ぎ便は翌日にお届けします。"},
{"id": "doc-003", "title": "支払い方法", "text": "クレジットカード、銀行振込、コンビニ払いに対応しています。"},
{"id": "doc-004", "title": "保証について", "text": "全製品にメーカー保証1年が付属します。延長保証は購入から30日以内に申し込み可能です。"},
]
ORDER_DB = {
"A123": {"status": "配送中", "eta": "2026-08-27", "carrier": "ヤマト運輸"},
"B456": {"status": "出荷準備中", "eta": "2026-08-29", "carrier": "未定"},
}
@mlflow.trace(span_type="RETRIEVER")
def retrieve_documents(question: str) -> list[dict]:
hits = [d for d in DOCS if any(kw in question for kw in d["title"])]
return hits or DOCS[:2]
@mlflow.trace(span_type="TOOL")
def lookup_order_status(order_id: str) -> dict:
return ORDER_DB.get(order_id, {"status": "注文が見つかりません"})
エージェント本体です。方針立案と最終回答で2回LLMを呼んでいます。
def call_llm(messages: list[dict]) -> str:
resp = openai_client.chat.completions.create(model=MODEL, messages=messages)
return resp.choices[0].message.content
@mlflow.trace(span_type="AGENT")
def support_agent(question: str) -> str:
docs = retrieve_documents(question)
context = "\n".join(f"[{d['id']}] {d['title']}: {d['text']}" for d in docs)
plan = call_llm([
{"role": "system", "content": "質問に注文番号 (英字1文字+数字3桁) が含まれる場合は「LOOKUP:<注文番号>」とだけ答えてください。それ以外は「ANSWER」とだけ答えてください。"},
{"role": "user", "content": question},
])
tool_result = ""
if "LOOKUP:" in plan:
order_id = plan.split("LOOKUP:")[1].strip()[:4]
tool_result = f"\n注文情報: {lookup_order_status(order_id)}"
return call_llm([
{"role": "system", "content": f"以下の情報のみに基づいて日本語で簡潔に回答してください。\n{context}{tool_result}"},
{"role": "user", "content": question},
])
あとは質問を投げるだけです。
questions = [
"注文A123はいつ届きますか?",
"開封してしまった商品は返品できますか?",
"保証期間を延長したいのですが",
]
for q in questions:
print(support_agent(q))
トレース画面で何が見えるか
実行後、エクスペリメントの「Traces」タブを開くと、リクエストごとのトレースが並びます。1件開くと、support_agent の下に retrieve_documents と2回のLLM呼び出しがネストしたウォーターフォールが表示されます。
デモで強調したのはこの3点です。
まず、ステップ単位で分解されていること。全体で1.91秒かかったうち、検索が0.24ミリ秒、1回目のLLM呼び出しが1.13秒、という内訳が一目でわかります。遅いのはどこか、失敗したのはどのステップかを推測しなくて済みます。
次に、トークン数が記録されていること。この例では552トークンと表示されています。リクエスト1件ごとの消費が見えるので、コストの議論を平均値ではなく実データでできます。
そして、スパンのグラフ表示でエージェントの構造が見えること。検索・LLM・ツールの呼び出し関係が図として出るので、「このエージェントは実際どう動いているのか」をチームで共有するときに便利です。
デモの小ネタとして、当日は注文番号を含む質問のトレースを開くようにしました。RETRIEVER・LLM・TOOL・LLMと4種類のスパンが揃うので、エージェントらしい構造が一番きれいに見えます。
明日からやる3つのこと
LTの締めとして、持ち帰ってもらうアクションを3つ挙げました。
- まずトレーシングを入れる。自動計装なら数行で始められます。「見える」だけで議論の質が変わりますし、標準規約に対応したツールを選べば資産は無駄になりません
- 評価データセットを5件作る。完璧な評価基盤は不要です。代表的な入出力5件と「良い回答の条件」を書き出すだけで、変更の良し悪しを語れるようになります
- コストをダッシュボードに出す。トークン消費とコストをチームの見える場所に置く。数字が見えれば、モデル選定やキャッシュの議論が自然に始まります
どれも大がかりな基盤構築を伴わない話です。雰囲気からの脱却は、意外と小さく始められます。
まとめ
LTで話した内容をまとめます。
- LLMアプリが「雰囲気で運用」になるのは担当者の問題ではなく、出力の非決定性・品質の多次元性・変更の影響範囲の読めなさという構造的な理由がある
- LLMOpsはトレーシング・評価・プロンプト管理・監視の4本柱で、雰囲気を計測と根拠に変える営み
- トレース形式はOpenTelemetry GenAIセマンティック規約に収斂しつつある。今始めても資産になる
- LLM-as-a-JudgeはUIで構築できるようになり、評価は専門家の特権ではなくなった
- マルチターン評価がエージェント時代の品質保証の本丸
- コーディングエージェントまで監視対象に入り、LLMOpsの守備範囲は開発現場まで拡大した
- Databricks Free Editionのオープンモデルを使えば、トレーシングは無料で試せる
一番伝えたかったのは、「見えれば、直せる。測れれば、良くできる」ということです。LLMアプリの品質改善が難しく感じるのは、そもそも見えていないから打ち手が決められないケースが多いように思います。トレーシングを1つ入れるだけで、チームの会話が「なんとなく良くなった気がする」から「このステップが遅い」に変わります。そこからがLLMOpsの入り口だと考えています。
なお、今回のスライドでも少し触れましたが、現在メタハーネス「Omnigent」に関する書籍を執筆中です。こちらは改訂のスピードを優先して電子版のみでの出版という新しい形に挑戦しています。進捗はまた別途お知らせします。
参考リンク
- MLflow Releases
- LLM Tracing and Agent Observability | MLflow
- Prompt Registry | MLflow
- プロンプトレジストリ | Databricksドキュメント
- Role-Based Access Control (RBAC) | MLflow
- Introducing DeepEval, RAGAS, and Phoenix Judges in MLflow
- Tired of Reviewing Traces? Meet Automatic Issue Detection for Your Agent
- 5 Tips to Get More Out of Your Claude Code with MLflow
- MLflowで実践するLLMOps (技術評論社)




