Jev 1.13 的参差之处
Jev 1.13 的参差之处
Jev 并非完美。以下是我们在 jev-1.13 上已知的一些参差之处。其中许多将在后续版本中修复。
jev-1.13 快速、校准良好、擅长常识判断,但并非完美。jev-1.13 在 System One 任务上表现最好。它可能难以应付需要多一层间接的任务。它的理解可能相当字面。它不擅长需要数值精确度的任务。
失败模式详解
| # | 失败模式 | 改为这样做 |
|---|---|---|
| 1 | 字面理解 | 写出确切的判断条件,以及每个可用选项的判定标准 |
| 2 | 数学与数字 | 把算术留在代码里 |
| 3 | 日期与时间比较 | 抽取各个组成部分;在代码里比较 |
| 4 | 间接 | 减少跳转;指向相关的状态 |
| 5 | 充满无关细节的大状态 | 先过滤;只发送问题需要的内容 |
| 6 | 对抗性内容 | 写精确的提示词,并在部署前测试边界情况 |
| 7 | 互相矛盾的 instructions 和 criteria | 让 criteria 和 instructions 对齐 |
| 8 | 常识性的结构不变式 | 每个决策只从一个方向问;在代码里强制恒等关系 |
| 9 | 生成 | 使用生成式模型 |
字面理解
jev-1.13 回答的是你写下的问题,而不是你心里想问的那个。限定词、否定和隐含条件都按字面理解。模型会依据 instruction 中写下的字面来作答,而人可能会读出指令背后的意图。
改为: 在 instructions 里写明确切的条件。要具体。把边界情况放进 criteria。当你看到一个错误答案、忍不住要解释你真正想表达什么时,那段解释就是 instruction 缺失的另一半。在解释不可避免的地方,把它拆成两个字面问题,在代码里组合。
数学与数字
Jev 不是计算器。我们强烈建议把任何数学逻辑放在代码里实现。Jev 在语义问题上比在数学问题上表现更好。
计数
jev-1.13 数数不可靠。这包括单词里的字符数、某个词在段落中出现的次数,以及长列表中的项数。模型是在辨认答案的大致形状,而不是逐项累加,而且被数的东西越大,误差越大。
在提出计数问题之前,先问一句:为什么这个计数需要一个模型?如果被数的单位是正则表达式或解析器能找到的东西,那计数就该放在代码里,模型帮不上忙。
改为: 在代码里计数。想统计满足某些标准的项时,在代码里遍历候选项,每项问一个问题,然后自己把答案加起来。
from typesafe_sdk import Noul, TypeSafeClient
client = TypeSafeClient(model="jev-1.13")
YES = 0.5 # up to you on what you want the threshold to be, depends on your usecase.
items = ["typesafe", "apple", "california", "banana", "likes", "calibration", "orange", "vertex"]
result = client.system_one(
{"items": items},
{
f"item_{i}": Noul(instructions=f"Is `items[{i}]` the name of a fruit?")
for i in range(len(items))
},
)
count = sum(result.nouls[f"item_{i}"].noul > YES for i in range(len(items)))
数值表示
jev-1.13 在语义表示上比在数值表示上表现更好。例如,用十六进制值询问颜色,效果不如用英文颜色名。给定 RGB 三元组或十六进制值,它无法可靠地判断两个值是否相近。
同理,关于高级编程语言的问题,表现会好于关于底层汇编或二进制编码指令的问题。
改为: 在代码里做转换,传入算好的数字或命名的分桶。把模型留给真正属于判断的部分,比如某个颜色读起来是否像警告。
用 score 做数学
请不要用 score 的输出(例如期望和概率)去计算某个数在 criterion 两级之间的确切大小。你可以用期望来判断它是否越过某个阈值,但 jev-1.13 的 score 档位在数值校准上很弱。它无法通过在最近的两个档位之间插值来帮你还原确切的数字。
日期与时间比较
jev-1.13 把日期当作文本读,而不是有序的量。问两个日期哪个更早、相隔多远、或某个日期是否落在某窗口内,都不可靠。格式混用、相对指代,以及季度、结算窗口、计息期这类领域边界,会让情况更糟。
改为: 把工作拆开。抽取是判断,交给模型。算术不是,留在代码里。
日期的每一部分都是一个小范围闭集:十二个月、三十一种可能的日、有界的年份范围。这样抽取就变成在一个Choice 上对枚举选项的选择,而不是自由形式的解析,而且你还多了一个地方放显式的“未说明”选项,这样缺失的部分会被报告出来而不是被猜。代码再把各部分组装成真正的日期,并接管之后的一切,包括排序、时长、偏移和星期。
完整示例见日期抽取 cookbook,包括相对日期和置信度门控。
间接
带有双重否定或复杂间接的指令,回答的可靠性更低。关于“属性的属性”,或需要多跳推理的问题,都会损失准确率。
改为: 把指令写得尽可能直接。尽可能按名字指出状态中相关的部分。
充满无关细节的大状态
当状态里塞进与决策无关的内容时,准确率会下降。无关细节会充当干扰项,而庞大的状态会让你更难判断是输入的哪一部分导致了错误答案。
改为: 先在代码里检索和过滤,只发送问题需要的字段。当无法在 state 里过滤时,可以用 Noul 过滤相关性。对 RAG 段落分类的 cookbook 有一个完整示例。
对抗性内容
状态是数据,jev-1.13 默认不把它当作敌意的。为了对抗性地操控模型而写的内容——无论是注入的指令、刻意误导的框定,还是为自己的分类辩护的文本——都可能改变答案。我们期望未来在这方面有所改进。
改为: 在 criteria 里写清楚。在部署给大量用户之前,充分测试你的集成。
互相矛盾的 instructions 和 criteria
当 instructions 和 criteria 要求的是不同的东西时,jev-1.13 可能会困惑。最好的表现来自清晰的措辞。例如,一个让 true 映射为“否”、false 映射为“是”的 Noul,表现会更差。目标是让普通人也能轻松读懂你的 instructions。
改为: 把 criteria 当作 instruction 的延伸。用清晰精确的语言把两者对齐。
常识性的结构不变式
jev-1.13 高度一致,也就是说,对于语义相似的输入,你应该预期得到数值上相近的输出。
然而,有许多你可能以为成立的结构不变式,模型根本并不保证。
例如,在工单 “I’m not happy with the fit. What are my options here?” 上,把“客户是在要求退款吗?”分别问成 Noul 和是/否 Choice:
Noul noul |
Choice yes |
Choice no |
Choice confidence |
|---|---|---|---|
| 0.22 | 0.01 | 0.99 | 0.97 |
可比较的数字是 noul 和 probabilities["yes"],而如何把 Choice 的输出和置信度解释成 Noul 问题的答案(或反过来),并不显然。
同一个问题及其否定——“客户是在要求退款以外的东西吗?”——作为两个 Noul,在工单 “I was charged twice for the same order. Can someone look into this?” 上:
refund |
not_refund |
合计 |
|---|---|---|
| 0.72 | 0.47 | 1.19 |
P(noul) 和 1 - P(not noul) 不能直接比较,原因有很多。
改为: 不要依赖你以为成立的结构不变式,把问题措辞成直接表达你想要的意思。不要把在 Noul 上调好的阈值搬到 Choice 上,也不要拿分开的问题之间要求模型满足算术恒等式。一个针对选项的 Choice 和每个选项一个 Noul,回答的是不同的东西:Choice 是相对的,用来确定哪一个选项,而每个 Noul 是绝对的,可以对所有选项都很低。技能建议 cookbook 在同一个候选列表上同时用了两者,用 Choice 挑选技能,用 Noul 决定到底要不要建议一个。
生成
jev-1.13 没有为生成文本而训练。虽然你可以通过串联 choice 强迫它生成,但效果不好而且会很慢。对于数据抽取,更好的做法是用正则表达式或生成式模型抽出可能的选项,再让 jev-1.13 挑出正确的那个抽取结果。
改为: 当答案空间有界时,把抽取变成在选项上的 Choice,而不是直接问那个值本身。如果你真的需要生成文本……那有别的模型来做这件事。