夜雨聆风学习资料网

ARTICLE · 1054869

AI 不聊天,专门做判断!TypeSafe AI 从零到实战:手把手教你构建一个智能决策系统

AI 不聊天,专门做判断!TypeSafe AI 从零到实战:手把手教你构建一个智能决策系统

我们平时使用 ChatGPT、DeepSeek 或 Qwen,主要是让模型回答问题、生成文章、编写代码,或者完成复杂的推理任务。但在真正开发 AI 应用时,你会发现,很多场景其实根本不需要模型长篇大论。

比如,一个智能客服系统收到客户投诉后,需要判断这条消息属于哪个部门、问题是否紧急、客户的情绪有多激烈;一个 RAG 知识库检索到十段文档后,需要判断哪些内容真正与用户问题相关;一个 Agent 接收到用户指令后,需要判断应该调用数据库、搜索工具,还是交给另一个模型处理。

这些任务有一个共同点:我们需要的不是一段精彩的回答,而是一个能直接被程序使用的判断结果。

最近,我发现了一个专门解决这类问题的 AI 项目——TypeSafe AI。

它推出了一种名为 Jev 的决策模型,不再以生成开放式文本为主要目标,而是让开发者提前定义问题和候选答案,由模型直接输出分类结果、评分、概率等结构化数据。

这篇文章就带大家从零开始体验 TypeSafe AI,使用 Python 编写一个真实的智能客服分类器,并进一步了解它如何接入 RAG、Agent 和 AI 安全护栏。

整个过程不需要训练模型,也不需要准备 GPU。只要有 Python 环境和 TypeSafe API Key,就可以跟着操作。

一、TypeSafe AI 到底是什么?

先来看一个实际场景。

假设我们正在开发一个 SaaS 平台,客户发来了这样一条消息:

“我的支付接口已经连续三天无法使用,订单都没办法支付了,请尽快解决!”

如果你负责开发这个系统,首先需要做什么?

很显然,我们希望程序能够自动判断出,这是一条技术故障相关的消息,客户表达了明显的紧急性,而且情绪比较激动。接下来,系统应该把工单交给技术部门,并设置相应的处理优先级。

传统做法是直接调用一个通用大模型,要求它返回 JSON。

例如:

请分析下面的客户消息,返回 JSON要求:1. 判断问题属于哪个部门。2. 判断客户是否紧急。3. 评估客户情绪。输出格式:{  "department""technical",  "urgent"true,  "emotion""angry"}

这种方法当然可以使用。现在不少大模型还支持 Structured Outputs,可以通过 JSON Schema 约束输出格式。

但实际业务中,我们还可能希望知道:模型为什么在技术问题和支付问题之间选择了前者?模型对不同候选类别的判断概率分别是多少?当分类不够明确时,应该如何让程序自动进入人工复核?

TypeSafe AI 就是针对这类结构化判断任务设计的。

它的核心模型叫作 Jev,官方将其定义为 System One 决策模型。开发者提供待分析的数据和需要回答的问题,模型返回类型化的判断结果,而不是生成一段自由文本。

它的基本工作流程可以概括为:

State + Questions → Jev → Answers

这里面有三个非常重要的概念。

State 表示需要分析的数据,例如一条客户投诉、一段合同内容,或者用户当前的请求。

Questions 表示我们希望模型回答的问题。例如,客户属于哪个类别?这条消息是否紧急?客户情绪有多激烈?

Answers 则是模型最终返回的结果,包括分类、评分和概率等信息。

需要注意,TypeSafe 并不是要全面替代 ChatGPT 或 Qwen。

它不适合编写长篇文章、生成复杂代码或完成开放式推理。它更适合处理答案范围明确、能够被结构化定义的判断任务。

简单理解就是:通用大模型负责生成和推理,TypeSafe 负责特定类型的判断,Python 负责执行实际业务逻辑。

二、搞懂三个核心功能,就理解了 TypeSafe 的大部分用法

TypeSafe 最重要的设计,是把判断问题分成三个基本类型:Choice、Score 和 Noul。

这三个名字第一次看到可能有些陌生,但其实非常容易理解。

1. Choice:从多个候选答案中选择一个

假设我们要判断一条客户消息应该交给哪个部门。

候选答案只有四个:

billing   支付与账单问题technical 技术问题sales     销售咨询other     其他问题

这就是一个典型的 Choice 问题。

我们可以这样定义:

{  "department": {    "type": "choice",    "instructions": "Which team should handle this ticket?",    "criteria": {      "billing": "Payment, invoices and refunds",      "technical": "Software bugs and integration failures",      "sales": "Pricing and subscription questions",      "other": "None of the above"    }  }}

其中,department 是问题名称,type 表示问题类型,instructions 告诉模型应该判断什么,criteria 则定义所有候选答案。

模型会从这些候选项中选择一个,并返回相应的概率分布。

例如:

{  "type": "choice",  "choice": "technical",  "confidence": 0.86,  "probabilities": {    "billing": 0.05,    "technical": 0.92,    "sales": 0.01,    "other": 0.02  }}

注意,上面的数值只是教学示例,并不是实际调用结果。

从这个结果中,我们不仅知道模型选择了 technical,还能够看到它对其他类别的判断概率。

不过,confidence 并不等于最高类别的概率。它反映的是整个概率分布的确定性程度,后面我们还会专门解释。

实际开发中,我建议在分类任务里尽量提供一个 other 选项,以避免模型被迫从几个明显不合适的类别中选择答案。

2. Score:按照预设等级进行评分

接下来,我们想判断客户的愤怒程度。

这个问题与刚才的分类有所不同,因为情绪程度具有明确的顺序。

我们可以定义三个等级:

{  "frustration": {    "type": "score",    "instructions": "How frustrated is the customer?",    "criteria": [      "Calm and neutral",      "Frustrated but polite",      "Very angry"    ]  }}

这三个等级分别对应 0、1、2。

假设模型认为客户处于第二个等级的概率为 60%,处于第三个等级的概率为 40%,那么评分结果就是:

ounter(lineounter(lineounter(lineScore = 0 × 0 + 1 × 0.6 + 2 × 0.4Score = 1.4

因此,Score 并不是简单地让模型随便生成一个数字,而是根据预设等级的概率分布计算加权结果。

这种设计适合情绪强度、风险程度、文档质量等需要进行有序评级的任务。

但是,如果你要预测一个精确数值,例如明天的电价、某个设备的实际温度,就不应该直接用 Score 替代回归模型。

3. Noul:判断一个条件是否成立

第三种类型是 Noul。

假设我们只想判断一件事:

“这条消息是否表达了紧急性?”

可以这样定义:

{  "urgency": {    "type": "noul",    "instructions": "Does this message express urgency?"  }}

假设返回:

JSON

{  "type": "noul",  "noul": 0.95}

这表示模型认为“消息表达了紧急性”这一命题成立的概率为 0.95。

Noul 的结果位于 0 到 1 之间。

越接近 1,模型越倾向于认为命题成立;越接近 0,则越倾向于认为命题不成立。

这里有一个很容易混淆的地方。

如果你问“客户是否愤怒”,Noul 返回 0.5,代表模型对真假判断存在不确定性,而不是说客户的愤怒程度刚好是中等。

如果你需要知道程度,应当使用 Score。

到这里,可以总结一下:Choice 解决“选哪个”,Score 解决“什么程度”,Noul 解决“是不是”。

掌握这三种类型,后面写代码就非常容易了。

三、先别急着写代码,打开 Playground 体验一下

理解基本概念以后,我们开始实际操作。

TypeSafe 提供了在线 Playground,可以先在浏览器里测试模型,不需要配置 Python。

官方地址:

👉https://console.typesafe.ai/playground

打开网站,按照页面提示登录,然后进入 Playground。

第一步:输入测试文本

找到 State 输入区域,粘贴下面这段英文:

ounter(lineounter(lineounter(lineounter(lineounter(lineHi, I've been trying to connect my Stripeaccount for 3 days and the integrationkeeps failing.I'm losing sales. Please help ASAP.

这段话的意思是:客户尝试连接 Stripe 支付账户已经三天,但集成一直失败,正在损失销售额,希望立即获得帮助。

这里建议先使用英文,因为 TypeSafe 官方表示,Jev 目前在英语任务上的表现更好。中文虽然也可以使用,但需要通过真实业务数据单独评测。

第二步:创建判断问题

在 Questions 区域添加一个问题,将问题类型设置为 Noul。

问题内容填写:

Does this message express urgency?

它的意思是:

这条消息是否表达了紧急性?

如果你使用的是 JSON 编辑方式,对应的问题定义如下:

{  "urgency": {    "type": "noul",    "instructions": "Does this message express urgency?"  }}

这里展示的是问题定义,不是完整的 HTTP 请求体。

第三步:运行测试

点击 Playground 提供的运行按钮,查看模型返回结果。

结果结构类似:

{  "urgency": {    "type": "noul",    "noul": 0.98  }}

其中 0.98 只是示意数值。真正的概率以你实际运行的结果为准。

看到结果以后,可以尝试把客户消息改成:

Hello, thank you for your help.

再次运行,观察紧急概率是否发生变化。

这样,通过两次简单测试,你应该就能理解 Noul 是如何工作的。

接下来,可以继续添加 Choice 和 Score 问题,让模型对同一条消息进行多个判断。

TypeSafe 的一个重要机制,就是允许我们在一次请求中提交多个独立问题,而不必先调用一个分类模型,再依次调用情绪判断和紧急程度判断。

四、准备开发环境:使用 uv 安装 Python SDK

网页体验完成以后,就进入真正的代码开发环节。

我们要编写一个 Python 程序,输入客户消息以后,自动输出所属部门、情绪评分、紧急概率,以及最终的业务处理路径。

首先,需要准备 API Key。

第一步:创建 API Key

进入官方控制台:

👉https://console.typesafe.ai/

登录以后,在控制台中找到 API Key 管理入口,按照页面提示创建密钥。

由于密钥管理界面需要登录账户,这里的具体按钮名称和位置以你的实际页面为准。

创建完成后,复制 API Key。

打开 Mac 终端,执行:

Bash

export TYPESAFE_API_KEY="你的API_KEY"

将引号中的内容替换成真实密钥。

之所以使用环境变量,是为了避免把 API Key 直接写在源代码里。

尤其要注意,不要把真实密钥提交到 GitHub,也不要放到前端 JavaScript 中。

第二步:创建项目

这里使用 uv 管理 Python 项目。

先检查是否安装 uv:

uv --version

如果没有安装,可以参考 uv 官方安装文档:

👉https://docs.astral.sh/uv/getting-started/installation/

安装完成以后,执行:

mkdir -p ~/projects/typesafe-democd ~/projects/typesafe-demo

这两条命令会在用户目录下创建项目,并进入项目文件夹。

接着初始化项目:

Bash

uv init --bare --python 3.11

再安装 TypeSafe 官方 SDK:

uv add typesafe-sdk

TypeSafe SDK 要求 Python 3.10 或更新版本,我们这里使用 Python 3.11。

如果电脑尚未安装 Python 3.11,可以先执行:

uv python install 3.11

最后验证 SDK 是否安装成功:

uv run python -c "from typesafe_sdk import TypeSafeClient; print('OK')"

如果终端输出:

OK

说明 Python 已经能够成功导入 SDK。

此时,开发环境就准备好了。

五、完整实战:写一个智能客服分类器

接下来是本文最重要的部分。

我们将使用刚才介绍的 Choice、Score 和 Noul,对一条客服消息同时进行三项判断。

模型负责返回判断结果,Python 负责决定工单应该自动分配给哪个部门,或者交由人工复核。

第一步:创建 Python 文件

在当前项目目录执行:

touch main.py

使用 VS Code、Cursor 或其他代码编辑器打开 main.py

然后将下面的代码完整复制进去。

第二步:编写完整代码

from typesafe_sdk import (    TypeSafeClient,    Choice,    Score,    Noul,)# ==================================# 1. 准备客户消息# ==================================ticket = """Hi, I've been trying to connect my paymentaccount for 3 days.The integration keeps failing.I'm losing sales. Please help ASAP."""# ==================================# 2. 定义需要判断的问题# ==================================questions = {    # 问题一:工单应该交给哪个部门?    "department": Choice(        instructions=(            "Which department should "            "handle this ticket?"        ),        criteria={            "billing": (                "Payment, invoices and refunds"            ),            "technical": (                "Software bugs and "                "integration failures"            ),            "sales": (                "Pricing and subscription questions"            ),            "other": (                "None of the above"            ),        },    ),    # 问题二:客户有多生气?    "frustration": Score(        instructions=(            "How frustrated is the customer?"        ),        criteria=[            "Calm and neutral",            "Frustrated but polite",            "Very angry",        ],    ),    # 问题三:客户是否表达了紧急性?    "urgent": Noul(        instructions=(            "Does this message express urgency?"        ),    ),}# ==================================# 3. 检查 API Key# ==================================if not os.getenv("TYPESAFE_API_KEY"):    raise SystemExit(        "请先配置 TYPESAFE_API_KEY 环境变量"    )# ==================================# 4. 调用 TypeSafe API# ==================================with TypeSafeClient() as client:    response = client.system_one(        model="jev-latest",        state=ticket,        questions=questions,    )# ==================================# 5. 提取模型判断结果# ==================================department = response.answers["department"]frustration = response.answers["frustration"]urgent = response.answers["urgent"]# ==================================# 6. 编写业务分流规则# ==================================# 以下阈值仅用于教学演示# 正式上线应通过真实数据确定if department.confidence < 0.7:    route = "human_review"elif 0.2 < urgent.noul < 0.8:    route = "human_review"else:    route = department.choice# ==================================# 7. 判断优先级# ==================================if (    urgent.noul >= 0.8    or frustration.score >= 1.5):    priority = "high"else:    priority = "normal"# ==================================# 8. 整理输出结果# ==================================result = {    "department": department.choice,    "department_confidence": (        department.confidence    ),    "department_probabilities": (        department.probabilities    ),    "frustration_score": (        frustration.score    ),    "urgent_probability": (        urgent.noul    ),    "route": route,    "priority": priority,}# ==================================# 9. 打印 JSON# ==================================print(    json.dumps(        result,        ensure_ascii=False,        indent=2,    ))

这段代码虽然有一些长度,但核心逻辑其实非常简单。

首先,我们准备一条客户投诉,并将它作为 State。

接着,在 Questions 中定义三个问题:Choice 判断所属部门,Score 评估客户情绪,Noul 判断紧急性。

然后,调用 TypeSafe 的 system_one() 接口。三个问题在同一次请求中提交,最终返回对应的结构化结果。

最后,通过 Python 编写业务规则,把模型结果转换为实际的工单处理路径和优先级。

需要注意,代码中的 0.7、0.8、1.5 等阈值仅用于展示业务逻辑,并不是 TypeSafe 官方推荐的生产阈值。

第三步:运行程序

保存 main.py,回到终端执行:

Bash

uv run python main.py

如果 API Key 有效、网络连接正常,并且账户具有相应权限,就会得到模型的判断结果。

输出结构可能类似:

  "department": "technical",  "department_confidence": 0.86,  "department_probabilities": {    "billing": 0.05,    "technical": 0.92,    "sales": 0.01,    "other": 0.02  },  "frustration_score": 1.4,  "urgent_probability": 0.95,  "route": "technical",  "priority": "high"}

以上是示例数据,不是本文实际调用 API 得到的结果。

从结果中可以看到,程序将客户消息归类为技术问题,同时判断客户表达了较高的紧急性,因此最终处理路径是技术部门,工单优先级为 high。

到这里,我们就完成了一个可以通过 TypeSafe API 进行智能分类和自动分流的 Python 程序。

六、最容易踩坑的地方:Confidence 不等于准确率

前面的代码中,有这样一段逻辑:

if department.confidence < 0.7:    route = "human_review"

很多开发者第一次看到这里,可能会直接把 confidence 理解成准确率。

实际上,两者不是一回事。

假设 Choice 返回以下结果:

{  "choice": "technical",  "probabilities": {    "technical": 0.95,    "billing": 0.03,    "sales": 0.02  }}

模型将绝大部分概率分配给 technical,说明判断比较集中。

但如果模型返回:

{  "choice": "technical",  "probabilities": {    "technical": 0.40,    "billing": 0.35,    "sales": 0.25  }}

虽然最后仍然选择了 technical,但三个候选类别的概率十分接近,说明模型在不同选项之间存在明显的不确定性。

TypeSafe 的 Choice 和 Score 会返回单独的 confidence 字段,它与整个概率分布的集中程度有关,而不等于最高类别的概率。

同时,confidence 也不能直接代表模型在真实业务数据集上的准确率。

例如,某一次预测的 confidence 为 0.99,并不意味着你的客服系统整体准确率已经达到 99%。

如果准备把它真正部署到生产环境,应该先准备一批人工标注的工单,将真实类别和模型预测结果进行对比,再计算 Accuracy、Precision、Recall、F1 等指标。

只有经过实际测试,才能判断某个置信度阈值是否足以支持自动分流。

这也引出了一个重要的工程原则:模型负责提供判断结果,实际业务操作仍然应该受到代码、规则和必要的人工审核控制。

七、进一步实战:把 TypeSafe 接入 RAG 系统

除了智能客服,TypeSafe 还可以放在 RAG 知识库中。

我们知道,一个典型的 RAG 系统通常包含用户提问、向量检索、重排序和大模型生成几个环节。

但是,即使经过 Embedding 检索和 Reranker 排序,最终检索到的文档也不一定全部具有价值。

有些文档可能只是包含了相同关键词,有些文档可能已经过时,还有些内容可能包含恶意构造的提示词。

这时,可以在检索和生成之间加入 TypeSafe 判断层。

整体流程就变成了:

用户提问    ↓Embedding 向量检索    ↓Reranker 重排序    ↓TypeSafe 判断    ↓筛选和标记候选文档    ↓LLM 生成最终答案

例如,用户提问:

“公司支持哪些退款方式?”

系统检索到三段文字:

passages = [    "Refunds are returned to the original payment method.",    "Our company was founded in 2020.",    "Refund processing normally takes several business days.",]

第一段描述退款方式,第二段介绍公司成立时间,第三段介绍退款处理周期。

我们希望模型判断每段文字是否有助于回答当前问题。

可以这样构建问题:

questions = {}for i in range(len(passages)):    questions[f"relevant_{i}"] = Noul(        instructions=(            f"Does `passages[{i}]` contain "            "information that helps answer "            "`question`?"        )    )

然后准备 State:

state = {    "question""What refund methods are supported?",    "passages": passages,}

调用模型:

withTypeSafeClient() as client:    response = client.system_one(        model="jev-latest",        state=state,        questions=questions,    )

最后,通过代码筛选:

selected = []for i, passage in enumerate(passages):    probability = response.answers[        f"relevant_{i}"    ].noul    if probability >= 0.8:        selected.append(passage)print(selected)

这里的 0.8 同样只是教学阈值,需要根据真实检索数据进行评测。

需要强调的是,TypeSafe 不一定要替代现有的 Reranker。

它可以作为独立的判断环节,针对相关性、内容矛盾、证据完整性和提示词注入风险等问题进行额外分析。

但是,增加这一层也会产生额外的调用成本和延迟,是否值得加入,应当以实际评测结果为准。

八、TypeSafe 还能接入 Agent 和 AI 安全护栏吗?

当然可以。

在 Agent 系统中,一个常见问题是:收到用户请求后,应该调用哪个工具?

比如用户说:

“帮我查询昨天的订单。”

这类任务可能只需要调用数据库,不一定需要进行复杂推理。

但如果用户说:

“帮我分析最近三个月订单转化率下降的原因,并提出优化方案。”

这就可能需要一个具有数据分析和推理能力的 Agent。

我们可以使用 Choice 判断用户意图。

intent = Choice(    instructions=(        "Which tool should handle "        "this user request?"    ),    criteria={        "database""Simple data queries",        "analysis""Complex data analysis",        "general""General conversation",        "other""Unsupported requests",    },)

模型返回意图以后,再由 Python 根据结果调用相应工具。

类似的方式也可以用在 AI 安全护栏中。

例如,系统需要判断用户输入是否试图覆盖原有指令、是否要求泄露机密信息,或者是否包含其他安全风险。

我们可以通过 Noul 定义这些真假问题,再根据业务规则决定继续处理、拒绝操作还是转人工审核。

不过,模型自身也可能受到对抗性输入影响,所以 TypeSafe 不应该成为唯一的安全防线。

对于敏感业务,还需要配合确定性规则、权限校验、专门的安全检测模型,以及真实的攻击样本测试。

九、上线之前,还需要了解这些限制

虽然 TypeSafe 的设计比较有意思,但它并不是万能的。

首先,Jev 当前主要接收文本输入,并不直接处理图片、音频和视频。如果业务中存在 PDF、图片或视频,可以先使用文档解析、OCR、ASR 等工具提取文字,再交给模型判断。

其次,TypeSafe 不适合承担复杂数学计算、精确日期比较和开放式文本生成。这些任务应该交给 Python、专门的算法或者其他大模型完成。

此外,中文场景需要额外关注。官方表示,Jev 以英语作为主要训练语言,其他语言的表现可能存在差异。

如果你的业务是中文合同审核、中文客服分类或工业缺陷分析,建议先准备带有人工标签的中文测试集,检查分类准确率、漏判率、误判率以及不同阈值下的表现。

最后,生产环境还需要考虑模型版本。

学习阶段可以使用:

model="jev-latest"

这个别名指向最新稳定版本。

如果系统已经完成测试,并针对某个模型版本确定了业务阈值,可以考虑在生产环境中固定具体版本,避免模型更新后出现未验证的行为变化。

当然,固定版本时也应当确认服务商仍然提供该版本。

十、这套技术值不值得用?

回到最初的问题:为什么我们需要一个专门负责判断的模型?

因为在实际应用中,并不是所有问题都需要复杂推理。

有些任务只需要分类,有些任务只需要评级,还有些任务只需要判断一个条件是否成立。

如果把这些范围明确的任务全部交给通用大模型,虽然也能实现,但可能需要额外的提示词、结果解析和业务约束。

TypeSafe 提供了另一种方式:通过标准化的问题类型,直接获得程序能够使用的结构化结果,并允许开发者进一步利用概率和置信度设计业务流程。

不过,它是否比现有的通用大模型、传统分类模型或者专门的 Reranker 更合适,仍然要从准确率、延迟、成本和系统复杂度等方面进行实际比较。

对于已经拥有成熟分类模型的项目,没有必要仅仅因为出现了一种新技术就立即替换。

更合理的做法是,选择一个小范围的业务场景进行验证。

比如先拿出几百条已经标注的客服工单,分别使用现有模型和 TypeSafe 分类,再对比预测结果、平均延迟、调用成本和人工复核比例。

这样才能知道它究竟能够带来什么价值。

写在最后

从最初的提示词工程,到 Structured Outputs,再到今天介绍的 TypeSafe,我们能够看到 AI 应用开发中的一个变化:开发者越来越关注模型输出如何真正进入业务系统,而不只是模型能否生成一段看起来正确的回答。

在这篇文章中,我们从 TypeSafe 的基本概念入手,理解了 Choice、Score 和 Noul 三种判断类型,然后通过 Playground 完成第一次体验,使用 uv 搭建 Python 环境,并编写了一个智能客服分类器。

最后,我们还了解了如何使用置信度进行人工分流,以及如何把同样的思想应用在 RAG、Agent 和 AI 安全护栏中。

如果用一句话总结 TypeSafe 的核心价值,我认为是:

把 AI 的判断能力转化为结构化数据,再通过确定性的业务代码,完成真正可控的应用流程。

AI 不需要负责每一步,也不应该替代所有业务规则。让不同组件承担适合自己的工作,往往比试图用一个大模型解决全部问题更容易测试和维护。

对于正在开发智能客服、知识库、Agent 或企业 AI 平台的工程师来说,TypeSafe 提供了一种值得动手验证的实现思路。

代码跑通只是第一步,真正决定这套技术能否落地的,还是后续的数据评测、异常处理和工程化设计。

项目与学习资料

TypeSafe 官方文档:

👉https://docs.typesafe.ai/introduction

官方 Quick Start:

👉https://docs.typesafe.ai/introduction/quickstart

TypeSafe Playground:

👉https://console.typesafe.ai/playground

官方 Python SDK:

👉https://docs.typesafe.ai/sdk/python

关注我了解AI最新知识~

相关学习资料