数据标注与分类
批量打标签先用便宜的小模型跑第一遍,要求按 JSON 返回标签和置信度;置信度低的样本交给另一家的模型复核,再随机抽一部分人工检查。按每月 50 万条短文本、5% 进入复核估算,用最低价分组计算,模型费用每月约 ¥68.24。
价格更新于 2026年11月12日 20:17|
01
业务问题
用户评论、客服工单、问卷回答、商品标题每天都在增加,运营和算法团队要把它们分进类目,统计问题分布,或者拿来训练自己的模型。人工标注慢,几个人的标准也很难统一。
大模型照着写清楚的标签定义打标,速度快、成本低,但在边界样本上会摇摆,偶尔还会给出标签清单之外的答案。
更现实的定位是把模型当第一遍标注员:输出限定在固定标签里并附置信度,拿不准的交给第二个模型或人工,再用抽检结果不断修正标签定义。
02
推荐模型组合
首轮标注(小模型)
gemini-2.5-flash-liteGoogle输入 ¥0.2 / 输出 ¥0.8 每百万 tokens· 标准分组处理全部样本。任务只是从固定标签里选一个,用不上大模型的推理能力,选输入单价低、响应快的小模型就够了。
复核低置信度样本(第二个模型)
qwen3.5-plus通义千问输入 ¥1.12 / 输出 ¥6.72 每百万 tokens· 国产模型分组只处理首轮置信度低的样本。换一家厂商的模型给第二意见,能减少同一个模型带来的系统性偏差;两次结果不一致的交给人工。
推荐模型按实时目录自动选取,价格取各模型最低价分组,更新于 2026年11月12日 20:17。点模型名可查看全部分组价格。
03
参考架构
- 1
写标签定义
每个标签写一句定义和两三个正反例,边界情况单独说明,比如「物流慢但对商品满意」该归哪一类。
- 2
小模型首轮标注
系统提示词固定,要求返回 JSON:标签加 0 到 1 的置信度;temperature 设为 0,限制输出长度。
- 3
程序校验
标签不在清单里、或者 JSON 解析失败的,直接记为待复核。
- 4
第二模型复核
置信度低于阈值(比如 0.7)的样本交给另一个模型重新标注,结果一致就采用,不一致进入人工队列。
- 5
抽样人工检查
每批随机抽 1% 到 2% 人工检查,算出一致率;一致率下降时修改标签定义和示例,重跑有问题的类目。
04
成本估算
假设:每月标注 50 万条短文本(评论、工单),每条输入约 400 tokens(标签定义与示例约 300、文本约 100),输出约 30 tokens;其中 5%(2.5 万条)低置信度样本交给第二个模型复核。
| 项目 | 模型 | 用量假设 | 费用 |
|---|---|---|---|
| 首轮标注 | gemini-2.5-flash-lite | 500,000 次 × 输入 400 + 输出 30 tokens | ¥52 |
| 低置信度复核 | qwen3.5-plus | 25,000 次 × 输入 400 + 输出 30 tokens | ¥16.24 |
| 合计(每月) | ¥68.24 | ||
按各模型最低价分组的实时价格计算,价格更新于 2026年11月12日 20:17。
只含模型调用费用,不含人工抽检成本。标签定义越长,每条的输入 tokens 越多;待标文本越长,费用越高。条数翻倍,费用大致翻倍。
05
示例代码
首轮用小模型按 JSON 返回标签和置信度,置信度低的交给第二个模型,两次不一致的标记为人工处理,结果写入 JSONL。
import json
import os
import random
from concurrent.futures import ThreadPoolExecutor
from openai import OpenAI
client = OpenAI(base_url="https://open.tutujin.com/v1", api_key=os.environ["TUTUJIN_API_KEY"], max_retries=3)
LABELS = ["shipping", "quality", "price", "service", "other"]
SYSTEM = (
"You label customer reviews. Choose exactly one label from: " + ", ".join(LABELS) + ". "
'Reply with JSON only, for example {"label": "quality", "confidence": 0.9}.'
)
def label(item, model):
resp = client.chat.completions.create(
model=model,
messages=[{"role": "system", "content": SYSTEM}, {"role": "user", "content": item["text"]}],
response_format={"type": "json_object"},
temperature=0,
max_tokens=50,
)
raw = resp.choices[0].message.content
try:
result = json.loads(raw[raw.find("{"): raw.rfind("}") + 1])
except ValueError:
result = {}
if result.get("label") not in LABELS:
return {"id": item["id"], "label": None, "confidence": 0.0}
return {"id": item["id"], "label": result["label"], "confidence": float(result.get("confidence", 0))}
items = [{"id": 1, "text": "Arrived two days late, but the mug itself is lovely."}]
with ThreadPoolExecutor(max_workers=8) as pool:
first = list(pool.map(lambda it: label(it, "gemini-2.5-flash-lite"), items))
# second opinion for low-confidence rows from another vendor's model
by_id = {it["id"]: it for it in items}
for row in first:
if row["confidence"] < 0.7:
second = label(by_id[row["id"]], "qwen3.5-plus")
row["needs_human"] = second["label"] != row["label"]
row["label"] = second["label"] if row["label"] is None else row["label"]
# a random 2% always goes to people for quality checks
for row in random.sample(first, max(1, len(first) // 50)):
row["needs_human"] = True
with open("labels.jsonl", "w", encoding="utf-8") as f:
for row in first:
f.write(json.dumps(row, ensure_ascii=False) + "\n")常见问题
每月 50 万条数据标注要多少钱?
按每条输入约 400 tokens、输出约 30 tokens,再让 5% 进入第二个模型复核估算,用最低价分组计算约 ¥68.24。标签定义写得越长,单条成本越高。
模型标注的准确率有多高?
取决于任务难度和标签定义是否清楚,没有通用的数字。上线前拿几百条人工标好的样本测一遍一致率,再定置信度阈值和人工抽检比例。
怎么避免模型输出清单外的标签?
提示词里列出全部标签并要求只能选其中一个,按 JSON 格式返回;程序里再校验一遍,不在清单里的直接归入待复核。
标注结果能拿去训练自己的模型吗?
技术上可以,但各家模型提供方对输出内容的用途有自己的使用条款,用于训练模型之前请先确认条款允许。
并发开多少合适?
从 8 个并发开始,看 429 出现的比例逐步调整;收到 429 时等一会儿再重试。量大的任务也可以分批放到业务低峰时段跑。