Agent Skillskunpengtalk/OmniStudio › jev-typed-decisions

jev-typed-decisions

GitHub

JEV类型化判定Skill,通过结构化调用实现分类、打分及判断,返回概率分布而非文本。适用于工单分派、内容审核、意图路由等需结果稳定可比的场景。

.agents/skills/jev-typed-decisions/SKILL.md kunpengtalk/OmniStudio

Trigger Scenarios

帮我按这个标准打分 这批数据分类一下 判断是不是垃圾邮件 给这几段回答打个分

Install

npx skills add kunpengtalk/OmniStudio --skill jev-typed-decisions -g -y
More Options

Non-standard path

npx skills add https://github.com/kunpengtalk/OmniStudio/tree/main/.agents/skills/jev-typed-decisions -g -y

Use without installing

npx skills use kunpengtalk/OmniStudio@jev-typed-decisions

指定 Agent (Claude Code)

npx skills add kunpengtalk/OmniStudio --skill jev-typed-decisions -a claude-code -g -y

安装 repo 全部 skill

npx skills add kunpengtalk/OmniStudio --all -g -y

预览 repo 内 skill

npx skills add kunpengtalk/OmniStudio --list

SKILL.md

Frontmatter
{
    "name": "jev-typed-decisions",
    "description": "用 JEV \/ SystemOne(TypeSafe 协议)做**类型化判定** —— 把「是\/否」「选哪个」「打几分」变成一次结构化调用,拿回概率分布而不是一段需要解析的文本。适用:分类与打标、工单分派、紧急度打分、简历\/文档评分、内容审核护栏、检索结果重排、意图路由、字段抽取、按置信度分流。当需要**结果稳定可比较**、答案必须落在给定的选项或档位里、或同一批内容要跑很多个判断时使用(\"帮我按这个标准打分\"、\"这批数据分类一下\"、\"判断是不是垃圾邮件\"、\"给这几段回答打个分\")。Answer typed questions (choice \/ score \/ noul) about a piece of state and get probabilities back — classification, rubric scoring, guardrails, reranking, intent routing, extraction — instead of sampling prose from a chat model."
}

JEV / SystemOne:类型化判定

它解决什么问题

用聊天模型做分类、打分、判断,得到的是生成的一段话:要写解析、格式会飘、同一个输入 跑两次可能不一致、多问几件事还会互相"带节奏"。JEV 把这类判断变成一次结构化推理

  • 三原语:noul(是/否,返回 P(true))、choice(在给定选项里选一个)、score(在有序档位上打分);
  • 一次请求可以问很多个问题,并行且互不影响(同一个 state,各问各的);
  • 答案被约束在你给的选项/档位/概率分布里 —— probabilities 加起来约等于 1,confidence 是分布的集中度;
  • 输出 0 个 token:不是逐字生成的,所以也没有"输出跑偏"这件事。

三个可直接调用的入口(同一套协议、同一个后端,选哪个看你在哪):

  1. Agent 工具 jev_evaluate —— 在这个应用的 Agent 里直接用(本地/云端由设置决定,免费);
  2. 本机网关 POST /v1/systemone —— 外部 agent(Claude Code / Codex / 你自己的脚本)用;
  3. 官方 SDK —— typesafe-sdk / @typesafe-ai/sdk,只改 TYPESAFE_BASE_URLTYPESAFE_API_KEY 两行,就能从官方切到本机网关(协议逐字段一致)。

界面上试:左侧一级菜单的 JEV 页(默认排在 Agent 与通话之间),结构同语音合成页 —— 左栏顶部切「本地运行 / 云端接入」(本地可装引擎、下权重、启动模型;云端填 Base URL 与 Key), 下面是 state 与问题清单;右栏是概率分布与置信度。侧栏有五个中英双语示例 (工单分派 / 简历评分 / 内容护栏 / 检索重排 / 意图路由),点一下就能装进左栏直接跑; 「复制调用示例」一键拿到 cURL / Python / JS 三种写法。

先决定用哪个原语

你要问的 拿回来的
是不是 / 有没有 / 成立吗 noul noul(P(true),0..1)
若干个无序选项里是哪个 choice choice + probabilities + confidence
在一条有序档位线上处于哪一档 score score(期望档位,可带小数)+ legend + probabilities + confidence

选择规则很简单:能排序就用 score,不能排序就用 choice,只有两种情况就用 noul。 把可以排序的东西写成 choice("低/中/高")会丢掉"到底有多靠近下一档"这个信息, 而 score 的期望值(2.99/5)恰恰是它最有用的地方。

直接调用(网关)

curl -s http://127.0.0.1:<网关端口>/v1/systemone \
  -H "Authorization: Bearer $OMNI_GATEWAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "I was charged twice for the same order. Please refund the duplicate.",
    "model": "jev-latest",
    "questions": {
      "department": { "type": "choice", "instructions": "Which team should handle this?",
        "criteria": { "billing": "invoices, payments, refunds", "technical": "bugs and outages", "sales": null } },
      "urgency": { "type": "score", "instructions": "How urgent is this request?",
        "criteria": ["not urgent", "soon", "critical"] },
      "refund_requested": { "type": "noul", "instructions": "Does the customer ask for money back?" }
    }
  }'

网关端口与 Key:应用 → 设置 → 网关(Key 在那里创建)。响应:

{
  "model": "jev-1.13.0",
  "answers": {
    "department": { "type": "choice", "choice": "billing", "confidence": 0.93, "probabilities": {"billing":0.93,"technical":0.05,"sales":0.02} },
    "urgency": { "type": "score", "score": 2.4, "confidence": 0.71, "legend": {"0":"not urgent","1":"soon","2":"critical"}, "probabilities": {"0":0.02,"1":0.56,"2":0.42} },
    "refund_requested": { "type": "noul", "noul": 0.97 }
  },
  "usage": { "input_tokens": 168, "output_tokens": 0 }
}

用官方 SDK(只换两行)

import os
os.environ["TYPESAFE_BASE_URL"] = "http://127.0.0.1:<网关端口>"   # 官方是 https://api.typesafe.ai
os.environ["TYPESAFE_API_KEY"] = "<设置 → 网关里的 API Key>"

from typesafe_sdk import Noul, Score, Choice, TypeSafeClient

with TypeSafeClient() as client:
    r = client.system_one(
        state="I was charged twice. Please refund the duplicate.",
        questions={
            "department": Choice(instructions="Which team?", criteria={"billing": None, "technical": "bugs"}),
            "urgency": Score(instructions="How urgent?", criteria=["not urgent", "soon", "critical"]),
            "refund": Noul(instructions="Does the customer ask for money back?"),
        },
    )
    print(r.answers["department"].choice, r.answers["urgency"].score, r.answers["refund"].noul)
import { TypeSafeClient, choice, noul, score } from "@typesafe-ai/sdk";

process.env.TYPESAFE_BASE_URL = "http://127.0.0.1:<网关端口>";
process.env.TYPESAFE_API_KEY = "<设置 → 网关里的 API Key>";

const client = new TypeSafeClient();
const r = await client.systemOne({
  state: "I was charged twice. Please refund the duplicate.",
  questions: {
    department: choice("Which team?", { billing: null, technical: "bugs" }),
    urgency: score("How urgent?", ["not urgent", "soon", "critical"]),
    refund: noul("Does the customer ask for money back?"),
  },
});
console.log(r.answers.department.choice, r.answers.urgency.score, r.answers.refund.noul);

更多可复制的例子(分派 / 打分 / 护栏 / 重排 / 抽取 / 按置信度分流)见 reference/examples.md;完整字段与错误码见 reference/api.md

写问题的四条硬规矩

  1. 一个维度一个问题。 "这条投诉是紧急的还是关于账单的"是两个判断,拆成两个问题。 合成一个,两个维度会互相污染,而且你没法分别设阈值。
  2. 描述情形,不要描述程度。 档位写"导出按钮在 Safari 上崩溃,有临时绕法",不要写"中等严重"。 模型只需要认得出情形,映射到几分是你的代码该做的事 —— 而且这样换档位不用重训。
  3. 给判定标准而不是给答案。 criteria 是"什么算这个选项",写清边界与反例, 尤其是容易混淆的那两个选项之间差在哪。
  4. 别把问题名当提示。 问题名只是你自己取的回执键,模型看不到它 (官方明确这么说)。想告诉模型什么,就写进 instructionscriteria

还有两条经验性的:

  • instructions 可以是对象或数组。 要引用一大段结构化数据时,把问题和数据分开: {"task": "...", "field": "…"};比把所有东西糊成一个长字符串稳。
  • 同一批数据问很多问题时,一次请求全问掉。 它们并行、互不影响,而且 state 只处理一次。

怎么读答案(这一节最容易被忽略)

  • probabilities完整分布,别只看第一名。{"billing":0.51,"technical":0.49}{"billing":0.99}choice 都是 billing,但前者的意义完全不同。
  • confidence 是分布的集中度(0=完全平摊,1=全压在一个选项上)。它衡量的是"分布有多集中", 不是"答案有多对" —— 官方文档也强调这点。正确的用法是设阈值分流: 高置信度走自动处理,低的转人工/换更强的模型/加一问。
  • score 是期望值,可以落在两档之间,这正是它的价值(2.99 比"3 分"信息量大)。 分档做阈值时用 probabilities 里相邻档位的概率,而不要只看期望值。
  • noul 没有 confidence(只有两个结果,一个概率就说完了)。自己按业务代价定阈值: 误判成本高就要求 >0.95,漏判成本高就放到 >0.6。别默认 0.5。

什么时候不要用它

  • 要生成文本(摘要、回复、改写)—— 那是聊天模型的事,JEV 只回答被约束的问题。
  • 需要长链推理 / 多步工具调用 —— 它是一次前向判定,不做 agent 循环。
  • 需要精确计算(算术、日期差值)—— 概率模型给的是"判断",不是"计算"。 日期这类"抽取"可以问,但结果要自己校验一遍。
  • state 超过上下文:官方 JEV 是 64k(state 32k + 最长问题);本地 Laya 更小 (英文 512 / 多语言 1024 token)。超了要先摘要或切片,别指望它自己截。本地模型 对中文的支持明显弱于英文 —— 中文内容优先走云端,或换 laya-multilingual

排查

  • 503 configuration_error:本地运行时没装、本地地址为空、云端 Key 也没配。 去 JEV 页左栏顶部切到「本地运行」装引擎与权重,或切到「云端接入」填 Key。
  • 401 / 403:401 = Key 无效,403 = 请求里根本没有 Key(官方的两种失败是分开的)。
  • 422:请求体不合规,detail[].loc 直接指出哪个字段(例如 body.questions.x.criteria)。
  • 502:后端连不上或响应不符合契约。本地运行时的话看应用日志(omi logs, source systemone)里的 systemone.laya.* 事件。
  • 本地第一次调用很慢:首次要把权重下到 Hugging Face 缓存(几百 MB)。
  • 结果看起来"太自信":检查档位/选项的描述是不是互相重叠了 —— 描述含糊时模型会挤在一个 选项上。置信度低反而是它在说"这两个我分不清"。

证据都在 <dataDir>/logs/app.logomi logs --source systemone)与用量的「调用来源 → JEV 类型化判定」(价格 0,只记次数与 tokens)。

Version History

  • 24199d4 Current 2026-09-21 23:52

Same Skill Collection

.agents/skills/omni-doctor/SKILL.md
.agents/skills/shadcn/SKILL.md

Metadata

Files
0
Version
24199d4
Hash
7a39c727
Indexed
2026-09-21 23:52

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-22 04:42
浙ICP备14020137号-1