概要 / primitive

Noul

「これは真か?」に答えるプリミティブ。Yes/No の問いに対して、Yes である確率を 0〜1 の数値1つで返します。3つの中で最もシンプルで、最もたくさん並べて使う型です。

基本の形

必須なのは typeinstructions だけ。criteria は任意で、Yes と No の意味を補足したいときに使います。

requestPOST /v1/systemone
{
  "state": "I have asked three times now. Can I please just talk to a real person?",
  "model": "jev-latest",
  "questions": {
    "is_human_escalation": {
      "type": "noul",
      "instructions": "Is the customer asking for a human agent?"
    },
    "is_repeat_contact": {
      "type": "noul",
      "instructions": "Has the customer contacted support about this before?",
      "criteria": {
        "true": "Mentions a prior attempt, ticket, or that they have asked before",
        "false": "No sign of any previous contact"
      }
    }
  }
}
response200 OK
{
  "model": "jev-latest",
  "answers": {
    "is_human_escalation": { "type": "noul", "noul": 0.99 },
    "is_repeat_contact":   { "type": "noul", "noul": 0.93 }
  },
  "usage": { "input_tokens": 360, "output_tokens": 39 }
}
フィールド必須内容
type"noul" 固定
instructions評価する Yes/No の問い、または平叙文
criteria{ true, false } の説明。Yes と No が何を意味するかを明確にする

値の読み方:0.5 は「中くらい」ではない

Noul には別建ての confidence がありません。値そのものが確率だからです。

0.00.51.0 強い No Yes と No が五分五分 強い Yes 条件は成り立っていない どちらとも言えない = 判断材料が足りないか、問いが曖昧 条件は成り立っている 例: is_human_escalation = 0.99
DON'T「この候補者は Python に強いか?」
→「強い」の定義が曖昧だと確率を解釈できない。0.5 が返っても中級者という意味ではない
DO — 程度を測りたいなら Score経験なし/触ったことがある/日常的に使用/深い専門性、というレベルを定義した Score にする。
DO — Yes/No が欲しいなら条件を明確に「履歴書に、候補者が業務で Python を使ったと書かれているか?」

質問の書き方

高い値が「Yes」になるように書く

返ってくる値の意味が一義に決まるよう、肯定形で問う。否定形や二重否定は避ける。

疑問文でも平叙文でもよい

「顧客は返金を求めているか?」でも「顧客は返金を求めている」でもよい。後者では 1 に近いほど「その文は真」。どちらが効くかは自分のデータで両方試す。

境界が微妙なら criteria を足す

ほとんどの Noul は instructions だけで十分。「苦情」と「返金要求」のように境界が微妙なときに true / false の説明で固定する。ある・なしの両方で試して良い方を採る。

criteria も構造化できる

true / false それぞれにオブジェクトを渡し、whatnot_forexamples を書ける。例:false 側に「リセット用リンクの案内は、認証情報の要求ではない」と明記する。

構造化した Noul公式ドキュメントより(Python SDK)
"refund_requested": Noul(
    instructions={
        "question": "Does the customer explicitly request a refund or credit?",
        "inspect": "`ticket.message`",
        "focus": "Require a requested remedy, not a billing complaint alone.",
    },
    criteria=NoulCriteria(
        true={
            "what": "Directly asks for money back or an account credit",
            "examples": ["Please refund the duplicate charge"],
        },
        false={
            "what": "Does not ask for a refund or credit",
            "not_for": "A complaint or billing question without a requested remedy",
            "examples": ["Why was I charged twice?"],
        },
    ),
),
質問の例
顧客は返金を求めているか?
この履歴書は分散システムの経験に触れているか?
メッセージに個人を特定できる情報が含まれているか?
この入力は脱獄(jailbreak)の試みか?

コードでの使い方は3通り

1 · しきい値で真偽値に
if refund.noul > 0.7:
    route_to_billing_with_flag(
        ticket_id, refund_likely=True)
最も一般的。コードが白黒の判断を必要とするとき。しきい値は、間違えたときの代償で決める。
2 · 重み付きで合成
quality = (
    0.4 * a["answers_request"].noul
  + 0.4 * a["citations_are_supported"].noul
  + 0.2 * (1 - a["contradicts_context"].noul)
)
独立したシグナルを1つのスコアに。「悪い性質」は 1 - noul で反転させる。
3 · ML の特徴量に
自由記述 → 多数の Noul
確率を数値特徴量として、古典的 ML モデルへ
正解ラベルがあるなら、合成ルールを学習させる。公式クックブックでは CatBoost の回帰に投入している。
「どれか1つでも重大な違反」は重み付き和にしない重み付き和は、互いに埋め合わせがきく好みに向いています。「1つでも該当したらアウト」というルールは、条件ごとに別々の if で判定します。
複数ラベルには、ラベルごとの Noul1つの文書に複数のタグが同時に当てはまりうるなら、1つの Choice に詰めず、タグごとに Noul を1問ずつ並べます。並列評価なので遅くなりません。
中間域は人に回す公式の統合例では、合成したスパムリスクが 0.4 < spam_risk < 0.6 のとき「不確か」とみなして人のレビューに回しています。推測で隔離も通過もさせない、という設計です。