JEV - 兩個 demo:回來的只是一張分佈
兩個例子都只問封閉的單選:客服裡切不切人工,合併前放不放行。回來的是分佈。公開延遲仍是大約 70 到 500 毫秒,不是某一次演示的毫秒數。

聯合作者:folkbench.com (Folkbench 是面向 AI API、模型服務及相關站點的可覆核評測與選擇平台,依據已發布的服務資料、價格、可用性、延遲與證據窗口,幫助用戶比較並選擇使用路徑。)
這一組共十篇:
- JEV - 關節不需要大腦
- JEV - 系統潤滑劑:控制節點不再生成
- JEV - 從 BERT 到 Jev:分類回到一張分佈
- JEV - 告別提示詞詩學:封閉題怎麼設計
- JEV - 反 Token 經濟學:大廠為什麼不先做
- JEV - 兩個 demo:回來的只是一張分佈
- JEV - 退出環路:置信度寫進程式碼
- JEV - 能力過線之後,更聰明不再是賣點
- JEV - 直覺與理性:有些話不該問關節
- JEV - 從操作螢幕到只出概率
兩個 demo 都是同一件事:不給自由文字,只給封閉題,拿分佈做分支。下面的 JSON 和程式碼是呼叫形狀,不是一份計時報告。公開的端到端大約 70 到 500 毫秒。不要把某一次 18 毫秒寫成產品指標。值得看的是返回裡沒有逐 token 的句子。
客服:意圖和熔斷
場景
客服最怕使用者已經在發火,系統還在打字。用生成式模型做意圖,常常為了準確而先寫一段 JSON,首包和生成都等在那裡。用純正則又讀不懂繞著說的怒氣。要的是封閉分類,然後立刻決定切不切人工。
狀態和選項
這是一道 Choice,不是 Noul。Noul 只回答是非。這裡選項有三項。
[State]
scene: live support entry
rule: assign probability across the given options from the message text
[user]
I have waited three days. The shipment has not moved. Are you even alive? Refund me now, or I escalate.
{
"question": "choice",
"options": [
{"id": "GENERAL", "description": "ordinary question or tracking, no strong emotion"},
{"id": "REFUND", "description": "a clear return or refund, stated flatly"},
{"id": "BREAKER", "description": "insult, threat, or a complaint that should break to a person"}
]
}
回來的是分佈
沒有游標在吐字。形狀是一張表,不是一段評語。
{
"top": "BREAKER",
"scores": [
{"choice": "BREAKER", "score": 0.9241},
{"choice": "REFUND", "score": 0.0715},
{"choice": "GENERAL", "score": 0.0044}
]
}
數字是這個例子裡的分佈,用來看分支怎麼寫。它不是一次公開基準。模型是在給定選項上分配機率,不是在預測下一個字元。
程式碼怎麼接
async function handleIncomingCustomerMessage(userMessage: string) {
const res = await jev.choice("cs_intent_v1", { input: userMessage });
const breaker = scoreOf(res, "BREAKER");
if (breaker > 0.85) {
return triggerHumanOverride({ priority: "CRITICAL", queue: "RETENTION" });
}
if (scoreOf(res, "REFUND") > 0.70) {
return launchWorkflow("AUTOMATED_REFUND_FLOW");
}
return launchWorkflow("DEFAULT_FAQ_BOT");
}
沒有為了解析 Markdown 再寫一輪重試。閾值寫在程式碼裡。0.85 和 0.70 是這個流程自己的政策,不是模型給的保證。
合併前的審計
場景
靜態掃描靠語法樹和死規則,變體能繞過,誤報也多。讓聊天模型讀 500 行 diff 再寫評語,常常要十幾秒,流水線等不起,腳本也讀不出「過」還是「不過」。把 diff 當 state,問一道 Choice:通過、人工看、還是阻斷。
狀態和選項
[Git diff]
PR #1042
file: src/auth/session.ts
+ // skip expiry outside production, or when the token starts with test_admin_
+ if (process.env.NODE_ENV !== 'production' || token.startsWith('test_admin_')) {
+ return session;
+ }
{
"question": "choice",
"options": [
{"id": "PASS", "description": "harmless refactor, docs, or ordinary logic"},
{"id": "WARN", "description": "config, dependency, or a non-sensitive refactor; a person should look"},
{"id": "BLOCK", "description": "backdoor, hardcoded secret, privilege jump, auth bypass, injection"}
]
}
test_admin_ 能在生產環境跳過過期檢查,這是身分驗證繞過。例子裡的分佈把 BLOCK 放在 0.98 一帶。刪掉這一截,只留下「非生產才跳過」,同一道題會從阻斷挪到人工看。這是題的用法,不是一組對外承諾的毫秒數。
流水線怎麼接
def audit_pr_diff(diff_text: str) -> int:
result = jev.choice(
question="pr_security_v2",
state=diff_text,
options=["PASS", "WARN", "BLOCK"],
)
scores = result.scores
if result.top == "BLOCK" and scores["BLOCK"] > 0.80:
print("high-risk auth change")
return 1
if result.top == "WARN":
mark_review_required()
return 0
return 0
位址寫成內部服務就行。不要把這理解成某個公開站點已經代為提供 Jev。流水線讀的是頂項和分數。評語如果還要給人看,另請一個會寫的模型,不要塞回這道題。
像調一個返回數字的介面
這兩次把同一件事做實了:複雜的判斷留在模型內部,外面只留機率。Noul、Choice、Score 是三種格子,不是三種聊天風格。
路由、風控、合併前檢查、策略引擎、Agent 的分支,都可以先問自己:這一步是否寫得成封閉題。寫得成,就不要再等一段生成。寫不成,就不要裝成 demo 裡的這種呼叫。