判断できるAIの最小構成 — Light DTM Starter Kit公開

Introduction

AIは、もう十分に賢くなっています。

分類できる。
予測できる。
文章も生成できる。

それでも現場では、

「結局、判断は人間がやっている」

という状態が変わりません。

理由はシンプルです。

AIが出しているのは、あくまで**Signal(判断材料)**であり、
現場で本当に必要なのは、**Decision(意思決定)**だからです。

たとえば問い合わせ対応でAIは、

  • 問い合わせを分類する
  • 緊急度を推定する
  • 回答候補を生成する

ことはできます。

しかし実際の運用では、その先にある

  • 自動返信してよいのか
  • 人に渡すべきか
  • いったん保留すべきか
  • 上位キューにエスカレーションすべきか

という判断が必要です。

ここが構造として存在していないために、

  • 同じAIでも結果がばらつく
  • 担当者ごとに判断が変わる
  • なぜその判断になったのか追えない
  • 再現や改善ができない

という問題が起きます。

この問題に対する最小のアプローチが、
SignalとDecisionを分離することです。

今回公開した Light DTM Starter Kit は、
この考え方を、まずは小さく・実際に動かせる形にしたものです。
README上でも、このキットは「問い合わせをSignal抽出→YAMLルール評価→構造化されたDecision→Trace記録」という流れで動く、最小で実行可能な意思決定パイプラインとして整理されています。

👉 GitHub
https://github.com/masao-watanabe-ai/light-dtm-starter-kit-cs

このStarter Kitで何ができるのか

このStarter Kitは、カスタマーサポート問い合わせを対象にした、最小の意思決定パイプラインです。

入力された問い合わせに対して、システムは次の流れで処理を行います。

Event(問い合わせ)
Preprocess(前処理)
Signal(緊急度・信頼度・リスクフラグ抽出)
Decision(YAMLルールによる判断)
Human(必要時のみ人間対応)
Log(Trace記録)

READMEでも、この流れは次のような構成として説明されています。
問い合わせ文とメタデータを受け取り、Signalとして urgency / confidence / risk_flags を生成し、それを decision_rules.yaml と照合して、route / action / decision_state を返し、さらに JSONL と runごとのJSONスナップショットとして記録します。

この構造のポイントは明確です。

  • AIはSignalを作る
  • Decisionはルールとして分離する
  • Human介入は必要なときだけ入れる
  • 全体をTraceとして残す

つまり、AIをそのまま判断者にするのではなく、
AIの上に意思決定構造を載せるための最小実装です。

Signal ≠ Decision を最小構成で実装する

このStarter Kitでは、問い合わせ本文そのものに対して直接判断を下すのではなく、
まず問い合わせから Signal を抽出します。

READMEにある通り、Signal層は主に以下を出力します。

  • urgency:緊急度
  • confidence:信号の確からしさ
  • risk_flags:complaint / legal / pii / system_error / critical / security など

その後、このSignalに対してYAMLルールを適用し、Decisionを作ります。
ここで返されるDecisionは、たとえば次の3つの軸を持ちます。

  • route:どこに回すか
    • auto
    • human
    • hold
  • action:何をするか
    • reply
    • assign_queue
    • escalate
    • none
  • decision_state:状態は何か
    • completed
    • requires_human
    • waiting

この分離によって、

  • 生テキストではなく、数値やフラグで判断できる
  • ルールが読みやすくなる
  • Signal抽出だけ後でLLMに差し替えられる
  • どのSignalがどのDecisionを生んだか追跡できる

という設計になります。

Dockerでの立ち上げ手順

ここからは、実際にこのStarter Kitをどう使うのかを具体的に見ていきます。

READMEでは、ローカル起動とDocker起動の両方が用意されていますが、
まず試すなら Docker起動 が一番簡単です。

1. リポジトリを取得する

git clone https://github.com/masao-watanabe-ai/light-dtm-starter-kit-cs.git
cd light-dtm-starter-kit-cs

2. 必要なら .env を作成する

READMEでは .env.example.env にコピーする形になっています。
すべての変数にはデフォルト値があるため、最初はそのままでも動きます。

cp .env.example .env

主な設定項目は次の通りです。

  • LLM_ENABLED
  • DECISION_MODE
  • TRACE_MODE
  • TRACE_STORE_PATH
  • OPENAI_API_KEY
  • ORCHESTRATOR_ENDPOINT
  • LEDGER_ENDPOINT

最初に試すだけであれば、基本的には以下のイメージです。

  • Signal抽出:まずはヒューリスティックで動かす
  • Decision:ローカルルールで動かす
  • Trace:ファイル保存で動かす

つまり、

  • LLM_ENABLED=false でもよい
  • DECISION_MODE=local
  • TRACE_MODE=file

という最小構成で問題ありません。

3. Dockerで起動する

docker compose up –build

起動後、READMEでは以下のURLが案内されています。

  • アプリ本体: http://localhost:8000
  • Swagger UI: http://localhost:8000/docs
  • デモ画面: http://localhost:8000/demo

また、Traceはホスト側の ./traces/ に書き出されます。

まず何を見るべきか

起動したら、最初に確認すべき場所は3つです。

1. ヘルスチェック

GET /health

レスポンスは以下です。

{“status”: “ok”}

これが返れば、まずサーバ自体は立ち上がっています。

2. デモ画面

ブラウザで以下を開きます。

http://localhost:8000/demo

READMEによると、この画面では以下が操作できます。

  • 問い合わせ本文の入力
  • priority の指定
  • complaint / legal / pii などの明示的な risk flag の指定
  • Run Decision ボタンでの実行

結果画面には、

  • route
  • action
  • decision state
  • applied rule
  • reason
  • confidence
  • risk flags
  • signal ID
  • trace ID

が表示されます。

3. Swagger UI

APIベースで確認したい場合は、以下が便利です。

http://localhost:8000/docs

ここから POST /api/decision/run を直接試すことができます。

実際の使い方

このStarter Kitの一番わかりやすい試し方は、
1件の問い合わせを入れて、Signal→Decision→Trace がどう流れるかを見ることです。

入力例

たとえば、READMEには次のようなリクエスト例があります。

{
 "id": "inq-001",
 "text": "Our payment system stopped responding 10 minutes ago.",
 "category": "technical",
 "priority": 7
}
これを POST /api/decision/run に送ると、システムは次のことを行います。
  1. 問い合わせを前処理する
  2. urgency / confidence / risk_flags を作る
  3. YAMLルールを上から順に評価する
  4. 最初に一致したルールでDecisionを作る
  5. その結果をTraceとして保存する

READMEの例では、レスポンスは次のようになります。

{
 "inquiry_id": "inq-001",
 "route": "auto",
 "action": "escalate",
 "decision_state": "completed",
 "applied_rule": "critical_risk_escalate",
 "reason": "High-risk flags detected (system_error, critical, or security). Automatically forwarded to an upstream high-priority queue — no human agent assigned.",
 "confidence": 0.95,
 "risk_flags": ["system_error"],
 "signal_id": "3f8a1c2d-...",
 "trace_id": "7b4e9a0f-...",
 "executed_at": "2026-04-17T04:32:26.478738"
}
ここで重要なのは、

単に「AIが危険そうと言った」ではなく、

  • どのSignalが出たのか
  • どのルールに当たったのか
  • なぜそのDecisionになったのか
  • その結果どこへ回ったのか

が、構造として見えることです。

ルールはどこで決まるのか

このStarter Kitでは、Decisionはコードに埋め込まれているのではなく、
app/rules/decision_rules.yaml に書かれたルールで決まります。

READMEの例では、たとえば次のようなルールがあります。

rules:
 - name: critical_risk_escalate
 reason: >-
 High-risk flags detected. Forwarded to upstream queue automatically.
 condition:
 risk_flags_any: ["system_error", "critical", "security"]
 route: auto
 action: escalate
 decision_state: completed
 base_confidence: 0.95
つまり、
  • system_error
  • critical
  • security

のいずれかが含まれていたら、
人手ではなく、まず自動的に上位処理キューへ回す、という判断です。

READMEには、条件として使えるキーも整理されています。

  • urgency_gte
  • confidence_gte
  • confidence_lt
  • risk_flags_any
  • risk_flags_all

ここが非常に大きなポイントです。

Signalの抽出とDecisionのルールを分離しているため、
判断基準をコード改修なしで読みやすく調整できる
のです。

実際に試すときのおすすめ手順

このStarter Kitは、単に起動するだけでなく、
少しずつケースを変えて結果を見ると設計意図がよくわかります。

手順1:通常問い合わせを入れる

たとえば一般的な問い合わせ文を入れてみる。
ここでは高リスクフラグが立たず、優先度も低いケースを試します。

見るべきポイントは、

  • auto になるか
  • reply になるか
  • completed で終わるか

です。

手順2:明示的に高リスクにする

次に、priority を上げるか、あるいは risk flag を付けて試します。

たとえば、

  • system_error
  • critical
  • security

を付けると、
高リスクルールに当たりやすくなります。
その結果、

  • route が変わる
  • action が escalate になる
  • applied_rule が変わる

ことを確認できます。

手順3:曖昧な問い合わせを入れる

次に、短文や曖昧な問い合わせを入れてみる。
このとき confidence が低くなれば、
hold や human へのルーティングが起こる可能性があります。

ここで見たいのは、

  • AIの出力が曖昧なとき
  • そのまま自動実行せず
  • 保留や人間確認に回す

という設計が入っていることです。

手順4:Traceファイルを見る

実行後、traces/ フォルダを確認します。
READMEによると、2種類の記録が残ります。

  • traces/traces.jsonl
  • traces/exports/{inquiry_id}_{timestamp}.json

traces.jsonl は全実行の追記ログ、
exports は各runごとの完全スナップショットです。

ここを見ると、

  • どの問い合わせが
  • どのSignalになり
  • どのルールに一致し
  • どのDecisionとして実行されたか

が追えるため、
まさに Decision Trace の最小形になっています。

Before / After

このStarter Kitで変わるのは、
AIの精度そのものではありません。

変わるのは、AIの使い方です。

Before

  • AIの出力をそのまま使う
  • 判断基準が暗黙的
  • 担当者依存になる
  • なぜそうなったのか説明しにくい
  • 改善したくても、どこを直せばよいかわからない

After

  • AIはSignalとして扱う
  • Decisionはルールとして明示する
  • Human介入点を設計できる
  • 判断の経路をTraceで追える
  • ルールやSignal抽出を個別に改善できる

つまり、

AIを出力ツールとして使う状態から、
意思決定システムとして扱う状態へ移す

ための最小構成が、Light DTMです。

このStarter Kitが重要なのは「最小で動く」こと

DTMは本来、もっと大きく拡張できます。

たとえば、

  • Ontology
  • Multi-Agent
  • Behavior Tree
  • Orchestrator
  • Ledger

といった構成に広げることもできます。

ただし、多くの現場では、最初からそこまでは導入できません。

そのため重要なのは、

最小構成でまず動かし、
SignalとDecisionの分離だけでも現場に入れること

です。

このStarter Kitも、READMEで明示されている通り、各層を後から差し替えられる設計になっています。

  • SignalService → LLMベース抽出へ差し替え可能
  • LocalExecutor → OrchestratorAdapter へ差し替え可能
  • FileTraceStore → LedgerAdapter へ差し替え可能

つまり、最初は小さく始めながら、
将来的にはそのまま本格的な意思決定インフラへ育てていけます。

Project Layout から見える設計思想

このリポジトリの構成も、Light DTMの考え方をそのまま反映しています。
READMEではプロジェクト構成が整理されています。

特に重要なのは次の分離です。

  • models/
    Inquiry / Signal / Decision / Trace の構造定義
  • services/
    preprocess / signal extraction / rule loader / pipeline orchestration
  • integrations/
    executor や trace store の差し替えポイント
  • rules/decision_rules.yaml
    Decisionロジックの外出し

この形にしておくことで、
「何を入力として、何をSignalとして、何をDecisionとして、どこに記録するのか」が、コード構成上も明確になります。

Conclusion

AIは、もう十分に賢い。

それでも現場で自動化が止まるのは、
精度が足りないからではありません。

判断の構造が存在していないからです。

Light DTM Starter Kit は、

  • Eventを受け取り
  • Signalを抽出し
  • Decisionをルールで明示し
  • 必要時のみHumanを介在させ
  • 全体をTraceとして記録する

という最小構成を、Dockerで今すぐ試せる形にしたものです。

最初から大きなシステムを作る必要はありません。

まずは小さく、

AIの上にDecisionを置く。

そこから、
再現可能で改善可能な意思決定システムは始まります。

モバイルバージョンを終了
タイトルとURLをコピーしました