第 17 章:电商市场与广告——E-commerce marketplaces / Advertising
第 17 章:电商市场与广告——E-commerce marketplaces / Advertising
电商和广告是 Jev 落地最密集的两个场景,原因很直接:判断量极大、判定标准又大多能用一句话讲清。"这个字段对不对得上""这条 listing 算不算违规""这条评论在夸还是在骂",都是能被类型化、被批量执行的判断。本章用几个真实项目讲清商品归类、属性对齐、买家意图与广告合规的工程做法。
电商判断的共同结构
把电商里的判断摊开,会发现它们反复出现同一种结构:一堆候选对象,一个标准,逐条判定。商品字段要映射到目标表的列,listing 要对照规则查违规,评论要归到某个主题,商品要挂到类目树的某个节点。这类任务的输出空间是封闭的,天然适合 Jev。
底下还叠着一层分层执行:先用确定性的规则或字符串匹配把能定的定掉,只剩真正模棱两可的项才交给 Jev。这个模式在电商里到处出现,因为电商数据噪声大、规则明确的占比高,先跑规则能省下大量判定。
商品属性抽取与表格导入映射
jev-table-import-mapper(DuvInc/jev-table-import-mapper)是理解这个模式的好例子。它解决的问题很具体:把一份上传 CSV 的列,映射到目标表的列上。
它分两层执行。第一层是严格的确定性名称相等匹配——列名完全一致的直接映射,不问模型。第二层才对剩下的 (source, destination) 配对,逐对问一个 Noul:"这一列是不是对应目标表的这一列?",并且给每个来列加一个 guard Noul 做保护。
实测数据值得记下来:一个 23 列的导出文件里,它一次调用问了 253 个问题,映射对了 10 of 10 列,耗时 915 ms,成本 $0.0012。关键在于阈值设计——低于 0.75 的映射不猜,直接留在界面上让人看。宁可让用户手动确认几列,也不把不确定的映射悄悄写进去。这和合规里的 fail-closed 是同一个思路。
# 第一层:代码里的确定性匹配
mapping = {}
remaining_src = []
for src in source_columns:
same = [d for d in dest_columns if normalize(src) == normalize(d)]
if same:
mapping[src] = same[0] # 名称相等,直接定
else:
remaining_src.append(src)
# 第二层:只对剩下的配对问 Jev
questions = {}
for s in remaining_src:
for d in dest_columns:
questions[f"{s}__{d}"] = {
"type": "noul",
"question": f"源列“{s}”是否对应目标列“{d}”?"
}
d = client.systemone(
state=build_state(remaining_src, dest_columns, sample_rows),
questions=questions,
instructions="你是数据导入助手,只看列名与样例值判断对应关系,拿不准判否。"
)
for key, ans in d.items():
s, dst = key.split("__")
if ans.probability >= 0.75: # 0.75 以下不猜
mapping[s] = dstAI-decision-maker(zlZayn/AI-decision-maker)做的是邻近的事:用 Choice 把 CSV 的列归入一个 13 种类型的编码表,再把整个数据集归到 6 种场景之一,所有写入都在本地执行。它有一个反直觉的实测结果:在这类任务上,Jev 的 token 成本是 LLM 的 6.6–12.7 倍。原因不是 Jev 变贵了,而是这个任务里每个问题都要重复一遍判定标准("这个列名是否符合以下的 13 类定义……"),标准文本被逐列重复发送,token 反而上去了。
这个数字很有价值——它是一份诚实的失效边界。Jev 省的是"生成"的钱,不是"输入"的钱。 当任务的特点是问题短、标准长、还要对每一列重复标准时,token 成本可能反而更高。判断要不要用 Jev,不能只看"决策比生成便宜"这句话,要看你发出去多少 token。
类目树映射:分层 Choice 与兜底桶
商品的类目树往往很深——"服饰 > 男装 > 上衣 > 卫衣 > 连帽卫衣"。指望模型一次输出完整路径,等于让它在一个组合爆炸的空间里做单一选择。更稳的做法是把类目树拆成逐层 Choice:先在第一层选大类,再在选中的大类下选子类,一层层收敛。
CATEGORY_TREE = {
"服饰": ["男装", "女装", "童装"],
"男装": ["上衣", "裤装", "鞋靴"],
"上衣": ["卫衣", "衬衫", "T恤"],
}
def classify_path(title, tree, root_labels):
path, candidates = [], root_labels
while candidates:
d = client.systemone(
state={"title": title, "path_so_far": path},
questions={"pick": {
"type": "choice",
"question": f"「{title}」应归入以下哪一类?",
"choices": candidates + ["以上都不是"],
}},
instructions="你是电商类目归类助手,只按商品标题判断,拿不准选「以上都不是」。"
)
if d["pick"].choice == "以上都不是" or d["pick"].probability < 0.7:
break # 拿不准就停,回落到人工队列
chosen = d["pick"].choice
path.append(chosen)
candidates = tree.get(chosen, [])
return path逐层判定的好处是每一层的候选只有几个,判定更准;代价是要多轮请求,所以现实里常见的是把确定的前几层用规则表定掉(品牌到类目的固定映射),只对模糊层问 Jev。
文档侧有同类做法的印证:DocJev(jerryjliu/docjev)用自然语言写的类目规则把文档归类,40 篇文档的试点全部 40/40 判对,Jev 决策的 p50 约 182 ms。规则用自然语言表达、类别可以随目录调整,这对类目经常变动的电商目录很实用。Tab Sorter(AstonyCat/jev-tab-grouper)的兜底桶策略同样该抄:分不出来的项不要硬塞进某个类目,落进一个"待归类"桶,等人工或后续规则处理。
买家意图与商品匹配
买家侧也是一堆类型化判断。hearth-jev-rental-search(Nancy-Chauhan/hearth-jev-rental-search)是个多源租房搜索的例子:它自主地从多个来源聚合房源,让 Jev 逐条判定"这条房源是否符合用户条件"。把"房源"换成"商品",就是电商里的搜索匹配——把筛选条件写成自然语言("预算 500 以内、全新、支持七天无理由"),对每个候选商品问一个 Noul,命中的进候选集。
这里有个和类目树相反的策略取舍:类目树要唯一归属,所以用 Choice 收敛到一条路径;买家筛选要多标签,一条商品可能同时"符合预算"又"符合成色要求",所以拆成一串独立的 Noul,各判各的。第 2 章讲过 Choice 和多个 Noul 的区别,电商场景里这两种用法几乎一半一半。
条件本身还经常是"半结构化"的——有的能直接比数字(预算、库存),有的只能靠语义("看起来不像正品""描述有夸大")。工程上的做法是把能算的用代码算,算不了的转成自然语言陈述交给 Jev,两者结果在代码里合并成一个候选集。
评价与买家意向的行级标注
电商的第三类判断落在用户生成内容上。Feed Lens(SkywalkerDarren/feed-lens)是个直接可参考的例子:它用 Jev 的 Noul 判定,对 Weibo、Threads、X 上的帖子打每个平台、用户自定义的主题词和表达标签。
这里的要点是"用户自定义标签"——标签不是预先写死的枚举,而是每个用户自己写的一串陈述(比如"在询问价格""在投诉物流"),Jev 逐条判断这条帖子是否符合。这其实就是把 Detection 形态用户化了:一个标签一个问题,返回一个概率。
user_labels = [
("询问价格", "这条帖子是否在向他人询问价格或优惠?"),
("物流投诉", "这条帖子是否在抱怨发货慢或物流问题?"),
("买家秀", "这条帖子是否在展示自己收到的商品?"),
]
questions = {
f"label_{i}": {"type": "noul", "question": q}
for i, (_, q) in enumerate(user_labels)
}
d = client.systemone(
state=post_text,
questions=questions,
instructions="你是社媒内容标注助手,逐条判断帖子是否符合给定标签,不做推测。"
)
hits = [label for i, (label, _) in enumerate(user_labels)
if d[f"label_{i}"].probability >= 0.6]注意这是多标签——一条帖子可能同时命中"询问价格"和"买家秀",所以用多个 Noul,不是一个大 Choice。
同样的模式可以搬到后台数据表上。Vibefilter(vibefilter/filament)是个 Filament 后台的表格过滤器:它对每一行问一个 Noul,题干就是一句大白话,比如 "The customer is angry.",把概率达到 0.8 的行留在筛选结果里。它的实测很具体:在 1,000 条评论里,判定结果与 demo 自带的情绪标签吻合 861 条,每条陈述约 $0.003、一秒,判定按内容缓存。查差评、查疑似刷单、查需要人工复核的 SKU,无非是换一句陈述而已——业务规则写成自然语言,一行一个布尔判定。
Listing 质量与广告创意合规
商品详情页和广告创意要过的审,本质上是同一类判断:这段内容算不算违规、算不算低质。jev-slop-guard(davertor/jev-slop-guard)给出了一个干净的实现:对每条帖子问一个 Choice(slop / not_slop),达到用户设定的阈值(默认 0.7)就打码加标记,并留一个"显示这条内容"的覆盖按钮。它还用了一个很实用的工程约束——三个并发请求的上限,每条内容只缓存一次判定结果,保证滚动浏览时不会被判定拖住。
阈值在这里的作用是让用户自己权衡误报和漏报:觉得误伤太多就调高阈值,觉得漏放了就调低。代码握着"打码/放行"的分叉,模型只回概率。
广告侧目前还没有高星开源项目,官方把它的关键判断归为几类:创意合规审核、定向与相关度、低质流量判定,以及在实时出价里把语义信号当作特征。"创意合规"和"定向相关度"可以直接复用上面的 Detection/Ranking 做法。有一个真实项目能印证"广告识别"的判定思路:Jev Wrapped(gaborishka/jev-wrapped)在分析 Telegram 频道的帖子时,用三个 Noul 判断每篇是否含付费广告、标题党、情绪施压——广告从 0.7 起算,但当帖子类型本身也判为广告时放宽到 0.4;标题党和情绪施压从 0.5 起算。
这种"主判定 + 条件放宽"的阈值组合,是广告识别里很有借鉴价值的策略:单一信号弱,但信号之间相互印证时可以降低门槛。
定向相关度则更接近 Ranking/Scoring——给定一条广告和一群受众画像,逐对判一个相关性 Score,再在代码里排序取头部。低质流量判定可以看成"多条 Noul 叠加":把"标题党""货不对板""诱导跳转"各写成一个独立布尔,任一命中降权。这里没有免费的准确率,误伤广告主的代价(少赚曝光)和放过低质内容的代价(伤用户体验)是一对权衡,只能靠阈值调。
实时出价里的语义信号,落在 ML Feature Extraction 形态上——把广告文案、落地页文本转成 Score/Noul 特征,喂给下游的竞价模型。特征本身的语义判定交给 Jev,出价逻辑仍然在你自己手里。
一个商品批量入库的编排
把前面几节串起来,一个"商品批量入库"的管线大致是这样:先用确定性规则处理标题格式、SKU 校验;需要语义判断的字段走 Jev(Choice 归到类目、Noul 判违规、Score 评质量分);不确定的留在人工队列。这个编排和 Tab Sorter 的思路一模一样——它对窗口里的每个标签页问一个 Choice,对照用户可编辑的分组标准,分不出来的一律落到一个固定兜底桶,绝不硬归。商品入库同理:拿不准的不要塞进某个类目,丢到"待归类"桶里。
flowchart TD
CSV["商品数据(多列)"] --> RULE["确定性规则层
SKU / 格式 / 名称相等"]
RULE -->|可判定| WRITE["写入目标表"]
RULE -->|需语义判断| JEV["Jev
Choice 归类 + Noul 违规 + Score 质量"]
JEV -->|p ≥ 阈值| WRITE
JEV -->|p < 阈值| REVIEW["人工队列 / 待归类桶"]
WRITE --> DONE["入库完成"]
REVIEW --> DONE阈值是这根管线的调节旋钮:调高,自动化程度下降但更准;调低,吞吐上来,但人工复核的压力前移到了下游。
小结
- 电商判断的共同结构是"一堆候选 + 一个标准 + 逐条判定",输出空间封闭,天然适合 Jev 的类型化决策。
DuvInc/jev-table-import-mapper用"确定性名称匹配 + 逐对 Noul"两层执行,23 列导出 253 问、915 ms、$0.0012,低于 0.75 的映射一律不猜。zlZayn/AI-decision-maker暴露了一个反直觉的边界:Jev 省的是生成的钱,不是输入的钱——标准文本被逐列重复发送时,token 成本可能反而更高。- 类目树映射用逐层 Choice 收敛 + 兜底桶,参考
jerryjliu/docjev(40/40、p50 约 182 ms)与AstonyCat/jev-tab-grouper;买家匹配则相反,用多个 Noul 做多标签,参考Nancy-Chauhan/hearth-jev-rental-search。 - 行级标注用"自然语言陈述 + 逐行 Noul",参考
SkywalkerDarren/feed-lens与vibefilter/filament(1,000 条评论吻合 861 条、约 $0.003/条)。 - Listing / 创意合规用
Choice+ 用户可调阈值,参考davertor/jev-slop-guard(默认 0.7);广告识别的阈值可"主判定 + 条件放宽",参考gaborishka/jev-wrapped(广告 0.7,类型为广告时 0.4)。
下一章进入判断量最大的内容审核与信任安全,看分级审核与逃逸对抗怎么做。