TypeSafe のプリミティブは、コード内で組み合わせて使用する小さく、型付けされたビルディングブロックです。
3つの TypeSafe の質問タイプ (Choice, Score, Noul)、それらが返す型付きの回答、各タイプの選び方、そして複数の質問を一度に実行する方法について説明します。
Jev 入門 : コンセプト – プリミティブ (質問)
作成 : Masashi Okumura (@ClassCat)
作成日時 : 10/23/2026
* 本記事は docs.typesafe.ai の以下のページを参考にしています :
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。

Jev 入門 : コンセプト – プリミティブ (質問)
3つの TypeSafe の質問タイプ (Choice, Score, Noul)、それらが返す型付きの回答、各タイプの選び方、そして複数の質問を一度に実行する方法について。
TypeSafe のプリミティブは、コード内で組み合わせて使用する小さく、型付けされたビルディングブロックです。これらはペアで構成されます: 質問 (question) は ステート について System One モデル が下す1つの判断 (judgment) を定義し、その回答は返される型付きの値となります。この回答をコード内で組み合わせることで、意思決定を行います。質問タイプは3種類あり、それぞれ異なる形状の回答を返します。
| タイプ | 何に答えるか | 返り値 |
|---|---|---|
| Choice | これらの選択肢のどれか? | choice, probabilities, confidence |
| Score | どのレベルか? | score, legend, probabilities, confidence |
| Noul (真偽確率) | これは真 (true) か? | noul (0 to 1) |
質問は1件だけ行うことも、複数まとめて送信することも可能です。1つのリクエストに含まれるすべての質問は同一のステートを参照し、個別に評価され、指定したIDのもとに型付きの回答を返します。
質問毎に1つの直感的な判断 (snap judgment) を求める
System One モデルは、高速かつ焦点を絞った判断を行うために構築されています。適切なコンテキストが与えられれば、十分な知識を持つ人間が1秒で下せるような判断を求めてください。「このメッセージは緊急性 (urgency) を伝えているか?」は良い質問です。「このメッセージを分析し、最善の行動方針を決定せよ」は良くありません。後者には時間をかけた推論 (slow reasoning) が必要であり、それはタスクを小さな質問へと分解し、コード上で回答を組み合わせるべきだというシグナルです。
下したい判断が複数の独立した要因に依存している場合は、要因ごとに個別に質問し、独自のロジックで回答を結合してください。「このスタートアップ・ピッチを評価せよ」とするのではなく、市場規模、技術的実現可能性、差別化要因について個別に尋ね、そしてそれぞれの相対的な重要度に基づいてコード側で重み付けを行います。優先順位が変わった場合も、プロンプトを書き直すのではなく、コード側で重みの値を変更してください。Ask multiple questions together shows how to do this.
質問の定義
すべての質問(question)は、ID、type と `instructions` を持ちます。Choice および Score の質問には `criteria` (基準) も指定し、Choice 質問では選択肢、Score ではレベルを定義します。Noul の質問では、何が yes であり何が no を意味するのかを明確にするためのオプションの基準として criteria を受け付けます。
- ID: refund_requested のようにユーザーが選択したキー。レスポンス内で回答を識別します。
- type: choice、score、または noul のいずれか。
- instructions: ステートに対して投げかける質問。評価ロジックをここに記述します。明確かつ具体的な質問文として書くか、モデルが判定するためのステートメントとして記述します。殆どの質問では文字列で十分です。それはまたオブジェクトや配列にすることも可能で、その場合は1つのフィールドに質問を配置し、参照するデータを他のフィールドに置くことができます; see Use structure in the questions.
- criteria: 取り得る回答の定義 – Choice 質問の場合は選択肢のマップ、Score の場合は順序付けられたレベルのリスト、Noul の場合は yes と no に関するオプションの説明です。Each question type’s page covers its shape.
この質問は、顧客が返金を要求したかどうかを尋ねています :
from typesafe_sdk import Noul
questions = {
"refund_requested": Noul(
instructions="Does the customer request a refund?",
),
}
💡 Question IDs are for your code. They are not sent to the model. Write the complete question in instructions, even when the ID seems self-explanatory.
質問タイプの選択
必要とする回答の形状に合ったタイプを選択してください。
- Choice は、回答が、順序関係のない既知の選択肢セットの中から1つである場合に適しています: チケットを対応部署へルーティングする、文書の種類を分類する、プログラミング言語を判別する。選択肢の完全なリストを指定し、そのリストがすべての入力パターンを網羅しきれない可能性がある場合は、`other` や `none of the above` (上記のいずれでもない) といった選択肢を追加してください。
- Score は、回答が一定のスペクトラム (連続的な尺度) 上に位置し、そのスペクトラム上の各ポイントが何を意味するかを説明できる場合に適しています: バグの深刻度、顧客の不満度、スキルレベル。各レベルの定義は自由に設定でき、モデルはそのレベル上のどの位置に該当するかを返します。
- Noul は、確率そのものが有用なシグナルとなる、明確な yes/no 質問に適しています: このメッセージに個人を特定できる情報が含まれているか、顧客は返金を要求しているか、履歴書に分散システムについての言及があるか。
ℹ️ yes/no 判定には Noul を、スペクトラム上の位置を測定するには Score を使用してください。“Is this candidate strong in Python?” (この候補者はPythonが得意か?) という問いには、”strong” の明確な定義が必要です。Noul の値が 0.5 であるということは、モデルが yes と no に同等の確率を付与していることを意味します。これは候補者のスキルレベルが中程度であることを意味するわけではありません。定義が曖昧だと、その確率の解釈が困難になります。
スキルレベルを測定したい場合は、(「未経験」「ある程度の知識あり」「日常的に使用」「深い専門知識あり」のように、) 明確にレベルを定義した Score を使用してください。yes/no の判定が必要な場合は、「履歴書に実務での Python 使用経験が記載されているか?」のように、条件を明確に定義してください。
2つの型のどちらも適しているように思える場合は、コードがその回答に対して直接アクションを起こしやすい方を選択してください。たとえば、refund (返金)、rebook (予約変更)、information (案内) から選ぶ Choice は、コード上の3つの分岐パスにそのまま対応します。顧客の不満度を表す Score は閾値判定に対応します。Noul はそのまま if 文に対応します。
返ってくるもの (What comes back)
回答もまたプリミティブです。それぞれの質問タイプは型付きの値を返し、これをコード側で比較したり、閾値で判定したり、ソートしたり、後続のロジックに渡したり、あるいは後続リクエストのステートに配置することができます (see When one question depends on another)。
| タイプ | 回答フィールド | 読み取り方 |
|---|---|---|
| Choice | choice, probabilities, confidence | choice は選択された選択肢 (option)です。probabilities はすべての選択肢にわたる確率分布です。confidence はその分布がどれだけ尖っているか (peaked) を要約します |
| Score | score, legend, probabilities, confidence | score は (ユーザ定義の) レベルに沿った位置であり、2つのレベルの中間の値をとることもあります。legend は各レベルを数値順に再掲したものです。probabilities は各レベルの確率分布です |
| Noul | noul | 回答が yes である確率。1に近いほど強い yes、0に近いほど強い no、0.5付近は不確実 (uncertain) を意味します。Noul には個別の confidence はありません |
これらの回答を組み合わせ可能 (コンポーザブル) にしているのは、次の2つの特性です :
- すべての回答は、ユーザが提供した選択肢の範囲内に制限される。モデルは指定された選択肢やレベルに対する確率分布を返し、それ以外の範囲外の値を返すことは決してありません。コード側が、生成された散文 (prose) から値を取り出す (recover) する必要が一切ありません。
- すべての回答は独立している。ある質問の回答が、別の質問の隠れたコンテキストになることはありません。他の質問の結果を変えることなく、質問を追加・削除できます。
質問タイプによっては confidence (確信度) も返されます; 回答にそれが含まれるかどうかは、各タイプのページに記載されています。Confidence では、これをどのように使って、自動処理を行うケースか、人間へエスカレーションするケースかを判断するかが説明されています。
特定のフィールドを参照する
評価対象となるコンテンツ – ステート は、多くの場合、会話、レコード、ポリシーなど複数のパーツで構成される JSON オブジェクトです。質問がそれらのパーツの一つに関するものである場合は、バッククォートを含めた、ドット記法と配列インデックスによるキーへのパスを instructions 内に指定してください。これにより、モデルはステートのどの部分を判定すべきかを把握できます。
例として、ステートのページにあるサポートの会話を見てみましょう :
{
"ticket": {
"subject": "Duplicate charge",
"messages": [
{"from": "customer", "text": "I was charged twice for order A-104. Please refund the duplicate."},
{"from": "support", "text": "We are checking the charges."}
]
},
"order": {
"id": "A-104",
"charges": [
{"amount_usd": 49, "status": "captured"},
{"amount_usd": 49, "status": "captured"}
]
},
"refund_policy": "Duplicate charges are eligible for a refund."
}
これら2つの質問は、顧客のメッセージ、ポリシー、および請求内容をパス指定で参照しています :
questions = {
"refund_requested": {
"type": "noul",
"instructions": "Does `ticket.messages[0].text` request a refund?",
},
"policy_supports_refund": {
"type": "noul",
"instructions": (
"Does `refund_policy` support the refund requested "
"in `ticket.messages[0].text`, given `order.charges`?"
),
},
}
パスを明示することで、構造化されたステートのどの部分を参照して各判断を行うべきかが明確になります。See State for how to structure the input.
questions = {
"refund_requested": {
"type": "noul",
"instructions": "Does `ticket.messages[0].text` request a refund?",
},
"policy_supports_refund": {
"type": "noul",
"instructions": (
"Does `refund_policy` support the refund requested "
"in `ticket.messages[0].text`, given `order.charges`?"
),
},
}
以上