☰
使用 Agno 构建文本分类数据标注流水线:从固定标签到置信度与推理依据
2026/10/10 16:44:18 网站建设 项目流程

使用 Agno 构建文本分类数据标注流水线:从固定标签到置信度与推理依据

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

文本分类(Text Classification)是数据标注领域最基础的原子能力:输入一段文本,输出一个来自封闭标签集合的标签。本文以 Agno 仓库cookbook/data_labeling/_01_text_classification/目录下的三个可运行示例为核心,讲解如何用Agent+output_schema结构化输出实现文本 → 单标签的分类标注,并逐步扩展出置信度字段(用于低置信样本转人工或转强模型)与推理依据字段(用于审计与训练数据沉淀),最后结合源码揭示其底层工作机理。读完本文,你将掌握一套可直接复制运行的情感/意图/主题分类标注脚本,并理解如何把它们接入更复杂的多标签分类与结构化抽取流程。

什么是"文本 → 单标签"分类

单标签文本分类是数据标注流水线中最简单的原语:输入是一个字符串,输出是封闭集合(closed set)中的一个标签。封闭集合意味着候选标签是预先固定、穷举的,模型只能从中选择一个作答,不能自由发挥。

在cookbook/data_labeling/_01_text_classification/README.md中给出了四类典型场景:

场景示例标签集合
情感(Sentiment)positive / negative / neutral
意图(Intent)refund / complaint / question / praise
主题(Topic)sports / politics / tech / health
质量分桶(Quality bucket)good / mediocre / poor

判断是否应该使用本文方案的关键在于:输出是否恰好是固定、穷举标签集合中的一个。如果多个标签可以同时命中(如一条餐厅评论同时涉及 food 和 service),应当改用cookbook/data_labeling/_02_text_multilabel_classification/;如果输出是带字段的结构化数据(实体、字段、嵌套对象),则应当使用cookbook/data_labeling/_03_text_extraction/。

从仓库整体布局看,cookbook/data_labeling/README.md明确指出:应当从本目录的basic.py开始学习,目录中其他所有 cookbook 都镜像了它的结构——每个子目录包含一个端到端可运行的basic.py,外加在任务上有意义(task-meaningful)的变体。因此本文不仅是单标签分类的指南,也是理解整个 data_labeling 系列(28 个子目录、75 个单文件示例)的入门钥匙。

目录结构与三个示例文件

cookbook/data_labeling/_01_text_classification/ ├── README.md ├── basic.py # 文本 → 单个标签(最小可读示例) ├── with_confidence.py # 在标签之外追加自报置信度字段 ├── with_rationale.py # 在标签之外追加一句话推理依据 └── TEST_LOG.md # 按 cookbook 惯例维护的运行日志
  • basic.py— 文本 → 单标签。最小、最直白的标注原语。
  • with_confidence.py— 为每次预测追加自报置信度(high/medium/low)。当需要把低置信度样本路由给人工或更强模型时使用。
  • with_rationale.py— 追加一段简短推理依据字符串,解释为什么选择该标签。适合审计追踪与作为训练数据沉淀。

三个文件共享同一套技术栈:agno.agent中的Agent与RunOutput、pydantic的BaseModel/Field、typing.Literal定义封闭标签、rich.pretty的pprint打印结果。下面逐一展开。

basic.py:文本 → 单个标签

完整源码位于 basic.py,核心只有三步。

第一步:用Literal定义封闭标签集合。typing.Literal是 Python 3.8+ 提供的类型,把允许取值限定为显式枚举的字符串:

from typing import Literal from pydantic import BaseModel, Field class Classification(BaseModel): label: Literal["positive", "negative", "neutral"] = Field( ..., description="The assigned sentiment label" )

这里label字段的类型被锁定为"positive"/"negative"/"neutral"三者之一,Pydantic 会在解析输出时强制校验——模型如果输出集合之外的标签,结构化解析会直接失败,从机制上杜绝了"模型自由发挥标签"的可能。这正是"封闭集合"这一约束在代码层面的落地。

第二步:创建 Agent,绑定模型、指令与输出 Schema。

from agno.agent import Agent, RunOutput agent = Agent( model="google:gemini-3.5-flash", instructions="You classify product reviews by sentiment.", output_schema=Classification, )

关键参数是output_schema=Classification:它声明了"模型必须返回符合Classification结构的 JSON 对象",而非自由文本。instructions则描述了任务语义(按情感分类产品评论)。示例默认使用google:gemini-3.5-flash(Gemini 3.5 Flash,原生多模态),这一点与整个 data_labeling cookbook 系列保持一致——cookbook/data_labeling/README.md的环境变量表中注明GOOGLE_API_KEY是该系列每个 cookbook 的默认凭证。

第三步:批量运行并打印结果。

from rich.pretty import pprint if __name__ == "__main__": samples = [ "I love this product, fantastic quality and fast shipping.", "Broken on arrival, total waste of money.", "It works as described, nothing special.", ] for text in samples: run: RunOutput = agent.run(text) pprint({"input": text, "result": run.content})

对每条样本调用agent.run(text)得到RunOutput,其中的content即解析后的Classification对象(含label字段)。pprint将输入与结果以字典形式结构化打印,方便直接观察标注输出。

预期的运行结果(来自 TEST_LOG.md,2026-07-18 针对gemini-3.5-flash、agno 2.7.4 实测 PASS):

  • "I love this product, fantastic quality and fast shipping."→positive
  • "Broken on arrival, total waste of money."→negative
  • "It works as described, nothing special."→neutral

三条样本恰好覆盖正、负、中三种情感,验证了单标签分类的最小闭环。

with_confidence.py:追加自报置信度,支持低置信样本路由

在生产标注流水线中,纯标签往往不够——你需要知道哪些标注"可信",从而把拿不准的样本转给人工或更强的模型。with_confidence.py在label之外追加了一个confidence字段:

class Classification(BaseModel): label: Literal["positive", "negative", "neutral"] = Field( ..., description="The assigned sentiment label" ) confidence: Literal["high", "medium", "low"] = Field( ..., description="Self-reported confidence in the label" )

置信度同样是封闭枚举(high/medium/low),并通过instructions向模型给出可操作的判定标准,而非空泛的"请给出置信度":

instructions = """\ Classify the sentiment of the input text. Report a confidence level: - high - the sentiment is clear and unambiguous - medium - the sentiment is mostly clear but with some hedging or mixed signals - low - the text is sarcastic, ambiguous, or off-topic """

这组指令把抽象置信度落到了可执行的启发式规则上:清晰无歧义 → high;有保留或混杂信号 → medium;讽刺、歧义或离题 → low。该示例的测试样本刻意覆盖了这三档:

samples = [ "Best purchase of my life, life-changing!", "It's fine I guess.", "Yeah right, this thing is 'amazing'.", ]

TEST_LOG.md 记录的实测结果为:第一句 →positive/high;第二句(带保留语气)→neutral/medium;第三句(讽刺)→negative/low。可见模型确实依据指令标准区分了歧义程度。

落地价值:有了confidence字段,下游消费者就能实现确定性路由——confidence == "low"的样本进入人工审核队列或转发给更强模型复审,而high/medium样本可以直接入库。这种"按置信度分流"模式是真实标注系统中最常见的质量兜底手段之一。

with_rationale.py:追加推理依据,服务审计与训练数据沉淀

仅凭一个标签,事后很难追溯"模型为什么这么标"。with_rationale.py在label之外追加自由文本rationale字段:

class Classification(BaseModel): label: Literal["positive", "negative", "neutral"] = Field( ..., description="The assigned sentiment label" ) rationale: str = Field( ..., description="One sentence explaining why this label was chosen" )

对应的指令要求模型在推理依据中引用或转述驱动决策的具体词汇:

instructions = """\ Classify the sentiment of the input text. Quote or paraphrase the specific words that drove your decision in the rationale. """

这种"引用关键证据"的约束让rationale不再是模型的自说自话,而是可校验的决策痕迹。该示例的两个测试样本:

samples = [ "Shipping was fast but the product itself fell apart in a week.", "Better than expected, will buy again.", ]

TEST_LOG.md 实测:第一句 →negative,rationale 引用了"产品在一周内散架";第二句 →positive,rationale 引用了'Better than expected'和'will buy again'。两个标签正确,且理由均落到决定性短语上。

落地价值:rationale有两大用途——其一,可审计性:人工审核员可以只读理由快速判断标注质量,无需重读全文;其二,训练数据沉淀:reasoning trace 本身就是产物,可以直接作为后续模型微调或少样本提示的输入素材。

运行方式与环境变量

在 agno 仓库根目录下,依次执行即可。三个脚本独立可跑,无需额外依赖:

python cookbook/data_labeling/_01_text_classification/basic.py python cookbook/data_labeling/_01_text_classification/with_confidence.py python cookbook/data_labeling/_01_text_classification/with_rationale.py

前置条件:需要设置GOOGLE_API_KEY环境变量(示例默认使用 Gemini 3.5 Flash)。若尚未配置演示环境,可先执行仓库根目录的./scripts/demo_setup.sh创建并激活 demo 虚拟环境(source .venvs/demo/bin/activate),再运行上述命令。本目录三个脚本均只依赖模型推理,无额外 Python 包或外部服务依赖。

源码级原理:output_schema 与 RunOutput 如何工作

示例中两个 API 值得从源码层面理解其机制。

output_schema的结构化输出强制。Agent的output_schema参数(本示例传入 Pydantic 模型Classification)驱动了从提示词到响应解析的全链路。在 libs/agno/agno/agent/_messages.py 中可以找到对应逻辑:当output_schema存在且模型不支持原生结构化输出时,系统会向系统消息追加 JSON 输出提示(get_json_output_prompt),要求模型按 schema 输出 JSON;模型返回后,Agno 再按Classification的 Pydantic 定义解析并强校验。因此示例代码中的类型约束(Literal封闭标签、必填字段)在运行时同样生效——解析失败会报错而不是静默放行。

RunOutput是agent.run()的统一返回容器。agent.run(text)返回的RunOutput定义于 libs/agno/agno/run/agent.py,其 docstring 明确写着"Response returned by Agent.run() or Workflow.run() functions"。它携带run_id、session_id、content(结构化解析后的结果对象)、metrics、messages、tools等字段。示例中访问的run.content即解析后的Classification实例(label、confidence、rationale等字段均可直接取用),而run_id/session_id等元数据可用于后续的记录、追踪与重放——这正是数据标注流水线需要的可追溯性基础。

与相邻标注原语的关系。当标注需求升级时,本文方案是其他原语的地基:

  • 多个标签同时命中 →cookbook/data_labeling/_02_text_multilabel_classification/(平面标签空间任意子集、逐标签置信度、层级化父子标签);
  • 输出为结构化对象(实体、字段、嵌套结构)→cookbook/data_labeling/_03_text_extraction/(生产环境最常见的标注形态);
  • 需要实体字符/Token 位置 →cookbook/data_labeling/_04_text_span_labeling/。

向上游看,cookbook/data_labeling/_17_llm_as_judge/、_18_quality_review/、_19_inter_annotator_agreement/等组合模式都建立在"分类/抽取"这类基础原语之上。理解本文的basic.py,等于掌握了整个 data_labeling 系列的通用骨架。

小结

  • basic.py用Literal封闭标签集合 +output_schema强制结构化输出,实现了最简的文本 → 单标签分类标注;
  • with_confidence.py追加confidence字段与可执行的判定指令,支撑低置信样本路由到人工或更强模型;
  • with_rationale.py追加rationale字段并要求引用关键证据,服务于审计追踪与训练数据沉淀;
  • 底层机制上,output_schema驱动"提示词注入 + 返回结果 Pydantic 强校验",RunOutput统一承载运行结果与追踪元数据,二者共同保证了标注输出的结构性与可追溯性。

如果你要构建真实标注流水线,推荐从这三个脚本出发:先用basic.py验证任务可行性,再按需叠加confidence(质量路由)与rationale(审计与训练素材),最后依据输出形态切换到多标签或结构化抽取目录,继续复用同一套 Agent +output_schema模式。

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询