☰
基于LabelStudio的准实时增量训练平台:从数据闭环到模型自动迭代
2026/10/21 23:35:48 网站建设 项目流程

去年年中,我帮一家做智能客服的公司搭模型持续迭代的机制。他们之前的意图分类模型,从数据收集到上线,周期基本稳定在两周——标注一周,训练一两天,人工导出导入数据小半天,还总担心标注完的样本分布和线上对不上。基于LabelStudio做完这套准实时增量训练平台之后,模型更新周期从两周压到了小时级,人工介入只剩数据抽检和模型验收两个环节。

这篇文章不聊太虚的架构,就把我怎么用LabelStudio搭数据闭环、怎么把增量训练流程接进去、日常维护会遇到哪些坑,一次性讲清楚。适合正在做文本分类、实体抽取、图像分类这类监督式任务的算法工程师和平台开发同学。如果你现在还靠人工导数据、手动跑脚本更新模型,这篇正好能给你一套可以直接抄的作业。

1. 为什么需要准实时增量训练

1.1 离线训练流程的真实痛点

很多团队的模型迭代节奏是这样的:线上日志攒着,每周或每两周导出来一次,丢给标注的同学标,标完导出一份JSON或CSV,训练脚本里把这份数据和原始数据合并,重训一版,评估没问题再手动替换线上模型。

这套流程最难受的地方不只是慢。慢其实还能忍,真正的问题是数据反馈链路断了——线上模型泛化能力下降的时候,你自己根本不知道是哪类样本出了问题,为什么会出问题。比如客服意图分类系统,用户换了一种问法,模型把“我要退款”识别成了“我要投诉”,这种badcase至少要等到下周看数据报表才能发现,再等标完、训练完、上线,两个星期过去了。这两个星期里,用户每天都在帮你积累错误样本,而系统没有任何反应。

准实时增量训练想解决的就是这件事:让数据从产生到影响模型的时间窗口尽可能短,短到小时级甚至分钟级。注意,这里不是指秒级的流式训练——大部分业务根本不需要做到那一步,成本和复杂度都划不来。准实时的意思是,在一个业务可接受的时间窗口内(比如15分钟、30分钟、1小时),自动完成数据收集、标注结果回收、增量训练、模型评估和上线这一整条链路。

我一开始也想过直接用流处理框架,把每条用户请求都丢进消息队列再触发训练,后来发现完全没必要。真实业务里,标注是异步的,人不可能一秒钟标一条,结果天然是批量到达的。与其搞复杂的流式架构,不如设计一个简单、可靠、按批次触发的流水线,这才是准实时增量训练平台能真正落地到生产环境的关键。

1.2 标注工具怎么选,为什么是LabelStudio

平台的核心子模块之一就是标注工具。市面上开源标注工具不少,我实际用过和调研过的有:

  • doccano:轻量,适合文本分类和序列标注,但API能力偏弱,自定义功能少。
  • brat:老牌文本标注工具,适合实体关系标注,但部署依赖稍重,交互偏老旧。
  • LabelStudio:功能全,支持文本、图像、音频、视频多模态,有REST API、webhook、机器学习后端接入机制。
  • 商业标注平台:标注质量高,但价格贵,数据出域也容易卡在合规上。

最后选LabelStudio,主要基于三点考虑。

第一,API能力完备。LabelStudio从v1.x版本开始就有完整的REST API,可以程序化地创建项目、导入数据、设置标签、拉取标注结果、控制标注进度。这意味着我不需要写一堆脚本来控制一个网页工具,所有数据交互都能被平台代码调用。

第二,有webhook机制。标注完成、项目更新、数据导入这些事件都能实时推送到外部服务,这是实现“准实时”触发最核心的能力。用事件推送而不是轮询,既省资源,又能把延时控制在秒级。

第三,支持ML backend。这是LabelStudio比较独特的能力——内置机器学习模型作为标注辅助(预标注、主动学习)。虽然第一版我没来得及用,但架构上留了扩展位,后面做主动学习会非常方便。

另外一个客观现实是,LabelStudio的用户基数大、社区活跃,文档也相对齐全。真遇到问题,GitHub issue里基本能找到解决方案。选型时这个隐形优势容易被忽略,真正用起来才知道有多重要。

2. 平台整体架构与数据闭环设计

2.1 五个核心模块和它们的关系

准实时增量训练平台按职责可以拆成五个模块:

模块职责关键组件
数据接入层拉取线上日志、业务库中的新样本定时任务、消息队列
标注管理层创建项目、导入样本、指派标注人员、接收标注事件LabelStudio、Webhook回调服务
增量训练层数据预处理、样本合并、模型微调、版本记录和评估训练脚本、模型仓库
模型服务层上线推理服务、新旧模型切换、影子模式推理服务、配置中心
监控运维层监控数据流状态、训练任务状态、效果指标和告警日志系统、监控面板

这五个模块之间不是简单的线性调用,而是围绕“数据闭环”组织的。用户产生新数据 -> 新数据进标注池 -> 标注完成 -> 增量化地训练 -> 新模型上线 -> 新模型服务新数据。每一步都有日志和状态机记录,方便排查问题。

为什么强调“闭环”?因为增量训练平台的本质不是“训练一个更好的模型”,而是“让模型在业务数据变化时自动跟上”。如果只做训练而不做数据回流,那只是一个离线训练脚本加一个定时任务,价值有限。闭环的价值在于,模型每上线一版,它自己的badcase会通过标注回流到下一版训练数据里,形成自我迭代的能力。

2.2 样本状态机的设计与作用

我一开始没做状态机,结果出了好几次数据重复训练、漏训练的事故。后来老老实实给每条数据加了完整的状态流转,才把问题止住。

每条样本的状态机大概是:

RAW -> PENDING_ANNOTATION -> ANNOTATED -> TRAINING_SAMPLED -> MODEL_UPDATED

其中穿插两个特殊状态:SKIPPED(标注人员跳过这条)和REJECTED(数据质量不合格被审核退回)。

具体来说:

  • RAW:数据接入层刚拉进来的原始数据,还没进入标注池。
  • PENDING_ANNOTATION:已推送到LabelStudio并创建了标注任务。
  • ANNOTATED:标注人员在LabelStudio中点击提交后由webhook触发更新。
  • TRAINING_SAMPLED:这条样本已被纳入某一轮增量训练。
  • MODEL_UPDATED:包含这条样本的模型已经训练并上线。

状态流转不需要复杂的状态机框架,用数据库表加一个状态字段就完全够用。我在PostgreSQL里建了一张样本状态表,每条样本记录唯一的样本ID、状态、变更时间戳和操作者ID。每个状态变更写一条流水日志,后续排查问题时会有比较清晰的线索链。

这个状态机带来的直接好处是:训练任务可以精确知道自己要拿哪些样本,不会重复训练,也不会漏掉新标注。即使调度器重启或者训练失败需要重跑,也能通过状态字段准确地恢复现场。这在自动化链路里是非常重要的可靠性保障。

2.3 触发机制:事件驱动加周期兜底

实现准实时闭环,通常有轮询和事件驱动两种触发方式,我实际做的是两者结合。

LabelStudio的webhook把标注完成事件推给一个回调服务。我的做法是,在FastAPI里开一个/api/annotations/webhook端点,在LabelStudio项目设置里配置这个地址,选择监听ANNOTATION_CREATED事件。每当标注人员提交一条标注,LabelStudio就向这个端点发一个POST请求,包含annotation的ID、数据ID、项目ID等信息。

收到webhook后,回调服务做三件事:

  1. 把对应标注结果写入PostgreSQL的标注结果表。
  2. 更新样本状态机为ANNOTATED。
  3. 判断该项目的“待训练样本数”是否达到触发阈值,达到就触发训练调度器。

这里有个关键点:不是每条标注完成都触发一次训练。训练是有成本的,一个小时内频繁触发几十次小训练完全没有必要。合理的做法是设置两个触发条件:

  • 数量阈值:累计新标注样本达到N条(比如50条)时触发。
  • 时间窗口:距离上次训练超过T分钟(比如30分钟)且存在至少1条新标注样本时周期触发。

两个条件任一满足就触发一次增量训练。这种设计的好处是:业务低谷期样本量少时,时间窗口能兜底,不会让新样本一直积压;业务高峰样本量骤增时,数量阈值能防止样本攒太多,保证模型不会跟实际分布偏得太远。

3. 关键模块实现:从LabelStudio到模型上线

3.1 用API初始化项目、导入数据和标签配置

LabelStudio本身有UI,但平台化之后所有操作尽量走API。我封装了一个LabelStudioClient工具类,核心操作包括创建项目、导入数据、拉取标注任务。创建标注项目时,几项配置很重要:

  • 标签配置:定义了标注任务的标签集合。文本分类就是<Choice value="退款"/>这类标签组;实体抽取就是各种实体类型的标签组。配置写在LabelStudio的label_config字段里,本质是它们定义的一段XML。
  • 标注指令:标注人员在界面上看到的说明,建议写得明确、带例子,比如“判断这句话的主要意图,若无法确定请选择‘其他’”。
  • 任务去重:导入数据时用业务字段(如对话ID)做去重,避免同一个自然对话被重复标注。

批量导入数据时,直接POST到/api/projects/{project_id}/import,请求体是JSON数组,每个元素就是一个任务。LabelStudio支持的字段包括data(自定义数据域)、annotations(预标注结果)、predictions(模型预测结果)。如果对接了ML backend,模型的预测结果以predictions形式传入,标注人员在页面上可以直接看到预标注结果,只需要修改或确认即可。这是主动学习的基础能力,效果非常明显。

3.2 Webhook回调服务的可靠实现

Webhook配置可以在LabelStudio项目设置里点几下完成,填上回调URL和选择事件类型。我把监控事件限定在ANNOTATION_CREATED——但注意,这个事件在新建标注和更新已有标注时都会触发,所以在回调里区分两者很重要。

我的处理方式是:解析webhook请求体的annotation.id,在PostgreSQL里用ON CONFLICT做UPSERT。如果是新标注就插入,如果是已有标注更新则覆盖。这么做的好处是,标注人员修改了某条标注,下一轮训练能直接拿到最新的标签,不会出现标签和实际标注不一致的情况。

Webhook请求体中最重要的字段包括:

  • project.id(项目ID)
  • data.id(样本数据ID)
  • annotation.id(标注结果ID)
  • annotation.result(标注内容,JSON数组)
  • annotation.updated_at(更新时间)

其中annotation.result是数组结构,每个元素包含type(如choices)、value(标注值)和from_name(对应标签配置里的字段名)。解析时按标签组配置来转换格式,这样就得到了训练样本。

有一个常见的坑:如果一个LabelStudio项目里配置了多个标签组,annotation.result会包含多个不同的from_name块。解析时必须要按每个字段的from_name分别归类,不要想当然认为结果只有一个标签。比如一个项目同时有意图分类和情感分类两个标签组,解析逻辑就要分别处理intent_label和sentiment_label两组结果。

另一个容易忽略的细节是,webhook处理器必须快速返回。LabelStudio在收到非2xx响应后会自动重试,如果回调服务把整个逻辑处理完再返回,就可能导致超时和重复请求。我的经验是,把耗时操作全部放到后台任务里,webhook函数只做解析和快速确认。

3.3 增量训练与防遗忘的具体做法

增量训练的核心不是“调用model.fit()再保存一下”这么简单,真正麻烦的是样本拼接和防遗忘。

我用的基础模型是一个中文BERT类的文本分类模型,PyTorch实现。标准增量训练流程是:

  1. 数据准备:从PostgreSQL的标注结果表中查出状态为ANNOTATED的所有新样本,连同原始文本,格式化为训练数据集。
  2. 样本合并:将新样本和全量历史样本合并成一个训练集。这里不要直接追加了事,要做重采样,确保每个意图类别的数量均衡。
  3. 模型加载:加载当前线上模型的权重作为初始权重。这里必须强调,加载的一定是线上最新版本,不是某个历史版本,否则会把模型带到几版之前的状态。
  4. 微调训练:用很小的学习率(BERT一般是2e-5到5e-5)跑几个epoch。增量训练最怕过拟合到新样本上,所以epoch数量要控制得保守。我一般跑2-3个epoch,配合早停策略。
  5. 版本记录:训练结束后,把模型权重上传到模型仓库,生成新版本号,记录训练的样本ID列表、训练时间、loss曲线等元信息。
  6. 评估:在固定评测集上评估新模型,关键指标包括准确率、召回率,以及特定类别(比如“退款”这个高风险类别)的单独指标。

防遗忘的“组合拳”我在第五章会详细讲,这里提前说一句:历史样本重放的比例、学习率的大小、epoch数量,这三者是增量训练效果最核心的调节旋钮。

3.4 上线、灰度与自动回滚

训练完成之后,不是直接全量切流量。一套可靠的上线策略是:

  1. 影子模式先跑:把新模型部署到推理服务的影子环境,复制线上流量同时跑新旧两个模型,对比两个模型输出的置信度分布。这一步主要看新模型会不会产生奇怪的输出,比如置信度整体偏低、某些类别的输出集中到了错误的区间。
  2. 小流量灰度:把5%的流量切给新模型,观察关键业务指标(如用户投诉率、转人工率)。灰度时间根据业务量而定,一般观察半天到一天比较稳妥。
  3. 全量上线:灰度观察正常后,把流量全部切到新模型。
  4. 自动回滚:这一步特别关键。平台要有一个独立的监控任务,持续监控新模型的badcase率或关键指标。一旦指标超过设定阈值(比如badcase率比基线高30%),立即回滚到上一个稳定版本,并触发告警推送。

自动回滚一定要有。因为增量训练平台的本质是“让模型自己迭代”,没人能保证每一版迭代都质量达标,回滚就是最后一道安全网。我见过不只一个团队,增量训练上线后效果反而变差,就是因为没有回滚机制,模型在错误的方向上越走越远。

4. 实操代码与调度细节

4.1 LabelStudio客户端封装

直接上代码。以下是我在项目中使用的核心API调用片段,Python实现。

import requests import json LABEL_STUDIO_HOST = "http://localhost:8080" LABEL_STUDIO_TOKEN = "your_api_token_here" def create_project(name, label_config): url = f"{LABEL_STUDIO_HOST}/api/projects" headers = {"Authorization": f"Token {LABEL_STUDIO_TOKEN}"} data = { "title": name, "label_config": label_config, } resp = requests.post(url, headers=headers, json=data) resp.raise_for_status() return resp.json() def import_tasks(project_id, tasks): url = f"{LABEL_STUDIO_HOST}/api/projects/{project_id}/import" headers = {"Authorization": f"Token {LABEL_STUDIO_TOKEN}"} resp = requests.post(url, headers=headers, json=tasks) resp.raise_for_status() return resp.json()

标签配置示例(文本分类):

<View> <Text name="text" value="$text"/> <Choices name="label" toName="text" choice="single"> <Choice value="refund"/> <Choice value="complaint"/> <Choice value="inquiry"/> </Choices> </View>

4.2 Webhook回调服务核心代码

用FastAPI实现接收webhook的服务:

from fastapi import FastAPI, Request, BackgroundTasks from db import upsert_annotation, get_annotated_count from trainer import trigger_training app = FastAPI() @app.post("/api/annotations/webhook") async def annotation_webhook(request: Request, background_tasks: BackgroundTasks): payload = await request.json() project_id = payload.get("project", {}).get("id") annotation_id = payload.get("annotation", {}).get("id") data_id = payload.get("data", {}).get("id") result = payload.get("annotation", {}).get("result", []) # 后台任务避免阻塞webhook响应 background_tasks.add_task(process_annotation, data_id, annotation_id, result) # 尽快返回,LabelStudio的重试机制依赖2xx响应 return {"status": "ok"} async def process_annotation(data_id, annotation_id, result): # 将标注结果写入数据库 upsert_annotation(data_id, annotation_id, result) # 检查是否达到训练触发条件 count = get_annotated_count() if count >= TRAIN_THRESHOLD_NUM: trigger_training()

4.3 增量训练脚本设计

训练脚本我用的是PyTorch + Transformers库:

from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments from datasets import Dataset def build_dataset(history_samples, new_samples): # 合并历史样本和新样本,并做类别重采样 all_samples = balance_samples(history_samples + new_samples) return Dataset.from_list(all_samples) def incremental_train(base_model_path, train_dataset, eval_dataset, output_dir): model = AutoModelForSequenceClassification.from_pretrained(base_model_path) tokenizer = AutoTokenizer.from_pretrained(base_model_path) training_args = TrainingArguments( output_dir=output_dir, per_device_train_batch_size=16, learning_rate=3e-5, num_train_epochs=3, evaluation_strategy="steps", eval_steps=50, save_strategy="no", logging_dir="./logs", report_to=[], ) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer, ) trainer.train() trainer.save_model(output_dir) return output_dir

这里有个需要注意的点:base_model_path必须指向线上当前模型。我会在训练任务调度时从模型仓库中拉取当前线上版本,而不是写死某个路径。这样每次训练都从最新状态开始迭代,不会出现“基于旧版本训练又重复学习”的问题。

4.4 调度与流水线编排

这一层我一开始用了一个简单的Python调度器,后来改成带失败重试和优先级队列的方案。大多数团队第一版不建议用Airflow这类重量级调度框架,杀鸡用牛刀还增加运维负担。简单实现方式就很可靠:

import time import queue training_queue = queue.Queue() while True: try: # 每30秒检查一次训练队列 if training_queue.qsize() > 0: job = training_queue.get() run_incremental_training(job) time.sleep(30) except Exception as e: logging.error(f"Training scheduler error: {e}") # 重试or告警

生产环境建议用成熟的任务队列加分布式锁,保证同一时间只有一个训练任务在跑。我当时加了基于Redis的锁,避免webhook并发触发导致两个训练任务同时跑。这个并发问题很隐蔽,在标注高峰时容易踩到,提前锁上能省很多麻烦。

5. 踩过的坑和排查方案

5.1 增量训练把历史知识弄丢了

这是我踩过最深的坑。第一次把增量训练跑通时,新模型在新样本上效果不错,但历史类别掉了5个百分点的F1值。原因很简单:新样本和旧样本比例失衡,模型被新样本带偏了。

解决方法是一套组合拳:

  1. 历史样本重放:每次增量训练,把历史样本按一定比例(约40%~60%)混进训练集,保证模型不忘记旧的类别分布。
  2. 降低学习率:增量训练的学习率比从头训练小很多,BERT类模型我一般设置在1e-5到3e-5。
  3. 限制epoch:只跑2-3个epoch,配合早停策略,看到验证集不再提升就停止训练。
  4. 类别均衡采样:对低频类别做上采样,高频类别做下采样,避免模型被高频新样本主导。

这四步缺一不可,尤其是历史样本重放。如果历史数据量特别大(比如百万级别),每次全量重放不现实的话,可以采用“代表性样本缓存”策略——保留每个类别最近N条样本作为记忆样本池,每次训练混入这部分。效果上和全量重放接近,但训练速度能快很多。

5.2 webhook事件丢失怎么办

项目上线后遇到过一次webhook没有触发的状况。原因不是LabelStudio坏了,而是我的webhook端点有一次部署更新重启,在重启的时间窗口内LabelStudio发来的回调请求失败了几次。默认情况下LabelStudio的重试策略并不激进,失败的请求有可能会被丢弃。

我的解决方案是加了冗余补偿机制:每隔5分钟全量扫一遍PostgreSQL中处于ANNOTATED状态但尚未进入训练队列的样本,把它们重新入队。这个兜底任务让人心安很多——事件驱动的实时性靠webhook,可靠性靠补偿轮询。两者配合,基本不会漏数据。

还有一点要注意:如果业务量特别大,补偿轮询不要写成一次扫全量表的SQL,要带时间条件或者游标分页,避免对数据库造成压力。

5.3 标注数据里混进垃圾标签

这是标注质量问题,非常隐蔽。标注人员对某条样本点了提交,但标注内容可能为空或选择的是“其他”类别。如果把空标签或异常标签直接当训练样本学进去,模型会学出垃圾规律。

两个处理办法:

  1. 解析时校验:在webhook解析阶段,如果检测到result为空或者标签值不在允许集合内,就把样本状态置为REJECTED,不进入训练集。
  2. 人工抽检机制:在标注结果入库后,按比例(比如5%)随机抽检,把质量不合格的标注反馈给标注人员。长期积累的标注质量数据还能用来做标注人员的绩效评估。

审核这个环节容易被工程团队省略,但真的不建议省。标注质量的方差远比你想象的大,系统自动兜底总比用户发现模型变笨了再排查要好得多。

5.4 在线服务与训练的资源竞争

业务高峰期,在线推理服务和增量训练同时跑,容易把GPU内存打满,导致推理延迟飙升。我的解决办法是给训练任务做资源隔离:

  • GPU隔离:训练任务使用独立的GPU实例,或者用显存限制参数限制占用。
  • 时间避让:训练任务错开业务高峰,比如凌晨跑,或者业务高峰时暂停训练队列。
  • 推理降级:如果必须同时跑,给推理服务做弹性伸缩和限流,保证在线服务不会因为训练而不可用。

这个问题在文本分类这种小模型场景下不明显,但如果换成大模型或者图像模型,资源竞争会非常致命。提前做好资源规划,别等到线上事故再救火。

5.5 阈值的“玄学”调参

还遇到过一个参数问题:数量阈值设置太小,导致训练任务过于频繁,一个下午触发了几十次小训练,GPU没闲着,但模型整体效果提升不明显。后来把阈值从10条调整到50条,时间窗口设为30分钟,训练任务数量下降了一个数量级,模型效果反而更好——因为每次训练的样本量够了,学到的规律更稳定。

这个参数没有标准答案,跟业务场景的数据量和标注速度直接相关。我的建议是:先按“一天训练不超过10次”的节奏来配参数,然后根据实际效果调整。不要一开始就追求“实时”,先把“准实时”做稳,再逐步逼近更短的窗口。

6. 效果评估与后续扩展方向

6.1 跑了一个月的数据对比

接入这套平台后,我做了一次对比实验。同一批标注数据,用两周一次的离线训练流程和用准实时增量流程分别跑了一个月,结果很明确:

指标离线训练准实时增量
模型F1(历史测试集)0.860.89
模型F1(新样本测试集)0.820.90
从标注完成到模型上线平均耗时2-4天35分钟
每周需人工介入次数4-5次1次(仅模型验收)

最让我印象深刻的不是F1提升了多少,而是新样本测试集的F1从0.82涨到了0.90。这证明流程的价值不只是“变快”,而是通过快速反馈闭环让模型持续适配新数据分布,这才是增量训练平台的核心收益。

6.2 主动学习与ML backend的扩展位

后续最有价值的扩展方向是主动学习。LabelStudio的ML backend支持在导入任务时预填模型预测结果。更进一步,可以对每条待标注样本计算模型的不确定性分数(比如预测置信度),然后把高不确定性样本优先推送到标注队列中。这样标注人员的时间价值最大化,同样的标注量能带来更大的模型提升。

实现上也不是太复杂:在数据接入层加一个打分步骤,调用当前模型对每个新样本做一次推理,输出预测置信度;低于某个阈值的样本优先导入标注池。阈值选择需要结合误分类成本和标注成本来平衡,偏保守就把阈值调低,追求覆盖率就调高。

6.3 多任务、多模态的演进空间

这个平台第一版只处理了文本分类这一类任务,但架构上已经预留了扩展空间——标签配置是JSON结构,训练模块按任务类型做了抽象。如果后续要支持实体抽取、图像分类、音频事件检测等任务,LabelStudio原生就支持这些类型的数据标注,不需要换工具;训练的权重加载和评估模块则需要针对不同模型架构做适配。

另一个我想强调的方向是“人机协同”的标注流程。LabelStudio允许预填predictions字段,标注人员可以直接看到模型预测结果。如果配合主动学习策略,这个环节可以显著减少标注成本,也是通往成熟MLOps数据飞轮的必经之路。

最后分享一段我在这个项目里的真实体会。

一开始,我对增量训练是持怀疑态度的,总觉得在线模型自己迭代会搞出不可控的东西。真正跑通之后,最大的认知转变是:增量训练平台的难点不在写训练脚本,而在于把数据闭环串起来、把异常处理掉。webhook丢事件了要能补偿,标注质量差了要能拦下,模型上线了要能回滚。把这些可靠性细节做到位,系统才会真正稳定。如果你也正在计划做类似的事情,建议先不要追求架构上的炫技,花更多时间想清楚数据怎么流转、异常怎么处理,这比选多先进的技术栈重要得多。

还有一个小技巧想分享给正在折腾LabelStudio的朋友:别把LabelStudio当成一个纯数据入库工具,它的predictions字段和ML backend能力是让标注环节变成人机协同的关键。哪怕暂时不做主动学习,也可以先把当前模型对每个新样本的预测结果写进predictions,标注人员能直接看到模型认为这段话是“退款”还是“投诉”,只需要确认或纠正,标注速度能快不少。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询