
这两年大模型的热度一直居高不下几乎每个技术团队都在讨论“要不要用 LLM 重写现在的系统”。但如果你真正做过一段时间业务落地会发现一个很有意思的现象那些日活很高、要求稳定低延迟的推荐、风控、搜索排序系统核心模型依然是 GBDT、逻辑回归、随机森林这些经典机器学习模型。LLM 并没有取代它们反而在越来越多的场景里变成了它们的数据上游。这篇文章我想围绕一个核心观点展开LLM 不是替代经典 ML而是给经典 ML 喂数据。我们会先讲清楚两者的边界再拆解一种已经可以落地实践的工程模式用 LLM 从非结构化文本中提取结构化特征把特征送入经典模型做训练和推理。最后会给出完整可运行的 Python 示例、工程落地要点、常见问题排查和最佳实践。如果你正在做推荐系统、风控模型、用户画像、工单分类这一类业务这篇文章会很有参考价值。1. 背景LLM 与经典 ML 不是替代关系而是分层协作1.1 为什么会有“LLM 会取代经典 ML”的错觉过去两年大语言模型的能力确实让人印象深刻。无论是文本摘要、情感分析、实体抽取、代码生成还是复杂指令理解LLM 的表现都远超几年前的 NLP 模型。于是很多技术文章开始渲染“大模型会终结传统机器学习”的观点甚至有人认为只要把数据丢给 LLM就能直接得到最终答案。这种观点的最大问题在于混淆了“模型能力”和“工程可用性”。从模型能力上看LLM 确实能做很多事但从业务系统角度看一个模型要落地不只是“效果够好”就行。它必须满足成本可控、延迟可接受、可回滚、可监控、可解释、可测试这一系列工程要求。在这些方面经典机器学习模型依然有非常大的优势。1.2 重新定义 LLM 与经典 ML 的边界要理清两者的关系可以先看一张简化分工图原始数据文本、图像、日志、行为序列 ↓ LLM 层理解、抽取、清洗、结构化、增强 ↓ 结构化特征数值、类别、向量、规则化标签 ↓ 经典 ML 层分类、回归、排序、聚类、异常检测 ↓ 业务决策在这个链路里LLM 扮演的角色更像是一个“特征工厂”。它负责把难以用传统规则处理的非结构化信息转换成经典模型喜欢的结构化输入。经典 ML 模型则继续负责最终的业务决策在稳定性、可解释性和资源消耗上发挥优势。两者不是竞争关系而是上下游协作关系。1.3 我为什么更看好这种“LLM 喂数据”的模式在真实业务场景里数据从来不是整齐的表格。大量信息藏在工单文本、客服对话、商品描述、评论内容、合同条款里。过去我们只能用 TF-IDF、Word2Vec、BERT embedding 这些方式做文本表示但效果有限尤其是面对长文本、隐含意图、多层语义的时候。LLM 的出现给了我们一个新选项与其让经典模型直接理解原始文本不如让 LLM 先把文本“翻译”成经典模型更容易理解的信号。比如判断一段客服对话里用户是不是愤怒、工单里是否包含财务问题、商品描述里有没有夸大宣传这些信号过去需要人工打标现在可以用 LLM 自动生成。这就是“LLM 喂经典 ML”的核心价值。2. 为什么经典 ML 仍然不可替代2.1 成本与延迟每次预测都调用大模型并不划算如果你把一个高并发的推荐系统改成每次请求都调一次 LLM成本会非常夸张。假设接口 QPS 是 2000每次请求需要生成 300 token按常见的计费方式计算一个月的模型调用费用可能比整个推荐团队的年预算还高。更关键的是延迟。LLM 生成 300 token 通常需要几百毫秒到几秒而推荐系统要求的是几十毫秒级别。如果把 LLM 放在主链路里整体 RT 会直接超标用户体验会受到明显影响。经典模型则完全没有这些问题。一次随机森林的预测只需要微秒到毫秒级别甚至可以批量并行部署在廉价 CPU 实例上就能支撑很高的 QPS。所以在高并发、低延迟的核心链路上经典 ML 依然是首选。2.2 可解释性与合规要求在很多行业里模型决策必须能向用户或监管方解释。比如信贷审批客户被拒绝后你有义务告诉他为什么被拒绝。如果是基于“规则变量 逻辑回归权重”来做判断我们可以明确说出“因为最近 3 个月逾期次数为 2信用分低于阈值所以被拒绝”。但如果你把决策完全交给一个黑盒大模型很难解释它具体参考了哪些变量更难以向监管方提供可审计的证据。经典模型虽然也有复杂度天花板但至少在工程上可以通过特征重要性、SHAP 值等方式给出比较清晰的解释路径。这在风控、金融、医疗、政务等场景里是硬约束。2.3 稳定性和可测试性大模型每次升级都有可能改变输出分布哪怕只是提示词里加了一个词都可能导致线上效果波动。这种“版本漂移”在生产环境里非常痛苦。经典模型在这个问题上要稳定得多。训练完成后模型参数就固定了特征分布一旦监控正常预测结果就是可预期的。测试也更容易因为输入输出维度都是确定的可以写非常严格的单元测试和回归测试。所以从系统工程角度看经典 ML 在可维护性上的优势决定了它不会被轻易替换掉。3. 核心模式拆解LLM 如何变成“特征工厂”3.1 传统特征工程的三个瓶颈在 LLM 出现之前我们处理非结构化文本特征主要靠三类方式词频统计类特征TF-IDF、词袋模型。这类方式实现简单但丢失了语序和上下文信息对语义理解几乎没有帮助。静态词向量Word2Vec、GloVe。能够表达词的语义但无法处理一词多义也没有办法通过上下文动态调整。预训练模型向量BERT embedding。效果比前两者好很多但对于“我需要一个明确的业务标签”这件事仍然需要在下游接一层分类头。换句话说传统方式的输出要么是“数值向量”要么是“粗糙的统计信号”它们不能直接告诉业务方“这是一条紧急工单”。3.2 LLM 做特征提取的价值点LLM 在特征提取上的优势不只是“理解语义”而是“可以直接输出业务定义的结构化结果”。举个例子。过去我们判断一段客服对话是否包含“用户想要退款”的意图需要标注数据、训练一个意图识别模型。现在可以让 LLM 直接输出一个下拉框级别的结果{has_refund_request: true, refund_reason: 商品质量问题}这个输出可以直接成为特征也可以进一步映射成数值特征供经典模型使用。这就是 LLM 作为特征工厂的意义它把原来需要标注团队、训练团队花几周做的事情压缩成一次带提示词的批量调用。3.3 两条典型技术路线当前工程上比较常用的路线有两条第一条LLM 抽取 经典模型决策。LLM 负责从文本中抽取结构化信息类别标签、数值评分、实体、摘要经典模型负责把这些信息和原有结构化特征融合做最终预测。这种方式适合业务规则复杂、需要可解释性的场景。第二条LLM embedding 经典模型决策。LLM 直接生成文本向量embedding然后将向量降维或直接作为特征输入给经典模型。这种方式信息保留更完整但可解释性稍弱一些。本文的实战部分我会以第一条路线为主因为它的可解释性更强也更贴近“LLM 喂经典 ML”这个主题。4. 实战案例LLM 提取特征 经典模型做工单紧急度分类4.1 场景说明与数据集假设我们运营一个企业客服系统每天会收到大量客户工单。每条工单有以下几个字段customer_level客户等级取值为 1 到 5数值越大等级越高。history_ticket_count该客户历史提交工单数量。ticket_text工单正文是一段非结构化文本。业务方希望构建一个模型自动判断当前工单是否需要加急处理标签为is_urgent取值为 0 或 1。这里有一个现实问题历史工单里有很多信息只存在于文本中比如“客户威胁投诉”“客户多次来电”“涉及金额较大”“服务已经持续三天没有解决”等。这些信息很难通过简单的关键词规则覆盖但恰恰是判断是否加急的关键信号。我们的方案是用 LLM 从ticket_text中提取 6 个结构化特征。将这 6 个特征与原始数值特征合并组成完整训练矩阵。训练一个逻辑回归模型对比“只用原始特征”和“加上 LLM 特征”的效果差异。4.2 环境准备本文示例使用 Python 3.9依赖如下pandas数据处理。scikit-learn经典机器学习建模与评估。openai 或兼容 OpenAI 协议的 SDK调用 LLM。安装命令pip install pandas scikit-learn openai由于真实 LLM 调用需要 API Key 且计费为了方便你直接跑通核心流程我会在特征提取部分做一个“模拟 LLM 输出”的版本。模拟版本返回的数据结构与真实调用一致你可以把它替换成真实的 LLM 接口调用不影响下游建模部分。4.3 创建示例数据先创建一份模拟的工单数据包含 200 条记录。这里为了演示我只贴出前几行。import pandas as pd data { customer_level: [3, 5, 2, 4, 1, 3], history_ticket_count: [1, 8, 0, 3, 10, 2], ticket_text: [ 客户反馈商品颜色不对希望换货语气平静。, 客户是大客户连续三天无法登录系统威胁要解除合同。, 客户咨询发票抬头如何修改需要提供操作指引。, 客户要求退款但商品已经拆封客服需要进一步核实。, 客户是黑钻会员反馈物流长时间未更新情绪激动要求赔偿。, 客户询问周末是否有人工客服值班。, ], is_urgent: [0, 1, 0, 1, 1, 0], } df pd.DataFrame(data) print(df)实际使用中你可以用自己业务的工单表替换这个 DataFrame。4.4 用 LLM 抽取结构化特征这一步是整篇文章的核心用 LLM 把非结构化工单文本“翻译”成结构化特征。我们需要让 LLM 从每个工单中输出以下字段is_emotional客户情绪是否激动或负面取 0 或 1。has_compensation_request是否包含赔偿或退款诉求取 0 或 1。has_churn_risk是否包含流失风险信号如威胁取消、解除合同取 0 或 1。mentions_vip文本中是否提到客户属于高价值会员取 0 或 1。issue_complexity问题复杂度评分范围 1 到 5。service_quality_complaint是否包含对服务质量的投诉取 0 或 1。这里我先给出真实调用 LLM 的示例代码使用的格式是 OpenAI 兼容接口。需要注意不同平台的接口参数会略有差异请根据你实际使用的模型服务调整。import os from openai import OpenAI client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) def extract_features_with_llm(text: str) - dict: prompt f 你是客服工单分析助手。请阅读下面这条工单内容抽取以下结构化信息。 只返回 JSON不要返回其他解释。 工单内容 {text} 需要输出的 JSON 字段 {{ is_emotional: 0 或 1, // 客户情绪是否激动或负面 has_compensation_request: 0 或 1, // 是否包含赔偿或退款诉求 has_churn_risk: 0 或 1, // 是否包含流失风险信号 mentions_vip: 0 或 1, // 是否提到高价值会员身份 issue_complexity: 1 到 5, // 问题复杂度评分 service_quality_complaint: 0 或 1 // 是否包含服务质量投诉 }} response client.chat.completions.create( modelyour-model-name, messages[ {role: system, content: 你是工单特征提取助手。}, {role: user, content: prompt}, ], temperature0, response_format{type: json_object}, ) content response.choices[0].message.content return json.loads(content)为了本地跑通流程我再给一个模拟版本。模拟输出基于简单的关键词规则生成仅用于展示建模代码不代表真实 LLM 效果。import random def extract_features_with_llm_simulated(text: str) - dict: text text or return { is_emotional: 1 if any(k in text for k in [激动, 威胁, 愤怒, 投诉]) else 0, has_compensation_request: 1 if any(k in text for k in [退款, 赔偿, 换货]) else 0, has_churn_risk: 1 if any(k in text for k in [解除合同, 流失, 不再续约]) else 0, mentions_vip: 1 if any(k in text for k in [大客户, 黑钻, VIP]) else 0, issue_complexity: random.randint(1, 5), service_quality_complaint: 1 if any(k in text for k in [服务太差, 没有解决, 客服态度]) else 0, }把真实版本和模拟版本放在一起是想强调一个工程思路LLM 调用层应该被封装成统一接口这样你在开发环境可以用模拟函数测试下游逻辑在生成环境再切换成真实调用。4.5 批量处理并构造特征矩阵拿到单条工单的特征后我们需要批量处理整个训练集。要注意真实 LLM 调用会消耗时间和费用所以工程上会先做缓存避免重复调用。import json # 为每条工单生成 LLM 特征 llm_feature_list [] for text in df[ticket_text]: feat extract_features_with_llm_simulated(text) llm_feature_list.append(feat) llm_feature_df pd.DataFrame(llm_feature_list) # 合并原始特征与 LLM 特征 feature_df pd.concat([df[[customer_level, history_ticket_count]], llm_feature_df], axis1) label df[is_urgent] print(feature_df.head())合并之后每一条工单就变成了一行“数值特征 类别特征”的结构化数据可以直接喂给经典模型了。4.6 训练经典 ML 模型并对比效果这里使用逻辑回归作为分类器。为了说明 LLM 特征的价值我训练两个模型模型 A只用原始数值特征。模型 B原始数值特征 LLM 抽取特征。然后比较两个模型在测试集上的 AUC曲线下面积和 F1 值。from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_auc_score, f1_score # 为了演示多一些样本这里把数据复制扩充到 1000 条 df_expanded pd.concat([df] * 50, ignore_indexTrue) # 重新生成 LLM 特征模拟 llm_feature_list [] for text in df_expanded[ticket_text]: feat extract_features_with_llm_simulated(text) llm_feature_list.append(feat) llm_feature_df pd.DataFrame(llm_feature_list) base_features df_expanded[[customer_level, history_ticket_count]] full_features pd.concat([base_features, llm_feature_df], axis1) labels df_expanded[is_urgent] # 训练集 / 测试集划分 X_train_base, X_test_base, y_train, y_test train_test_split( base_features, labels, test_size0.3, random_state42 ) X_train_full, X_test_full, _, _ train_test_split( full_features, labels, test_size0.3, random_state42 ) model_base LogisticRegression(max_iter1000) model_base.fit(X_train_base, y_train) model_full LogisticRegression(max_iter1000) model_full.fit(X_train_full, y_train) # 预测与评估 pred_base model_base.predict_proba(X_test_base)[:, 1] pred_full model_full.predict_proba(X_test_full)[:, 1] auc_base roc_auc_score(y_test, pred_base) auc_full roc_auc_score(y_test, pred_full) pred_base_label model_base.predict(X_test_base) pred_full_label model_full.predict(X_test_full) f1_base f1_score(y_test, pred_base_label) f1_full f1_score(y_test, pred_full_label) print(f原始特征模型 - AUC: {auc_base:.4f}, F1: {f1_base:.4f}) print(fLLM特征增强模型 - AUC: {auc_full:.4f}, F1: {f1_full:.4f})在这个示例中受限于模拟数据的写法两个模型的效果差异可能不直观。但在真实业务场景里当文本中的关键信号无法被传统规则覆盖时LLM 特征带来的 AUC 提升通常会在 0.02 到 0.1 之间尤其是在工单分类、舆情判断、风险识别这类任务上。4.7 结果说明与落地意义从这个案例可以看出整个流程实际上是在做两件事用 LLM 解决“非结构化文本怎么变成业务信号”的问题。用经典 ML 解决“多特征如何组合决策”的问题。LLM 部分可以持续迭代换更强的模型、优化提示词、增加新的抽取字段。经典模型部分保持稳定只要特征分布不变线上行为就是可控的。两者解耦后团队可以分别迭代互不阻塞。5. 工程落地要点别把 LLM 调用写进主链路5.1 LLM 调用层要做缓存与批量离线化在真实生产环境里直接在线调用 LLM 抽取特征通常不是最优选择。更推荐的方式是“离线批量抽取 特征存储 在线读取”。流程大致是每天定时任务读取新增工单。调用 LLM 抽取特征将结果写入特征表。在线服务从特征表读取特征送入经典模型。这样做的好处是LLM 调用产生的延迟和波动被隔离在离线链路中不影响在线服务稳定性。同时缓存结果可以避免重复计费。5.2 特征版本管理LLM 提示词的微小改动可能导致特征分布发生变化。做好特征版本管理非常重要。推荐做法是给每个版本的 LLM 特征加一个feature_version字段例如v1、v2。模型训练时记录使用了哪个版本的特征。这样当线上效果出现波动时你可以快速定位是特征变了还是模型参数变了还是数据分布变了。5.3 超时与重试机制LLM 接口调用不可避免会出现超时、限流、返回格式异常。工程上建议设置合理的超时时间例如 10 秒。失败重试 2 到 3 次但要注意退避策略避免打爆上游接口。解析 JSON 失败时要有兜底策略比如将特征置为默认值并写入日志。这里有一个判断逻辑值得注意如果 LLM 特征解析失败是保存一条默认特征还是丢弃这条数据我的建议是在离线批量抽取阶段保存默认特征并记录失败原因同时用人工或规则补采的方式修复而不是直接丢弃否则会导致测试集和线上特征分布不一致。6. 常见问题与排查思路在实际项目中你大概率会遇到下面这些问题。这里整理了一张排查表。问题现象常见原因解决思路LLM 返回内容不是合法 JSON模型上下文设置不对提示词没有约束输出格式使用response_format参数强制 JSON 输出在提示词里强调“只返回 JSON”增加解析失败重试LLM 特征在训练集和测试集分布不一致提示词版本不同或模型版本不同统一特征抽取版本训练和预测使用同一批离线特征加了 LLM 特征之后模型效果反而下降特征与标签高度相关但部分样本标注噪声大特征数量太少导致过拟合检查特征与标签相关性增加样本量用正则化更强的模型LLM 调用成本过高每条样本都调用一次且没有缓存引入缓存层对相似文本做去重使用批量接口线上模型预测延迟高LLM 调用被放进了在线主链路改为离线抽取 特征存储在线只读取特征不调用 LLM特征缺失值变多LLM 抽取失败或字段名变更增加失败兜底逻辑建立特征质量监控统计缺失率和默认值占比排查这类问题有一个通用套路先确认数据链路。特征是从哪里产出的有没有缓存版本是什么解析有没有失败。再确认模型链路。模型是谁训练的用的哪个版本特征训练集和线上特征是否同源。最后确认业务链路。标签口径有没有变业务规则是否更新。7. 最佳实践与工程建议基于我接触到的项目经验下面这些建议会帮你在实际落地时少踩很多坑。7.1 明确 LLM 的职责边界LLM 不是万能的。在你的系统里它应该只负责“理解文本、抽取信号”这件事不要让它直接做业务决策。业务决策应该由经典模型结合所有特征来完成。这样职责清晰出现问题也容易回溯。7.2 设计稳定的特征映射LLM 输出的原始结果通常是文字比如service_quality_complaint: 是。在送入模型前需要统一映射为数值。建议在特征抽取层输出规范 JSON 后再做一次字典映射FEATURE_MAP { is_emotional: {是: 1, 否: 0, unknown: 0}, has_compensation_request: {是: 1, 否: 0, unknown: 0}, has_churn_risk: {是: 1, 否: 0, unknown: 0}, mentions_vip: {是: 1, 否: 0, unknown: 0}, }所有无法解析的值统一落到unknown再映射到 0。这样可以避免特征解析失败导致模型异常。7.3 对 LLM 特征做质量监控每个特征都应该有对应的监控指标。最简单的监控方式是统计每个字段的取值分布观察分布是否在周维度、日维度发生明显漂移。一旦发现某个字段大量出现默认值或者取值为 1 的比例突然从 20% 涨到 60%就要立刻检查上游 LLM 调用是否出了问题。也可以把 LLM 特征当作普通特征做模型训练前的特征重要性分析。如果某个字段在业务上很重要但重要性始终很低可能需要检查提示词是不是写得不准确。7.4 处理好冷启动与人工回流LLM 特征抽取输出的标签并不 100% 准确。无论模型效果多好建议在高风险决策场景保留人工抽检机制。给每批 LLM 抽取结果做一定比例的人工复核把复核数据存入样本库后续可以用于评估 LLM 特征的质量变化。这也是“LLM 喂经典 ML”和“纯 LLM 决策”相比的一个重要工程优势中间多了一层可审计、可干预的特征层。7.5 控制样本量和特征维度经典模型对特征维度是有限制的。如果你一次性让 LLM 抽取 50 个特征但又只有 2000 条训练样本很容易过拟合。建议先抽取业务上最关键的 5 到 10 个特征跑通链路后再迭代增加。特征选择上也可以借助模型本身的系数或树模型的特征重要性逐步收敛到稳定特征集。7.6 安全与数据合规如果工单文本包含用户隐私信息直接调用外部大模型需要格外小心。两种情况要区分开私有化部署的 LLM数据不出内网合规风险相对可控。云端 API 调用数据会离开本地环境需要先做脱敏处理并且要确认是否符合公司数据安全规范。在实践中最简单的做法是在调用 LLM 前用规则或者小模型把姓名、电话、身份证号、地址等敏感实体替换为占位符比如[NAME]、[PHONE]。这样既能降低合规风险也不影响文本语义理解。8. 总结把大模型放进生产线而不是把整条生产线换掉这篇文章的核心信息其实就一句话LLM 和经典 ML 不是二选一的关系更常见也更务实的做法是把 LLM 当作一个高质量的特征提取器给下游的经典模型提供更有业务语义的信号。我建议你按下面的顺序去实践第一步找到当前业务中最难处理的“非结构化信息瓶颈”。它可能是工单文本、客服对话、商品描述、合同条款、舆情评论。第二步设计一个 LLM 提示词让模型输出 5 到 10 个业务相关的结构化字段。先不用着急训练模型先抽样看抽取结果是否符合业务直觉。第三步把抽取字段作为新特征和原有结构化特征一起送入经典模型计算效果增量。第四步设计缓存、监控、人工抽检机制把整个流程工程化。如果你在未来项目中能把这套链路跑通你会发现一个很有意思的变化原本团队里最花时间的是“业务数据怎么变成可用特征”现在这部分被 LLM 大幅压缩大家可以把精力放到更上层的事情上比如业务策略、模型调优、系统架构。这才是大模型在实际业务中真正的价值。如果你正在做类似的事情欢迎在实践中多验证这套“LLM 做特征、经典模型做决策”的思路。遇到什么问题也欢迎一起交流讨论。