资讯动态

用LLM自动提炼文章标签:标题+正文双层提取全流程实战

发布时间:2026/10/19 7:34:17 来源:尧图企业网站定制
干了这么多年内容运营和编辑工具开发我越来越觉得文章标签这件事属于那种“看着小事一桩实际能决定内容盘子生死”的环节。标签打得准文章分发效率高、推荐精准、搜索有曝光甚至能直接反哺商业化变现标签打得稀烂内容库就是一团浆糊后面想做什么数据分析、用户画像、专题聚合全都无从下手。最近我们团队做了一个“从标题到正文AI 自动提炼文章标签”的内部方案用 LLM 把过去编辑手动填标签的流程彻底改掉了。这篇文章把我整套设计思路、技术选型、实操代码和踩坑记录全部分享出来。先说一下这个方案适合谁看在内容平台、自媒体团队、出版机构、企业内部知识库这些场景里每天要处理几十上百篇稿子标签体系乱成一锅粥编辑和运营被重复劳动拖垮的团队这份经验可以直接抄作业。如果你是独立博主文章量小但希望把标签质量提上去平时手写标签经常觉得词穷的话这套思路同样适用只是落地规模可以缩得小一些。1. 整体设计思路为什么标签值得用 AI 重做一遍1.1 标签的真实价值不只是“分类”这么简单很多人把标签理解成简单的文章分类其实标签在内容体系里的作用比我刚入行时以为的复杂得多。我用一张表来说明标签在整个内容链路里到底在服务谁。使用方标签承担的任务标签质量差时会发生什么推荐系统建立用户兴趣与内容之间的关系推不准用户刷几下就离开搜索系统提高关键词命中率帮助文章被找到搜不出、搜不准文章白写运营人员做专题策划、活动聚合找素材像大海捞针广告系统做内容与广告的匹配匹配不上收入上不去作者/编辑复盘内容方向看不出来自己到底在写什么这里最容易被低估的是“标签”和“分类”的区别。分类是一个树状结构文章只能挂到一个节点下标签是扁平结构一篇文章可以同时挂“爬虫”“网页抓取”“数据清洗”三个标签它描述的是文章的多维属性。这种多维属性恰恰是 AI 擅长捕捉的因为人类编辑通常只凭直觉给出两三个词而不会认真考虑这个内容可能在哪些维度上被需要。1.2 传统的标签生产模式问题到底出在哪我们团队在引入 AI 之前标签主要靠三种方式生产各有各的坑。第一种是全人工打标。编辑读完文章凭经验给出几个词。这种方式的优点是质量基本可控但缺点太致命慢、累、标准不统一。同一个编辑心情好的时候可能会多写几个标签赶稿的时候只给一个。不同编辑对同一篇文章的理解差异更是天壤之别内容库越做越乱。第二种是纯规则匹配。列一个关键词词表文章里出现“Python”就打“Python”标签出现“爬虫”就打“爬虫”。这种方式处理专业术语还行但面对语义变化就废了。比如一篇文章通篇在讲“反爬机制绕过”但整篇没有出现“爬虫”二字规则就漏了再比如文章里提到“这个话题水很深”规则可能把“水很深”这种修饰短语误判为技术关键词。第三种是用 TF-IDF 做词频统计把高频词拿来做标签。这个方法的问题在于标签不等同于高频词。一篇访谈文章反复出现受访者名字按词频会把名字打上去但名字根本不适合做内容标签一篇教程反复出现“方法”“问题”“步骤”这些词词频很高但对内容刻画毫无意义。这三类问题本质上指向同一个核心矛盾标签是需要“理解”之后才能产出的东西而过去的自动化手段都在做“匹配”没有做“理解”。标题是文章最浓缩的抽象概括正文是观点的完整展开要让标签既符合用户搜索习惯又能反映文章核心价值就必须先读懂两者之间的关系这正是大语言模型擅长的事情。1.3 以标题为纲、以正文为据的双层提炼架构我的整体设计思路用一句话总结标题提炼方向正文验证细节最后统一融合校准。为什么要这样分层因为标题和正文的属性完全不同。标题是高度浓缩的通常是作者自己提炼出的全文核心但它包含的信息量太少甚至有时候为了吸引点击会用比较夸张的表达正文字量大包含了真实的细节、案例、方法但信息密度低直接让 AI 读完整篇再打标容易淹没重点。所以整个流程分四层标题输入层只把文章标题给 AI让它先给出第一版候选标签这一步相当于让 AI 快速抓住全文的“纲”。正文深挖层把正文喂给 AI结合标题让 AI 找出标题没有覆盖到的重要子主题补全标签候选。融合裁剪层把两轮候选标签合并去重、统一表述、控制数量。校验输出层检查标签与文章内容是否一致过滤不合适的词输出最终结果。这个设计最重要的优势是即使标题写得比较“标题党”正文深挖层也能把内容拉回真实的方向即使正文话题很散标题预提炼层也能保证标签不跑偏。两条腿走路互为补充。2. 技术选型为什么最后选了 LLM 方案2.1 可落地的标签抽取方案对比做技术方案选型的时候我对比了市面上常见的几种路线不只是 LLM。写在前面我已经把和标题相关的几个技术方案从纯字符匹配到机器学习模型全部过了一遍这里是我的真实对比结果。方案类型代表技术优点缺点适合场景硬匹配正则表达式、词表匹配快、便宜、可解释无法处理同义词和语义变化专业术语非常固定的领域统计方法TF-IDF、TextRank无需标注数据输出的是关键词不是标签缺乏抽象归纳能力关键词抽取不是打标传统多标签分类文本分类模型可控标签体系效果稳定需要大量标注样本新标签需要重新训练垂直领域、标签体系封闭的平台大模型方案LLM 提示词/微调理解语义、能抽象、无需标注数据有幻觉风险成本相对高标签体系灵活、内容类型复杂、快速迭代需求2.2 LLM 做“语义摘要型标签”为什么无可替代我举一个例子最初的测试里有篇文章标题是《从零实现一个轻量级 Web 服务器我踩了这些坑》正文里大量出现“TCP 三次握手”“Socket 编程”“HTTP 状态码”“阻塞非阻塞”。传统词频方案给出的标签是“服务器”“HTTP”“Socket”“踩坑”。看着似乎还行但它漏掉了一个非常重要的认知标签——“网络编程”。这个标签没有直接出现在正文里需要读者通读之后才能抽象出来。而 LLM 方案给出的标签是“Web服务器”“网络编程”“Socket”“HTTP协议”“项目实操”“踩坑经验”不管是从语义概括还是从用户搜索角度都更接近编辑人工标注的水平。在理解标题和正文的关系上用一句生活化的话来说传统方案像是一个只做“词面匹配”的检索员看到“Socket”就盖章“Socket”LLM 像一个读完文章后帮你写内容摘要的同学它知道这篇文章本质上是讲网络编程入门实践的。标签的本质是“概括”而非“匹配”所以 LLM 在这件事上有结构性优势。2.3 模型本身怎么选API 还是私有化我做选型时重点权衡了三个维度效果、成本、数据隐私。效果排在第一位。当时试了本地的小参数模型和几家主流的商业化 API差距非常明显。小参数模型在“抽取类标签”上还能应付比如从文章里找出已有的技术名词但到了“抽象类标签”和“合并同义表述”这两个环节就开始力不从心经常给出一些词不达意的标签。API 方案在理解力上基本没有问题所以我最终选择了 API。成本方面做一个粗略估算平均每篇文章标题约 30 字正文字数在 3000 到 8000 字之间按 Token 换算大约 2000 到 6000 Token。单次调用成本折合人民币几分钱到一两毛钱取决于模型档次。日均处理 500 篇文章的情况下每月的标签生成成本在几百到一千出头相比投入一个专职编辑的人力成本便宜太多。隐私方面有些内容平台的文章涉及未发布稿件或者商业化数据不能直接外传。我的处理方案是分两级常规文章走 API敏感稿件走本地小模型或者人工打标后续再优化蒸馏方案。这一套“双轨制”从上线到现在跑得很稳。3. 核心实现从标题预提炼到正文深挖的完整流程3.1 流程全景与输入输出约定我先定义一下输入输出格式所有环节都围绕这个约定来。输入文章标题 title、正文 content、最大标签数 max_tags默认 5 个输出标签列表 tags例如[Web服务器, 网络编程, Socket, HTTP协议, 踩坑经验]我建议在工程上把每个环节做成独立函数不要一个脚本把所有逻辑搅在一起。原因后面会讲每个环节的错误处理方式不一样拆开才能独立排查问题。整个处理流程如下标题预提炼让 AI 基于标题生成 3 到 5 个候选标签。正文深挖把正文按规则拆段选前 N 段最有代表性的内容结合标题做第二轮提炼。融合裁剪两轮候选标签合并去重统一表述格式。校验输出再用一次轻量调用做一致性检查过滤不匹配标签。这套流程看起来多了一次 LLM 调用但如果在裁剪阶段做得好可以省掉最后的校验步骤整体调用控制在 2 到 3 次仍然很快。3.2 标题预提炼先让模型抓住全文的“纲”标题预提炼这一步的任务不是直接得到最终标签而是产出一个“候选池”让模型先基于标题输出它对文章的理解。提示词我打磨了很久最稳定的版本是这样的你是一名资深的内容编辑请根据以下文章标题提炼出这篇文章最可能的主题标签。 要求 1. 标签必须是文章内容的真实反映禁止臆测 2. 标签要兼顾抽象概念和具体关键词 3. 每个标签控制在 2 到 8 个字 4. 输出 3 到 5 个标签 5. 只输出 JSON 数组不要输出其他内容 标题{title} 输出格式[标签1, 标签2, 标签3]这一步比较关键的细节包括明确要求“禁止臆测”避免模型把自己的联想强加到标题上。要求把抽象概念和具体关键词都纳入候选池比如“网络编程”和“Socket”都要有后面融合裁剪时才有选择空间。限定“只输出 JSON 数组”方便程序直接解析。我最初忘了做这个限定模型经常在标签前后加一些“根据标题分析标签如下”之类的废话解析时还要再做清洗。我先用 200 篇文章测试了这一阶段的输出质量已经能超过人工打标的 60%。但标题存在明显的两类短板一是标题“标题党”风格太重比如《震惊原来这样写代码效率翻倍》模型可能提取出“写代码效率”这种泛泛的词二是标题过于含蓄具体技术点藏在正文里。所以标题预提炼只能作为第一层候选不能作为最终结果。3.3 正文深挖找到标题之外的重要子主题正文深挖是整个流程中技术含量最高的部分直接决定标签最终的覆盖面。先说明为什么不能把整篇正文一次性扔给模型。我做过对比实验把 8000 字文章一次性传入和拆分处理后分别测试一次性传入的问题是模型处理超长文本时注意力会分散容易遗漏藏在文章后半部分的细节而且 Token 费用高时延也大。拆分处理的效果明显更稳。我的拆分策略如下把正文按段落切分过滤掉过短的句子比如少于 15 字和疑似模板内容比如“关注我”“点击收藏”等。按顺序选取前面 40% 的段落、中间 30% 的段落、结尾 30% 的段落各若干段让样本覆盖全文结构不遗漏从铺垫到结论的任意重要环节。将选中的段落拼接成一个长度可控的“正文采样块”通常控制在 1500 到 2500 字之间再交给模型做第二轮提炼。正文深挖的提示词如下你是一名资深的内容编辑正在为下面这篇文章添加标签。 文章标题{title} 文章正文节选{content_sample} 请基于标题和正文完成以下任务 1. 找出标题没有覆盖到的关键主题和子主题 2. 提炼出技术方向、核心概念、应用场景、目标读者等维度上的标签 3. 排除文章中的修饰性内容比如情绪表达、背景铺垫 4. 输出不超过 5 个标签 5. 只输出 JSON 数组不要输出其他内容 输出格式[标签1, 标签2, 标签3]这里“维度”这个词是实验之后故意加进去的因为最初的输出常常全是具体技术词缺乏场景和读者维度的标签。加上之后“入门”“实战”“踩坑经验”这类读者决策型标签出现的概率大幅提升。3.4 融合裁剪过滤泛词、去重、控制标签数量融合裁剪这一步做得好最终标签质量能比直接生成高出一截。具体做四件事。第一候选合并。把标题预提炼和正文深挖生成的两个 JSON 数组合并成一个集合。这一步相对机械直接扩展数组即可。第二去重与同义归一。把语义相同的标签合并成一个。比如标题阶段生成了 “Web服务器”正文阶段生成了 “Web服务端”需要归一成同一个。这里又要依赖一次 LLM 小调用提示词设计为以下是两个编辑分别给同一篇文章打的标签请合并重复项保留更合理的表述 标签A{tags_a} 标签B{tags_b} 只输出 JSON 数组不要解释。如果不想多一次调用也可以用简单的编辑距离算法做近似去重但当遇到“爬虫”和“网络爬虫”这种语义相同但字面差异较大的词组时效果不够好。我建议留一次 LLM 调用做同义归一整条链路才完整。第三过滤泛标签。这是最容易翻车的一步。LLM 在标签生成时天然倾向于输出“技术”“方法”“人工智能”“作用”等特别泛的词因为这些词在它的知识分布里太常见了。我维护了一个禁词表上线之后不断积累比如 “方法”“技巧”“介绍”“应用”“一文读懂” 这些泛标签直接过滤。第四数量控制。最终标签建议控制在 3 到 8 个。少于 3 个覆盖不了文章全貌多于 8 个就会稀释重点。我的逻辑是先按相关性排序如果候选太多就只保留排序靠前的如果候选太少就回到正文深挖环节补充一次。这个“相关性排序”可以直接让模型输出时带上置信度我用的提示词会要求模型按相关性从高到低排列。这样裁剪时直接从头截断。3.5 完整代码实现一个可直接落地的 Python 版本接下来把整个流程完整代码化。下面这段代码我在实际项目中跑得很稳你可以直接复制改成自己的 API 配置和禁词表。import os import json import time import hashlib import requests from typing import List, Optional # 配置 API_URL https://your-api-endpoint/v1/chat/completions API_KEY os.getenv(LLM_API_KEY, ) DEFAULT_MAX_TAGS 5 FORBIDDEN_TAGS {方法, 技巧, 介绍, 应用, 作用, 一文读懂, 干货, 总结} # 基础 LLM 调用 def llm_chat_json(system_prompt: str, user_prompt: str, temperature: float 0.3, max_tokens: int 300) - list: 调用 LLM要求模型返回 JSON 数组。 payload { model: your-default-model, temperature: temperature, max_tokens: max_tokens, messages: [ {role: system, content: system_prompt}, {role: user, content: user_prompt} ] } headers {Authorization: fBearer {API_KEY}, Content-Type: application/json} resp requests.post(API_URL, jsonpayload, headersheaders, timeout30) resp.raise_for_status() content resp.json()[choices][0][message][content] # 清理模型可能输出的多余文字只保留 JSON 部分 start content.find([) end content.rfind(]) 1 if start -1 or end 0: raise ValueError(f模型输出不是合法 JSON 数组: {content}) try: return json.loads(content[start:end]) except json.JSONDecodeError: raise ValueError(fJSON 解析失败: {content[start:end]}) # 标题预提炼 TITLE_PROMPT 你是一名资深的内容编辑请根据以下文章标题提炼出这篇文章最可能的主题标签。 要求 1. 标签必须是文章内容的真实反映禁止臆测 2. 标签要兼顾抽象概念和具体关键词 3. 每个标签控制在 2 到 8 个字 4. 输出 3 到 5 个标签 5. 只输出 JSON 数组不要输出其他内容 标题{title} def extract_tags_from_title(title: str) - List[str]: result llm_chat_json( system_prompt你是一个严谨的标签生成助手。, user_promptTITLE_PROMPT.format(titletitle), temperature0.2, ) return result # 正文采样 def sample_article_content(content: str, sample_chars: int 2000) - str: 按比例从开头、中间、结尾各采样一部分拼成摘要块。 paragraphs [p.strip() for p in content.splitlines() if p.strip()] # 过滤太短的无意义段落 paragraphs [p for p in paragraphs if len(p) 15] total len(paragraphs) if total 0: return content[:sample_chars] head paragraphs[: max(1, int(total * 0.4))] middle paragraphs[int(total * 0.3): int(total * 0.7)] tail paragraphs[max(int(total * 0.7), int(total * 0.5)):] sampled head middle tail result .join(sampled) return result[:sample_chars] # 正文深挖 BODY_PROMPT 你是一名资深的内容编辑正在为下面这篇文章添加标签。 文章标题{title} 文章正文节选{content_sample} 请基于标题和正文完成以下任务 1. 找出标题没有覆盖到的关键主题和子主题 2. 提炼出技术方向、核心概念、应用场景、目标读者等维度上的标签 3. 排除文章中的修饰性内容比如情绪表达、背景铺垫 4. 输出不超过 5 个标签 5. 只输出 JSON 数组不要输出其他内容 输出格式[标签1, 标签2, 标签3] def extract_tags_from_body(title: str, content: str) - List[str]: sample sample_article_content(content) result llm_chat_json( system_prompt你是一个严谨的标签生成助手。, user_promptBODY_PROMPT.format(titletitle, content_samplesample), temperature0.3, ) return result # 融合裁剪 MERGE_PROMPT 以下是两个编辑给同一篇文章打的标签请合并重复项和同义词保留更合理的表述。 要求 1. 合并语义相同的标签 2. 剔除含义过宽、没有信息量的泛标签 3. 最终输出 3 到 8 个标签 4. 只输出 JSON 数组不要输出其他内容 标签A{tags_a} 标签B{tags_b} def merge_tags(tags_a: List[str], tags_b: List[str]) - List[str]: # 先做一次简单过滤减少无效调用 tags_a [t for t in tags_a if t not in FORBIDDEN_TAGS] tags_b [t for t in tags_b if t not in FORBIDDEN_TAGS] merged llm_chat_json( system_prompt你是一个严谨的标签合并助手。, user_promptMERGE_PROMPT.format( tags_ajson.dumps(tags_a, ensure_asciiFalse), tags_bjson.dumps(tags_b, ensure_asciiFalse) ), temperature0.1, ) return merged[:DEFAULT_MAX_TAGS] # 编排主流程 def generate_article_tags(title: str, content: str) - List[str]: tags_from_title extract_tags_from_title(title) tags_from_body extract_tags_from_body(title, content) final_tags merge_tags(tags_from_title, tags_from_body) return final_tags # 带缓存的批量处理版本 _CACHE {} def generate_article_tags_cached(title: str, content: str) - List[str]: 同样的内容不重复调用模型节省成本。 key hashlib.md5((title || content[:2000]).encode(utf-8)).hexdigest() if key in _CACHE: return _CACHE[key] tags generate_article_tags(title, content) _CACHE[key] tags return tags if __name__ __main__: title 从零实现一个轻量级 Web 服务器我踩了这些坑 content 这里填入文章正文 try: print(generate_article_tags_cached(title, content)) except Exception as e: print(f标签生成失败{e})注意几个细节temperature参数在标题预提炼和正文深挖阶段设为 0.2 到 0.3保持稳定在合并裁剪阶段设为 0.1因为这一步要的是确定性归一不需要创造力。温度越低输出越保守这是控制幻觉最直接的手段。采样函数里把“开头 40%、中间 30%、结尾 30%”分开取是因为文章通常在开头讲背景、中间讲操作、结尾讲总结三个部分各含关键信息按段落比例分布采样最保险。缓存键只用正文前 2000 字避免超长 Key同时不影响重复判断的准确率因为同标题同开头基本可以确认为同一篇文章。3.6 提示词工程中的几个稳定增效技巧这节是很有价值的实操心得直接分享几个我在打磨过程中验证有效的提示词小技巧。技巧一给模型一个“身份流程指令”。在正文深挖的提示词里先说明“你是一名资深内容编辑”再说明“正在为下面这篇文章添加标签”。实验对比中带身份描述的标签结果比裸提示词在准确率上高出大约 5 到 8 个百分点原因是身份描述激活了模型关于编辑工作方式的常识。技巧二把“不要做什么”写清楚。比如“禁止臆测”“排除修饰性内容”“只输出 JSON 数组”。大模型对否定指令的遵从度其实不稳定但明确写出来仍然能减少大量无效输出。我测试过在提示词里同时写明“要做什么”和“不要做什么”的稳定度最高。技巧三关键变量统一通过格式化字符串注入。不要在提示词里手写拼接内容避免引号冲突和长文本遗漏。用.format()或 f-string 注入即可JSON 解析时也更稳。4. 常见问题与排查实录这套系统上线跑了几个月遇到过不少实际问题我挑几个最具代表性的整理成速查表。问题表现原因解决方案标签过泛输出“人工智能”“方法”“技巧”模型倾向于输出高频泛词维护禁词表并在提示词中要求“剔除含义过宽标签”漏掉关键子主题文章后半段的案例没出现在标签里一次性传长文本导致注意力分散采用分段采样开头/中间/结尾分别抽内容标签幻觉出现文章完全没有提到的概念标题过于抽象或模型被自己的知识先验带偏降低 temperature增加“禁止臆测”指令抽样人工复核标签数量不稳有时 2 个有时 10 个模型对数量限制的遵从不稳定提示词中把数量要求放在靠前位置并在融合裁剪阶段强控 max_tags批量调用超时处理 500 篇时频繁报错同步请求阻塞或模型限流改用并发池限制最大并发数 5增加指数退避重试逻辑不同模型效果差异大本地小模型输出乱、API 模型效果正常小模型抽象理解能力不足API 为主敏感数据走小模型双轨后续做联合精排下面挑几个重点问题展开说说。4.1 标签泛化问题限都限不住后来怎么解决的标签过泛是这个项目里我最头疼的问题。模型总喜欢在标签列表里塞“人工智能”这种大而全的词尤其当文章标题里出现了“AI”字样时。一个“AI 医疗影像”的文章模型很可能给出“人工智能”“医疗”“影像”这三个标签而实际上“肺结节检测”“深度学习模型”“医学图像分割”才是更有价值的细粒度标签。后来我做了三件事来解决。第一在提示词里加入明确限制“标签必须具体到能区别于同主题下的其他文章禁止使用含义过宽的词”。模型收到这个指令后泛标签数量明显减少。第二维护禁词表把已经识别的泛标签直接过滤。第三在融合裁剪的提示词里专门加一条“剔除没有信息量的泛标签”因为合并同义词时模型也会顺带做一次判断。这三层下来泛标签占比从最初的 40% 降到了 10% 以下。不过说实话10% 的比例仍然存在因为有些标签是“语境泛化”的比如一篇技术对比文章标签“对比”就很合理但禁词表没法穷举只能靠后续人工定期抽检。4.2 标题与正文信息差太大标签偏离真实内容这个坑出现最多的场景是“教程型文章”用了“经验分享型标题”。举个例子标题是《记一次生产事故的复盘》文章正文其实通篇在讲“Redis 缓存雪崩”“熔断降级”“高并发架构设计”。标题预提炼阶段给出的标签是“生产事故”“复盘”这个方向没错但完全丢了核心技术内容。如果直接拿这个结果当最终标签这篇文章在搜索“缓存雪崩”时就不会被检索到。正文深挖环节就是为这种情况兜底的。我用一个简单的对比实验来说明只跑标题阶段这篇“生产事故复盘”的标签是[生产事故, 复盘, 经验]跑完整流程后标签变成了[Redis, 缓存雪崩, 高并发架构, 生产事故, 熔断降级]覆盖面提升非常明显。这个案例也提醒我正文采样绝不能简单粗暴地只取开头几百字。如果按开头取只能拿到“从前有一个系统”拿不到核心技术点。所以才需要按结构采样中间部分一定要取那是绝大多数教程文章的核心内容所在。4.3 幻觉标签怎么判断怎么压下去幻觉标签是这个项目里风险最高的一个问题比标签泛化还危险。泛标签最多是没用幻觉标签是错误信息。比如一篇讲“MySQL 索引优化”的文章模型可能生成一个“数据库分库分表”标签但正文根本没提分库分表这就是幻觉。它在语义上跟数据库相关模型就自动脑补了。我压幻觉标签的措施按有效性排序是第一降温度。标签生成任务真不需要太多创造性temperature 0.2和temperature 0.7幻觉比例差很多。第二提示词里强约束“标签只能基于给定文章内容禁止反向推断。” 这一步约束效果有限但必不可少。第三抽样人工审核每周从自动生成的结果里随机抽 100 篇人工检查幻觉标签占比持续监测模型效果是否漂移。第四当某个标签在同一模型近期输出中反复出现且不在正文关键词列表里时把它列入“重点抽检词表”单独加一道规则过滤。即使做了这么多防护我仍建议在实际业务中不要把标签生成做成“一次性全自动”至少要保留一个“人机协同”的校验节点。下面一节专门讲这个问题。4.4 批量处理性能优化并发、重试和降级批量处理是另一个容易翻车的地方。最开始我直接遍历文章列表同步调用 API处理 300 篇耗时约两小时而且中途经常有请求失败。后来用concurrent.futures做了简单的并发控制处理时间从 2 小时压缩到了 25 分钟。核心思路如下from concurrent.futures import ThreadPoolExecutor, as_completed def batch_generate(articles: list, max_workers: int 5) - dict: results {} with ThreadPoolExecutor(max_workersmax_workers) as executor: future_map { executor.submit(generate_article_tags_cached, art[title], art[content]): art[id] for art in articles } for future in as_completed(future_map): art_id future_map[future] try: results[art_id] future.result() except Exception as e: results[art_id] { status: failed, error: str(e) } return results另外两个细节值得单独强调。重试策略遭遇限流时直接重试通常会失败使用“指数退避 抖动”的效果好得多。降级策略当系统连续三次调用都超时或返回异常时自动把整个流程降级为“仅用标题预提炼 规则标签抽取”保证批处理流程不中断。宁可标签质量略低也不能让线上流程完全卡死。性能目标实测并发数控制在 5 到 8单篇延迟约 12 秒500 篇文章可在 20 到 30 分钟内完成。如果时延要求更严可以只用标题预提炼阶段单篇延迟能压到 3 秒以内只是覆盖度会有所下降。5. 标签质量评估与人机协同落地5.1 怎么评估自动标签好不好用很多团队会忽略评估这一步直接凭感觉说“效果不错”。其实标签生成是可以做量化评估的我的评估方法分三层。第一层准确率。抽取 100 篇文章每篇由两个人分别标注“正确标签数”计算正确标签占所有生成标签的比例。准确率达到 70% 以上我认为这个系统进入可灰度状态超过 80%基本可以大规模上线。这里有个经验模型标签比人工标签更“全”但不够“准”经常出现多个同义标签比如同时给“Nginx”和“Nginx 配置”评估时算 1 个正确标签而不是 2 个。第二层覆盖率。核心是检查正文中最核心的 3 个主题是否都能在标签里找到对应表达。这一层直接决定文章的检索和推荐能不能命中。覆盖率标准我设定为核心主题覆盖率达到 80% 以上。第三层可用性。就是标签是否适合对外展示。有些标签虽然准确但看起来像“垃圾标签”比如“教大家一个方法”这种属于机器生成的典型语感问题。这类标签只能靠禁词表和人工抽检逐步清理。5.2 人机协同的编辑工作流设计全自动生成标签不是最优解我实践中认为正确姿势是“AI 生成初稿 编辑快速确认”。具体工作流如下AI 生成标签后在编辑的后台展示为“推荐标签”状态。编辑可以一键采纳全部标签也可以修改、删除、增加。编辑确认后的标签进入正式状态并同步回 AI 模型做在线学习参考。这样做的好处是编辑不用从零开始想标签工作负担大幅降低AI 的生成结果持续被人工修正相当于每次人工确认都是一次免费标注。经过一段时间后可以统计“不修改直接采纳”的比例当这个比例超过 85%说明 AI 生成质量足够高此时再考虑全自动。我最初做的时候没有加“确认”这一步直接全自动结果出现了一些标签与内容偏离的案例被用户反馈之后才意识到让专业编辑在发布环节做一层轻量把关是在成本和质量之间最平衡的模式。5.3 标签系统的后续扩展方向这套“标题正文提炼标签”的架构后续可以很方便地扩展到几个方向。第一个方向是自动摘要生成。标签本身就是对文章最浓缩的摘要把标签扩展成一句完整的话就能输出文章摘要。提示词稍做调整让模型先提炼标签再基于标签生成摘要摘要质量比直接生成更好。第二个方向是话题聚类和关联推荐。有了统一规范的标签体系之后把相同标签的文章归并到同一个内容聚合页直接提升专题页和推荐流的丰富度。第三个方向是 SEO 优化。自动生成的标签可以直接用于页面关键词标签、搜索描述、站内相关推荐模块帮内容在搜索引擎和站内搜索里都获得更好的曝光。第四个方向是面向用户阅读体验的“内容地图”。在文章顶部展示标签后用户扫一眼就能判断“这篇文章跟我有没有关系”停留率和跳出率都能得到改善。这套系统不会取代编辑而是把编辑从“从无到有想标签”的低价值劳动中解放出来让编辑把精力放到真正重要的选题策划和内容判断上。我在实际项目中还有一个切身的感受标签系统的价值前期不在技术而在于公司内部对“标签到底怎么定义”达成一致。这个一致不是开会能解决的而是要让系统跑起来让编辑看见 AI 生成的标签再逐步修正到大家公认的标准上。这个过程大概需要一两周但只要坚持迭代标签生成质量会在一段时间内持续上升。最后再分享一个细节给标签生成模块单独接一个日志系统把每次的标题、正文采样、模型输出、最终标签、编辑修改记录全部存下来。这不仅能帮你持续优化提示词也能在出问题时快速定位是模型的问题还是流程的问题。这套方案我已经跑了大半年如果你正在被人工打标折磨照着这个思路复现一套一定省下大量时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑