自然语言点单:转成结构化购物车
💡 一句话总结:用 Jev 把一句话点单转成结构化购物车 —— Choice 收缩选项循环找出每样商品,再对每样商品发一批请求填齐字段,最后由代码拼装进你的订单系统。
顾客会说「Can I get a large oat milk latte and a blueberry muffin please」(大杯燕麦奶拿铁加一个蓝莓麦芬,谢谢),但你的收银系统需要的是一件件分开、字段各就各位的结构化购物车。官方 Shopping cart cookbook 的解法只用 Choice 选择题这一种题型,分两段完成自然语言转结构化:
- 找商品:商品数量事先不知道,就用一个收缩选项循环——每轮问「订单里最先提到的是哪样剩余商品」,选中一样就从下一轮的选项里删掉,直到模型选出哨兵选项
nothing_else。 - 填字段:知道了每样商品,也就知道了它有哪些字段(拿铁有 size 和 milk),每样商品一次批量请求把所有字段题并行问完。
官方实测(jev-1.14.0,2026-10-29):3 次请求找齐 2 样商品(拿铁 0.99、蓝莓麦芬 1.00、哨兵 1.00),再加 1 次请求填完拿铁两个字段(large 1.00、oat 1.00)——一共 4 次请求拼出整个购物车。本课约 15 分钟整套跑通,而且下载官方缓存后不设 API Key 也能复现官方全部数字(本页实测通过)。
学完你能做什么
- 写出
find_items(order):给一句自然语言订单,不管她点了几样,循环找出每样商品、自带把握度,nothing_else哨兵兜住「点完了」 - 写出
fill_fields(order, item):每样商品一次请求并行填齐所有已知字段,顾客没提的字段明确答unspecified,而不是脑补一个值 - 把菜单写成纯数据(描述 + 字段 schema):加商品、加字段改字典就行,问题一个字不用动
- 不花一分钱复现官方数字:官方
json_cache.json缓存重放,重跑零请求
为什么用 Jev,而不是让 LLM 直接生成购物车 JSON?
「让 LLM 把这句话解析成 JSON 购物车」是很多人的第一反应——能跑,但你拿到的是一段要祈祷的文本。
| 能力 | 让 LLM 生成 JSON | Jev 收缩选项循环 |
|---|---|---|
| 商品数量 | ❌ 「她点了几样」要靠模型数,数错就漏项多项 | ✅ 循环一次找一样、找完自动停,件数由代码数 |
| 字段值合法性 | ❌ 可能生成 venti、燕麦奶——不在你的菜单里 | ✅ 选项就是合法值(size ∈ small/medium/large),答案永远落在选项里 |
| 没提的字段 | ❌ 倾向于替顾客补一个「默认中杯」 | ✅ unspecified 选项明确报「订单没说」,交给你按默认规则处理 |
| 下游解析 | ❌ JSON 解析失败、幻觉字段,层层校验 | ✅ 类型化答案 + 概率分布,代码直接用 |
| 把握度 | ❌ 要追问「你确定吗」 | ✅ 每个判断自带 confidence,低置信送店员人工确认 |
一句话:LLM 会替你重写订单,Jev 只替你读订单——每样商品、每个字段都是一次可校准的选择题。
你现在的困境
- 「让 LLM 输出购物车 JSON,十次有九次对,漏掉的那次是顾客点了三样它只吐两样——投诉都找不到是哪行代码的错」
- 「顾客说『来杯拿铁』没说大小,模型每次都自信地编一个 medium 写进订单」
- 「菜单一上新,解析 prompt 就要跟着改一遍,改完还得全量回归测试」
什么时候用这一招
当你需要:
- 把一句自然语言变成结构化数据:点单、配置项、表单填写、商品属性选择
- 候选集合是已知的闭集——菜单是你定的,字段合法值是你定的
- 数量不定:可能点 1 样,可能点 5 样,事先不知道
而且不想:
- 解析 LLM 吐出来的 JSON,再写一层「它是不是又编了」的校验
- 让生成模型做计数——官方踩坑手册明说计数不可靠,误差随规模增大
- 每次菜单变动都重调 prompt
🎒 开始前的准备
- 完成了 Choice 选择题:会写
criteria选项 map、读得懂choice和confidence,知道一题最多 255 个选项 - 建议读过 Confidence 置信度:知道低置信答案怎么转人工复核
- 跑通过安装与第一个请求:
.venv可用。本课全程不设 Key 也能跑(官方缓存重放);想 live 跑设TYPESAFE_API_KEY - 一杯水 ☕——本课是一个完整小项目:一个循环加一批题,把「一句话」变成「购物车」
跟我做
先说好怎么跑:新建 cart.py,把下面每一步的代码块按顺序贴进同一个文件,每完成一步运行一次 python cart.py。所有 API 调用走 json_cache.json 缓存,重复运行零花费。
第 1 步:装环境、下官方缓存,备好菜单和订单
为什么:官方为这个案例录制了全部 4 次请求的答案缓存 json_cache.json,放对位置就能不调 API 复现官方全部数字;没有它则设 TYPESAFE_API_KEY 真跑。
安装依赖(官方 cookbook 原命令;cooksafe 是官方配套工具库,PyPI 自述「Shared helpers for the TypeSafe cookbooks」,它的依赖声明里带 typesafe-sdk<0.8.0,>=0.7.0,所以 SDK 不用单独写):
pip install ipython 'cooksafe>=0.2.0,<0.3.0'下载官方缓存(raw 直链;不设 Key 复现官方数字全靠它):
curl -sL -o json_cache.json https://raw.githubusercontent.com/typesafe-ai/typesafe-public-examples/main/cookbooks/cart_from_primitives/json_cache.json新建 cart.py,贴入文件头——客户端、缓存、常量:
import os
from pathlib import Path
from cooksafe import JsonCache, make_playground_link
from IPython.display import Markdown, display
from typesafe_sdk import Choice, TypeSafeClient
TYPESAFE_MODEL = "jev-1.14.0" # 官方数字的录制版本
NOTHING_ELSE = "nothing_else" # the sentinel option that ends the item loop
MAX_ITEM_REQUESTS = 6 # a hard stop, so a bad answer can never loop forever
client = TypeSafeClient(
api_key=os.environ.get("TYPESAFE_API_KEY", "cache-only"), # cached re-renders need no key
model=TYPESAFE_MODEL,
timeout=30.0,
)
json_cache = JsonCache(Path("json_cache.json"))
def fmt_confidence(confidence: float | None) -> str:
"""A confidence for printing. The API can return None, so never format it blind."""
return f"{confidence:.2f}" if confidence is not None else "n/a"
print("setup ok")运行 python cart.py。
你应该看到:setup ok——还没发任何请求。
三个名字先记住:NOTHING_ELSE 是结束循环的哨兵选项;MAX_ITEM_REQUESTS = 6 是硬上限——官方注释写得很清楚,防的是一个坏答案让循环永远停不下来;fmt_confidence 提醒你 confidence 可能为 None,别盲格式化。
setup ok打印出来了,json_cache.json就在运行目录里
第 2 步:把菜单写成数据——描述给 Jev 看,字段就是选项
为什么:自然语言转结构化的「结构」住在哪里?官方的答案是一个字典:每个商品的描述写上顾客会怎么点它(latte 也被叫 flat white 或 milky coffee),fields 是它自己的 schema——字段名映射到合法值列表,而这些值就是那道字段题的 criteria 选项。菜单是数据不是 prompt,上新改字典就行。
贴入菜单和订单:
MENU = {
"latte": {
"description": "Espresso with steamed milk. Also ordered as a flat white or a milky coffee.",
"fields": {
"size": ["small", "medium", "large"],
"milk": ["whole", "oat", "almond"],
},
},
"filter_coffee": {
"description": "Plain brewed drip coffee, sometimes ordered as a black coffee.",
"fields": {},
},
"blueberry_muffin": {
"description": "A blueberry muffin.",
"fields": {},
},
"almond_croissant": {
"description": "An almond croissant, sometimes ordered as a pastry.",
"fields": {},
},
}
ORDER = "Can I get a large oat milk latte and a blueberry muffin please"两个设计点:
- 描述承载点单用语:Jev 拿订单和这些描述做匹配——顾客说「a milky coffee」,命中的是 latte 的描述,不是这个词的字面。这就是为什么描述要写「顾客会怎么说」而不是「这是什么」
- 只有 latte 有字段:size 和 milk 各自是闭集;其余三样没有字段,第 4 步会直接跳过它们的请求
运行 python cart.py。
你应该看到:还是只有 setup ok——菜单只是数据定义,一个请求都没发。
- 我能说出
MENU里 description 和 fields 各自的作用,以及为什么描述要写点单的同义词
第 3 步:收缩选项循环——自然语言转结构化的第一段,找出每样商品
为什么:顾客点几样事先不知道。直接问「她点了几样」是让模型做计数——官方踩坑手册(Jev 1.13 版,9 种失败模式见 Jev 1.13 踩坑手册)明说:Jev 不可靠地计数,误差随被数对象的规模增大;替代做法是代码迭代候选、每个一问。收缩选项循环就是这个做法:每轮一道 Choice 问「订单里最先提到的是哪样剩余商品」,选中就存下并从下轮选项里删掉,把整句话原样再发一遍。这也是官方判据下的真依赖——官方原话:只有当代码拿到上一个答案才能构造下一个请求(比如决定下一题的选项)时,第二次请求才是真依赖。
先看循环全貌,再贴代码:
第 1 轮 选项 = latte / filter_coffee / blueberry_muffin / almond_croissant + nothing_else
→ latte (0.99) 存下,从下轮选项里删掉
第 2 轮 选项 = filter_coffee / blueberry_muffin / almond_croissant + nothing_else
→ blueberry_muffin (1.00) 存下,从下轮选项里删掉
第 3 轮 选项 = filter_coffee / almond_croissant + nothing_else
→ nothing_else (1.00) ← 哨兵被选中,循环停贴入问题构造器、单次请求函数和主循环:
def item_question(remaining: dict[str, dict], found: list[str]) -> Choice:
"""Build one request's question from the items not found yet."""
already = ", ".join(found) if found else "nothing yet"
criteria = {name: item["description"] for name, item in remaining.items()}
criteria[NOTHING_ELSE] = (
"The order mentions no menu item other than the ones already accounted for."
)
return Choice(
instructions=(
f"This is a cafe order. Items already accounted for: {already}. "
"Which remaining menu item does the order mention? If the order mentions more "
"than one remaining item, choose the one mentioned first."
),
criteria=criteria,
)
@json_cache
def ask_item(order: str, question: dict) -> dict:
"""One item request. The question arrives as its API JSON, which also keys the cache."""
answer = client.system_one(state=order, questions={"item": question}).choices["item"]
return {"choice": answer.choice, "confidence": answer.confidence}
def find_items(order: str) -> list[dict]:
remaining = list(MENU)
found: list[dict] = []
item_requests = 0
for _ in range(MAX_ITEM_REQUESTS):
if not remaining:
break
question = item_question(
{name: MENU[name] for name in remaining},
[item["name"] for item in found],
)
result = ask_item(order, question.model_dump(mode="json", exclude_none=True))
item_requests += 1
print(
f"item request {item_requests}: {len(remaining)} items + sentinel "
f"-> {result['choice']} (confidence {fmt_confidence(result['confidence'])})"
)
if result["choice"] == NOTHING_ELSE:
break
remaining.remove(result["choice"])
found.append({"name": result["choice"], "confidence": result["confidence"]})
return found
items = find_items(ORDER)
print(f"\nfound {len(items)} items: {[item['name'] for item in items]}")运行 python cart.py——全部命中官方缓存,一个请求都不发。
你应该看到(官方 jev-1.14.0 录制;本页实测逐字复现):
item request 1: 4 items + sentinel -> latte (confidence 0.99)
item request 2: 3 items + sentinel -> blueberry_muffin (confidence 1.00)
item request 3: 2 items + sentinel -> nothing_else (confidence 1.00)
found 2 items: ['latte', 'blueberry_muffin']四个设计点值得停下来看:
- 哨兵是循环的刹车:Choice 必须选一个选项,没有「都不选」——所以每轮都带
nothing_else,它的描述写明「订单里没有提到已算过之外的商品」。选中它,循环停 - instructions 报进度:「Items already accounted for: nothing yet → latte → latte, blueberry_muffin」——每轮告诉模型前面找到了什么,避免它重复报已找到的商品
- 「最先提到的选一个」消歧:订单提到多于一样剩余商品时,只选最先提到的那样——确定的规则,不是让模型自由发挥
- 三重保险的退出:哨兵被选中、菜单清空、
MAX_ITEM_REQUESTS上限——循环一定会停
💡 这就是 Jev 的独有价值
这是软件循环,不是 agent 循环——官方构建指南明说「能用软件工作流表达的,就别用 agent 的 while 循环」。控制流、退出条件、去重全在你的代码里,模型每轮只做一件极窄的事:在当轮选项里挑一个。挑错了,代码的硬上限兜底;挑对了,confidence 告诉你这次挑选有多稳。
- 零 Key 跑出 3 行 item request 和 found 2 items;我能说出循环的三个退出条件和哨兵选项的作用
第 4 步:每样商品一批量请求填字段
为什么:商品找齐后,每样商品该问哪些字段就确定了——拿铁有 size 和 milk,麦芬没有字段。官方的填法是每样商品一次请求带上它全部字段题(fan-out 模式:多题对同一 state 并行评估),而不是一个字段一次请求。每个字段题还带 unspecified 选项——顾客没提的字段明确答「订单没说」,而不是被迫挑一个具体值。
贴入字段题构造和填空代码:
UNSPECIFIED = "unspecified"
def field_questions(item_name: str) -> dict[str, Choice]:
questions = {}
for field, values in MENU[item_name]["fields"].items():
criteria = {value: None for value in values}
criteria[UNSPECIFIED] = (
f"The order does not say which {field} for the {item_name}."
)
questions[field] = Choice(
instructions=f"Which {field} did the order ask for, for the {item_name}?",
criteria=criteria,
)
return questions
@json_cache
def ask_fields(order: str, questions: dict[str, dict]) -> dict:
"""One field request. The questions arrive as their API JSON, which also keys the cache."""
response = client.system_one(state=order, questions=questions)
return {
field: {"choice": answer.choice, "confidence": answer.confidence}
for field, answer in response.choices.items()
}
def fill_fields(order: str, item_name: str) -> dict:
if not MENU[item_name]["fields"]:
return {}
questions = {
field: question.model_dump(mode="json", exclude_none=True)
for field, question in field_questions(item_name).items()
}
return ask_fields(order, questions)
cart = []
for item in items:
fields = fill_fields(ORDER, item["name"])
cart.append(
{"name": item["name"], "confidence": item["confidence"], "fields": fields}
)运行。拿铁发 1 次请求(size + milk 两题并行),蓝莓麦芬 fields 为空——直接跳过请求。加上第 3 步的 3 次,全案例共 4 次请求。
你应该看到:没有新输出——这一步只把 cart 列表在内存里拼好(拿铁带着两个字段答案,麦芬 fields 为空字典),第 5 步才打印。
- 我能说出为什么麦芬不发请求、
unspecified选项解决的是哪类「脑补默认值」问题
第 5 步:代码拼装结构化购物车
为什么:拼装是纯代码的活,一次 API 都不发。每样商品带自己的 confidence,每个字段也带——哪个判断拖后腿一目了然。
贴入打印代码:
print(f'order: "{ORDER}"\n')
for line in cart:
print(f"{line['name']} (item confidence {fmt_confidence(line['confidence'])})")
for field, answer in line["fields"].items():
conf = fmt_confidence(answer["confidence"])
print(f" {field:<6} {answer['choice']:<12} confidence {conf}")运行。
你应该看到(官方 jev-1.14.0 录制;本页实测逐字复现):
order: "Can I get a large oat milk latte and a blueberry muffin please"
latte (item confidence 0.99)
size large confidence 1.00
milk oat confidence 1.00
blueberry_muffin (item confidence 1.00)对照第 2 步的菜单 schema 检查:商品是菜单里的合法 key,size 是 large(合法值之一),milk 是 oat(合法值之一)——不可能出现菜单外的商品或字段值,因为答案只能从选项里选。这就是「结构化」的底气:下游订单系统拿到的永远是 schema 内的数据。
- 我的输出和官方数字逐字一致:latte 0.99 / large 1.00 / oat 1.00 / blueberry_muffin 1.00
📋 魔法 Prompt
本页的「Prompt」是给 API 的问题模板——抄走、替换【】占位符(带 ? 的是选填)就能接到你自己的菜单或商品目录上。三件套:找商品题、填字段题、循环骨架。
📝 找商品题(Choice 收缩版)
预期效果:凡是「从一句话里找出所有命中的已知条目」的需求——点单、选配置项、勾选服务——都套这一题,放进循环里逐个找出。
from typesafe_sdk import Choice
# 必填项:remaining 传还没找到的商品(名字 -> 顾客会怎么点它的描述)
criteria = {【name】: 【商品描述,写顾客的同义叫法】 for name in 【remaining】}
criteria[【哨兵名】] = "【订单里没有提到已算过之外的商品】"
item_q = Choice(
instructions=(
f"【这是什么场景的一句话。已算过的:{【found 或 'nothing yet'】}。】"
"【订单里最先提到的剩余商品是哪样?提到多件时选最先说的】"
),
criteria=criteria,
)
# 选填项:场景词换掉 cafe order——配置单、服务预约、商品咨询?
# 输出规范:answer.choice 是商品名或哨兵名;answer.confidence 接复核线
# 约束条件:
# ✅ 描述写「顾客会怎么点它」,同义词写进去(flat white 也是 latte)
# ✅ 每轮把已找到的报进 instructions,防止重复报
# ❌ 别问「她点了几样」——计数交给循环,模型只做挑选✅ 填字段题(字段 schema 版)
预期效果:把每样商品的字段合法值变成一题一题的 Choice,一次请求并行问完;顾客没提的字段明确报 unspecified。
# 必填项:fields 是该商品的 schema:字段名 -> 合法值列表
questions = {}
for field, values in 【商品["fields"]】.items():
criteria = {value: None for value in values}
criteria[【"unspecified"】] = f"The order does not say which {field} for the {【商品名】}."
questions[field] = Choice(
instructions=f"【订单为这个商品点了哪个 {field}?】",
criteria=criteria,
)
# 选填项:unspecified 的下游处理——按你的默认值规则补,或转人工确认?
# 输出规范:每字段 answer.choice ∈ 合法值 ∪ {unspecified},各带 confidence
# 约束条件:
# ✅ 选项就是函数/系统接受的合法值——答案不可能越界
# ✅ 没有字段的商品跳过请求,别发空请求
# ❌ 不给 unspecified = 逼模型编一个值🔧 循环骨架(代码版)
预期效果:找齐不定数量的条目、防死循环、缓存省钱——一段纯代码,可单测。
MAX_REQUESTS = 【6:硬上限,防坏答案死循环】
remaining, found = list(【MENU】), []
for _ in range(MAX_REQUESTS):
if not remaining:
break
result = ask(【order】, build_question(remaining, found))
if result["choice"] == 【哨兵名】:
break
remaining.remove(result["choice"])
found.append(result)
# 输出规范:found 是 [{name, confidence}, ...];件数 = len(found),由代码数
# 约束条件:
# ✅ 三个出口缺一不可:哨兵、候选清空、硬上限
# ✅ 请求函数挂 @json_cache——改菜单/改问题会换缓存键自动真跑,重跑零花费
# ❌ 别把循环交给模型自己「决定何时结束」——退出条件是代码的事检查点 ✅
- 不设
TYPESAFE_API_KEY、放好官方json_cache.json,我逐字复现了官方全部数字:latte 0.99 / blueberry_muffin 1.00 / nothing_else 1.00 / size large 1.00 / milk oat 1.00 - 全案例共 4 次请求:3 次找商品(含 1 次哨兵)+ 1 次填拿铁字段;麦芬没发请求
- 我能说出为什么用循环而不是问「点了几样」:计数不可靠,代码迭代 + 每个一问才是官方替代做法
- 我能解释这是「真依赖」:下一轮的选项要等上一轮的答案才能构造——这正是官方判据认可第二次请求的情形
- 我知道
unspecified和nothing_else的分工:前者是字段没说,后者是商品找完了
踩坑提醒
❌ 让模型输出整个购物车 JSON
一次生成把计数、字段合法性、格式三件事搅在一起:数错件、编造 venti 这种菜单外的值、JSON 解析失败——错了都不知道错在哪一环。官方拆法让每件事单独可测:件数由循环数、合法性由选项保证、拼装由代码做。生成模型做不了这个保证,因为它的每个字都是重新打出来的。
❌ 忘了哨兵选项或硬上限
没有 nothing_else,Choice 被迫在剩余商品里硬挑一个——点完的订单会「多出」一件。没有 MAX_ITEM_REQUESTS,一个坏答案能让循环永远停不下来。两个都写上,循环才既正确又必然终止。
❌ 顾客没说的字段,模型替她选了
不给 unspecified 出口,模型只能挑一个具体值——「来杯拿铁」会自信地变成 medium whole milk latte。官方的解法就是每道字段题带 unspecified,下游按你的默认值规则补或转店员确认。同场景的另一个官方做法见 Agent 决策:函数调用 cookbook 用一道单独的是非题判断「用户提没提这个参数」,两种出口选一种。
❌ 直接拿中文订单上线
官方说明:Jev 主要用英语训练,英语准确度最好;其他语言(含中文)能用但准确度较低——上线前先拿自己的中文订单跑一批看概率分布,重点关注 confidence,语言支持说明见模型与价格。另外改菜单或改问题会换缓存键:cooksafe 的缓存键由函数名和参数构成,改 MENU 后重跑会自动真请求(设了 Key 才会成功),想强制重跑就删掉 json_cache.json。
进阶技巧(可选)
数量:加一个 quantity 字段。 官方明说本例的局限:购物车没有数量字段,「two flat whites」也只产出一件 latte。官方给的解法:给每样商品的 schema 加 quantity 字段,合法值如 one / two / three——第 4 步的批量请求会自动把它一起问了。
大菜单:先分块再挑。 一道 Choice 最多 255 个选项(Choice 选择题有完整说明)。菜单更大时先挑区块(哪个类目),再挑区块内的商品——每段都在 255 以内。搜索与匹配的逐行搜索是同一思想的实战:给 218 行各标 ID,让 Choice 指向匹配的行。
免代码先试。 官方 cookbook 页面底部有做好的 Playground 分享链接——完整订单 + 第一轮找商品题(四样商品加哨兵),点开(https://console.typesafe.ai/playground)改订单措辞,答案跟着变。想生成自己的链接:
playground_link = make_playground_link(ORDER, {"item": item_question(MENU, [])})
# Print a usable URL in a script; render a clickable link in a notebook.
if __name__ == "__main__" and "__file__" in globals():
print(f"Open in the TypeSafe playground:\n{playground_link}")
else:
display(Markdown(f"🔗 [Open the first item-finding request in the TypeSafe playground]({playground_link})"))链接生成离线完成、不需要 API Key;URL 里带着完整 state 和问题,别放敏感数据。看官方实拍:TypeSafe shopping cart demo。
接进你的点单流。 把 ORDER 换成聊天消息、语音转写、表单备注,MENU 换成你的商品目录;答案结构不变,下游订单系统照单全收。字段多了成本涨?并行提问与投机扇出实测过批量提问的收益:13 题一次请求比逐题问 12.2 倍便宜、10.0 倍快,答案不变。
本课小结
✅ 自然语言转结构化,官方拆成两段:收缩选项循环找商品(件数由代码数,nothing_else 哨兵刹车),每样商品一批量请求填字段(合法值就是选项,unspecified 报「没说」)。
✅ 每个判断可校准:商品 0.99 / 1.00、字段 1.00 / 1.00——低置信的判断送店员人工确认,而不是硬进订单。
✅ 官方数字零 Key 复现:4 次请求(3 找商品 + 1 填字段)全部命中官方缓存,本页实测逐字重放。
✅ 菜单是数据不是 prompt:上新改 MENU 字典,问题模板一个字不动;改了会自动换缓存键真跑。
关键配置字段回顾:
| 字段 | 本页的值 | 说明 |
|---|---|---|
TYPESAFE_MODEL | "jev-1.14.0" | 官方数字录制版本(2026-10-29);live 跑锁版本 ID,别用会漂移的 jev-latest |
NOTHING_ELSE | "nothing_else" | 哨兵选项:订单里没有剩余商品时被选中,循环停 |
MAX_ITEM_REQUESTS | 6 | 硬上限:哨兵、菜单清空之外的第三重保险 |
UNSPECIFIED | "unspecified" | 字段没提时的出口,防模型脑补默认值 |
MENU | 4 样商品,仅 latte 有 size/milk | 描述写顾客的点单叫法;fields 即 schema |
| 每单请求数 | 找商品 N+1 次 + 每样有字段的商品 1 次 | 本例 3+1=4 次;全走缓存,改菜单/改题才 miss |
相关教程:
- Agent 决策:挑技能、转函数调用——同一个「一句话变结构化调用」思想用在函数上:一道 Choice 选函数,每参数一题填值;没提的参数用是非题出口
- 值提取:日期、邮箱、电话、金额——同在「文档与数据」路线:值只能来自原文,正则找候选、Jev 挑对的那个
- 并行提问与投机扇出——字段题为什么批量发:13 题一次请求 12.2 倍便宜、10.0 倍快
下一课预告
一句话点单变成了购物车,下一个问题是一大堆候选里哪几条真正匹配。下一课:搜索与匹配:重排序、逐行搜索、实体对齐。
你会学到:
- 重排序把 CLERC 法律查询 top-1 命中从 5% 提到 18%、top-10 从 38% 提到 62%
- GitHub ToS 218 行逐行语义搜索:给每行标 ID,一道 Choice 指向匹配的行——本页「选项即候选」的大规模版
- 两份啤酒目录 450 个候选对怎么用一道 Score 加三道 Noul 找出同款