メインコンテンツへ移動
AIチュートリアル

Jeevesで推論ベースの意思決定APIを構築する

Jeevesのインストール方法、公開済み重みの提供方法、Jev互換の意思決定リクエストの送信方法、Python SDKの統合方法を学びます。このチュートリアルでは、推論制御、レイテンシと性能のトレードオフ、拡散ドラフター、プロジェクトのSFTおよびCISPOトレーニングパイプラインについても解説します。

Jeevesで推論ベースの意思決定APIを構築する

Jeevesとは?

Jeevesプロジェクトのマスコット

Jeevesは、構造化された判断を行う前に推論チェーンを生成するJev形式の分類器です。Qwen3.5-9BにLoRAアダプター、ポインターヘッド、較正済み確率、block-4拡散ドラフターを組み合わせて構築されています。リポジトリには、モデルとドラフターのコード、トレーニングパイプライン、評価ツール、トレーニング用・開発用・テスト用データが含まれています。

このプロジェクトは、自由形式のテキスト生成以上の機能を必要とするアプリケーション向けに設計されています。共有状態と1つ以上の質問を与えると、JeevesはJev互換APIを通じて、構造化された回答と確率を返します。1回のリクエストで複数の質問を処理できます。

主な機能

  • 3種類の判断: 二値のnoul、カテゴリ型のchoice、順序尺度型のscoreの質問。
  • 判断前の推論: モデルは推論チェーンを生成し、その後ポインターヘッドを使って利用可能な選択肢を評価できます。
  • 較正済み出力: 最終的な選択肢の確率には、開発セットで適合させた温度が使用されます。
  • Jev互換API: 既存のJevクライアントから基本リクエスト形式を送信でき、Jeeves固有のオプションで推論を制御できます。
  • Python SDK: 付属のsdk/パッケージは、Jevのtypesafe-sdkのドロップイン置換として使えます。
  • 拡散ドラフティング: block-4ドラフターが推論チェーンの生成を高速化し、Qwen3.5のGated DeltaNetレイヤーに対応します。
  • トレーニングコード: リポジトリには、SFT、CISPO、較正、評価、エクスポート、ドラフター学習の各コンポーネントが含まれています。

貪欲推論を2,560トークンに制限した場合、READMEによると、保留テストセットおよびドメイン外テストセットでの精度は0.889、公開JevBench 231項目全体では0.935です。ただし、MMLUとMMLU-Proでは知識に関する結果がJevを下回るため、ベンチマークへの適合性はタスクによって異なります。

前提条件

Python 3.12とCUDA GPUが必要です。推論実装のFP8カーネルにはHopper GPUが必要です。以下のコマンドはリポジトリのルートから実行してください。

依存関係をインストールする

pip install -r requirements.txt

リリース済みの重みをダウンロードする

Hugging Face CLIを使用して、公開されている9Bチェックポイントとblock-4ドラフターをダウンロードします。

hf download PostHog/jeeves --local-dir jeeves-weights

リリース済みモデルはHugging Faceから入手できます。

APIサーバーを起動する

python -m inference.serve --model jeeves-weights --drafter jeeves-weights/drafter_k4.safetensors --port 8009

これにより、ポート8009でJev互換サービスが起動します。付属のPythonクライアントはデフォルトでhttp://127.0.0.1:8009を使用し、APIキーは不要で、レスポンスを最大120秒待機します。

最初の判断リクエストを送信する

/v1/systemoneエンドポイントは、state、questionsのマップ、任意の推論制御を受け付けます。次のリクエストでは、顧客の問題の担当部署、エスカレーションが必要かどうか、顧客の不満度を判断するようJeevesに依頼しています。

curl -s localhost:8009/v1/systemone \
  -H 'content-type: application/json' \
  -d '{
    "state": "Shoes arrived two weeks late and in the wrong size. Also I see two charges on my card.",
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this?",
        "criteria": {
          "returns": "Exchanges, refunds, wrong or damaged items",
          "shipping": "Delivery status, delays, lost packages",
          "billing": "Charges, invoices, payment problems"
        }
      },
      "escalate": {
        "type": "noul",
        "instructions": "Does this need urgent human attention?"
      },
      "frustration": {
        "type": "score",
        "instructions": "How frustrated is the customer?",
        "criteria": ["Calm", "Frustrated", "Very angry"]
      }
    },
    "options": {"max_think": 512}
  }'

質問の種類を理解する

  • choice: 名前付きの選択肢から選び、選択されたキー、確率、信頼度を返します。
  • noul: はい・いいえ形式の判断を表し、数値のnoul値を返します。
  • score: 順序付けられたラベルのリストを評価し、数値スコア、凡例、確率、信頼度を返します。

レスポンスには、入力・出力・推論のトークン数や合計レイテンシなどの使用量情報も含まれます。同じリクエスト内の質問は並列に推論できます。

PythonからJeevesを使用する

付属SDKをインストールする

pip install ./sdk

型付き質問を作成する

from jeeves_sdk import Choice, Noul, Score, TypeSafeClient

with TypeSafeClient() as client:
    result = client.system_one(
        state="I was charged twice. Please help.",
        questions={
            "billing": Noul(
                instructions="Is this about billing?"
            ),
            "tone": Choice(
                instructions="What is the tone?",
                criteria={"calm": None, "angry": None},
            ),
            "urgency": Score(
                instructions="How urgent is this?",
                criteria=["can wait", "this week", "today"],
            ),
        },
        max_think=768,
        return_reasoning=True,
    )

    print(result.nouls["billing"].noul)
    print(result.choices["tone"].choice)
    print(result.scores["urgency"].score)
    print(result.reasoning["tone"].text)

TypeSafeClientは、返される値を質問の種類ごとにまとめます。return_reasoning=Trueを設定すると、各質問の推論テキストも利用できるようになります。READMEでは、トレーニング中に言語の一貫性に対する報酬は使用されていないため、推論チェーンが必ずしも解釈しやすいとは限らないと注意しています。

別のサーバーに接続する

クライアントはデフォルトでhttp://127.0.0.1:8009を使用します。サーバーが別のアドレスで実行されている場合は、JEEVES_BASE_URL環境変数を設定してください。

export JEEVES_BASE_URL=http://your-server:8009

推論とレイテンシーを制御する

オプションのoptionsオブジェクトには、4つの推論制御項目があります。対応するサーバーフラグを使って、サーバー全体のデフォルト値を設定できます。

  • think:デフォルトはtrueです。falseにすると、推論チェーンを生成せず、プロンプトから直接回答します。
  • max_think:デフォルトは2560です。モデルが回答する前に、各推論チェーンを指定したトークン数で切り詰めます。
  • nothink_threshold:デフォルトはnullです。設定すると、「推論不要」の信頼度がしきい値以上になった場合に、Jeevesは推論を省略します。
  • return_reasoning:デフォルトはfalseです。有効にすると、レスポンスに推論テキストを含めます。

レイテンシープロファイルを選択する

READMEに記載された325問の開発評価では、完全な推論で精度0.825、平均推論トークン数1,138、レイテンシー中央値3.3秒を達成しました。max_thinkを768、nothink_thresholdを0.9にすると、精度0.806、平均推論トークン数344、レイテンシー中央値2.0秒でした。推論を無効にすると、約0.3秒で精度0.775となりました。

実用的なバランス設定は次のとおりです。

{
  "options": {
    "max_think": 768,
    "nothink_threshold": 0.9,
    "return_reasoning": false
  }
}

完全な推論では、レイテンシーの裾が長くなります。報告されたp90は17.1秒です。応答時間が重要な場合は、短いチェーンまたは信頼度ベースの推論を使用してください。

Jeevesの意思決定方法

Jeevesは、Qwenトークナイザーの出現頻度が低いトークンを使って、状態、質問の指示、回答の選択肢をフォーマットします。その後、thinkマーカーから始まる推論チェーンを生成します。推論後、意思決定マーカーの前に質問と選択肢が再度記述されます。

ポインターヘッドは、意思決定マーカーにおけるクエリ射影と、各選択肢の境界におけるキー射影とのスケールド内積を計算します。ソフトマックスによってスコアを確率に変換し、開発セットで適合した温度によって確率を較正します。READMEのアブレーションによると、特殊なプロンプトトークンを通常のラベルに置き換えたり、推論後に質問を繰り返す処理を省略したりすると、性能が低下しました。

拡散ドラフター

オプションのドラフターは、投機的デコーディングによって推論生成を高速化します。Orthrusの拡散アプローチをQwen3.5のGated DeltaNetレイヤー向けに適応し、マスクトークンが畳み込み後のキーと値に対してクロスアテンションできるようにしています。

報告された1問あたりのスループットは、通常のグラフ付き貪欲デコーディングのチェーントークン毎秒109から、ブロック4では毎秒176トークンに向上します。ブロック8では毎秒193トークンに達しますが、複数の質問をバッチ処理する場合でも低コストであるため、デフォルトは引き続きブロック4です。ブロック4で8問をバッチ処理すると、合計で毎秒約960チェーントークンに達します。

トレーニング済みチェックポイントを提供する

JeevesはトレーニングにLoRAを使用します。トレーニング済みチェックポイントを提供する前に、スタンドアロンモデルに統合し、対応するドラフターファイルを指定してください。

python export.py runs/cispo/final --out runs/fused
python -m inference.serve \
  --model runs/fused \
  --drafter runs/drafter_k4/drafter.safetensors \
  --port 8009

トレーニングパイプラインを再現する

データセットを準備する

準備スクリプトは、prep/public.pyでリビジョンが固定された公開データセットをHugging Faceからダウンロードします。各ソースデータセットは、それぞれのライセンスに従います。

python -m prep.prep

トレーニングと評価を実行する

文書化された再現パイプラインでは、8基のGPUを使用します。教師ありファインチューニング、CISPOトレーニング、テストおよびJevBench評価、モデルのエクスポート、チェーン生成、ブロック4ドラフターのトレーニングを実行します。

torchrun --nproc_per_node 8 train.py sft --run-dir runs/sft

torchrun --nproc_per_node 8 train.py cispo \
  --run-dir runs/cispo \
  --init runs/sft/final

torchrun --nproc_per_node 8 test.py runs/cispo/final
torchrun --nproc_per_node 8 jevbench.py runs/cispo/final
python export.py runs/cispo/final --out runs/fused

torchrun --nproc_per_node 8 -m drafter.gen --model runs/fused

torchrun --nproc_per_node 8 train.py drafter \
  --model runs/fused \
  --block 4 \
  --run-dir runs/drafter_k4

公開されたレシピでは、まず12の公開データセットと合成ポリシーデータに含まれる19,126問を使って、SFTを2エポック実行します。次に、問題ごとに8回のロールアウト、温度1、2,560トークンの推論上限を設定してCISPOを適用します。その後のステップでは、飽和した強化学習プール上でポインターヘッドが過度に先鋭化したため、予定されていた624ステップのスケジュールをステップ402で停止しました。最後に、開発セットでキャリブレーション用の温度を1つ適合させました。

高度な利用のヒント

  1. 関連する判断をまとめる。 複数の質問を1つの共有状態にまとめると、サーバーはそれらの推論チェーンを並列処理できます。
  2. 簡単なケースでは直接回答を使う。 nothink_thresholdを設定し、思考なしの信頼度が指定したしきい値を下回る判断にだけ推論を使うようにします。
  3. レイテンシーが重要なサービスでは推論を制限する。 速度と精度の中間点を求める場合は、推論を完全に無効にするのではなく、max_thinkを下げます。
  4. 推論を選択的に返す。 アプリケーションがテキストを必要としない限り、return_reasoningは無効のままにします。特に、チェーンがすぐに解釈できるとは限らないためです。
  5. 独自のドメインで評価する。 Jeevesはプロジェクトのテスト分割と公開Je​​vBenchティアでは高い性能を発揮しますが、報告されたMMLUおよびMMLU-Proの知識評価ではJevを下回ります。
  6. 比較結果は慎重に解釈する。 JevBench以外では、公開されているKevとJevの比較に、同じ基礎ソースから取得した異なる項目が使われています。

結論

Jeevesは、構造化されたJev形式の出力に、テスト時推論、キャリブレーション済み確率、高速化されたチェーン生成を組み合わせています。公開された重みとJev互換のHTTPエンドポイントから始め、型付きアプリケーションコードにはPython SDKを使用し、精度とレイテンシーのバランスを取るためにmax_thinkとnothink_thresholdを調整してください。さらに深くカスタマイズする場合は、リポジトリにSFT、CISPO、キャリブレーション、エクスポート、ドラフターの各パイプラインが完全に用意されています。