AI 功能下线:流量、数据、索引与遗留调用方

发布时间:2026/10/25 9:35:08
AI 功能下线:流量、数据、索引与遗留调用方 说明本文讨论的是一个 AI 功能整体下线时的收尾流程属于 AI 运维话题不涉及具体模型版本与价格。AI 领域版本迭代极快凡涉及版本号、价格、可用性请以你阅读时的官方页面为准。文中代码为结构示意请按自己的技术栈调整后再上生产。一、关掉一个进程不等于下线一个功能下线一个 AI 功能最常见的收尾方式是发一条公告、把副本数调到零、把入口摘掉。三件事做完负责人在群里说一句下线了。三个月后账单里还能找到它一个向量集合按月计费一份对话归档表按天增长一个定时任务每天凌晨调三次接口拿到 404 然后记进错误日志没有人看。这些残留物的共同点是都不在服务的部署清单里清单管进程、端口、副本数而一个功能占用的东西宽得多。遗留类型停服务后它还活在哪不处理的后果通常谁先发现流量定时任务、老版本客户端、合作方服务端错误日志每天涨或对方业务静默失败调用方投诉数据对话表、记忆表、产物对象存储存储成本不降删除请求答不上来财务或合规索引向量集合、别名、缓存键前缀误召回、存储计量不降下游检索效果变差配置与提示提示模板、工具注册、密钥、配额模型仍在生成对旧工具的调用线上报错调用方前端入口、内部服务、外部合作方不知道还有谁在依赖往往在最后为什么 AI 功能比普通服务多两摊普通无状态服务下线主要工作是摘流量、清配置、清掉依赖它的调度项。AI 功能会多出两摊原因不在模型本身在它的使用方式。第一它天然带状态。一次交互会留下对话、记忆、摘要、产物这些数据的生命周期比服务长得多。你没法顺便把它们删掉因为删数据有保留期、有用户协议、有审计要求是一套独立流程和停服务不在同一个节奏上。第二它的配置面比普通服务宽。普通服务的配置是环境变量和开关一个 AI 功能的配置还包括提示模板的版本链、注册给模型的工具定义、检索用的索引与别名、单独申请的配额。这些东西没有统一清单散在四个系统里每一个都能在服务停掉之后继续产生影响。还有一个更隐蔽的差别普通服务关掉之后调用方拿到的是连接失败问题立刻暴露。AI 功能关掉之后很多调用方不报错——检索返回空结果模型照样生成一段话只是内容不对。这种静默降级让下线少了一个天然探测器你得自己造一个。判断它有没有下线问一句就够把它重新启起来还有谁会来用。二、先盘调用方五类遗留里只有调用方会因为你的动作立刻报错所以它排第一。盘不全的代价很直接你在第三阶段拒绝了请求对方业务流程断了而这条链路从来没出现在你的名单上。三个信息源各缺一块网关日志、鉴权记录、代码搜索三个源各有盲区必须交叉。网关日志能给出调用量、时间分布、客户端版本但主体标识往往只有一个 app_id 或源 IP对这是哪个团队基本无解。窗口至少 90 天只看 30 天会漏掉季度任务。鉴权记录能把 app_id 对到一个具体的 key 和申请人这是找到人的唯一途径。盲区是共享 key——一份 key 被三个服务共用你通知到的人只承认自己那部分。代码搜索能找出还没上线、但代码里已经写死的调用这类调用在日志里根本不存在。盲区是它只覆盖你有权限的仓库合作方的代码你搜不到。⚠️ 代码待验证-- 90 天窗口窗口短于季度任务周期就会漏WITHcallsAS(SELECTCOALESCE(a.subject_id,unknown)ASsubject_id,a.app_id,a.client_version,date_trunc(day,a.ts)ASd,count(*)ASnFROMgateway_access_log aWHEREa.pathLIKE/api/assist/v1/%ANDa.tsnow()-interval90 daysANDa.user_agentNOTLIKE%healthcheck%GROUPBY1,2,3,4)SELECTsubject_id,app_id,count(DISTINCTd)ASactive_days,sum(n)AStotal_calls,max(d)ASlast_day,count(DISTINCTclient_version)ASversionsFROMcallsGROUPBY1,2ORDERBYtotal_callsDESC;-- 反向查比上面那条更重要-- 调用量极低但最近仍在调的主体最容易落在名单外-- 条件加上 HAVING sum(n) 10 AND max(d) current_date - 7第二条查询的价值高于第一条。调用量大的主体一定会被注意到一天三次、每周一次的主体不会而它们往往最难改——批处理、月结、监管报送都长这个样子。⚠️ 代码待验证#!/usr/bin/env bashset-euopipefail# 搜的是调用痕迹而不是包名多数调用是拼出来的 URLrg-n--hidden\-g!**/node_modules/**-g!**/.git/**-g!**/vendor/**\-eassist/v1\-eASSIST_ENDPOINT\-eask_v1\(\-elegacy[_-]assist\--stats-l.|teecallers_repos.txt# 命中仓库找最近一次改动的人找不到的单独列出来人工确认whileread-rf;dorepo$(git -C $(dirname$f)rev-parse --show-toplevel2/dev/null||echo$f) who$(git-C$repolog-1--format%ae2/dev/null||echounknown) printf %s\t%s\n $repo $whodonecallers_repos.txt|sort-u搜assist/v1这个路径前缀而不是完整 URL是因为环境变量拼接、网关改写、SDK 内置 base 都会让完整 URL 搜不到。用提交作者当 owner 只是兜底真正的责任方要去 CODEOWNERS 里核对。找不到的那一类最危险三类调用方里外部合作方最难盘。它们不在你的代码仓库里日志里只有一个合作方维度的 app_id而且经常处于我们这边没人负责这件事的状态。这类调用方只能靠拒绝阶段逼出来。前提是拒绝必须显式返回 4xx 加错误码并在网关侧按 subject 计数。如果为了平滑返回 200 加空结果那个每天跑三次的批处理会一直跑下去永远不报错你也永远不知道它在。调用方典型形态首选发现手段容易漏掉的部分通知方式前端入口网页、移动端、桌面客户端网关日志按 path 与版本聚合未升级的老版本客户端应用内公告 版本提示内部服务定时任务、异步队列消费者鉴权记录 代码搜索没有 trace 头的脚本任务工单 负责人签字外部合作方合作方服务端直连网关日志 app_id 商务台账转包给第三方的接口商务函件 技术对接人确认三、流量收口的四步收口不能一步到位。直接全量拒绝会把所有问题压在同一天你既分不清哪条是未迁移、哪条是早就废弃只是没人关也没法回退。四步与各自的观察窗第一步摘入口。前端不再展示入口接口保持可用。观察窗 7 天起依据是周周期——很多内部任务按周跑。晋级判据两条入口曝光计数为 0接口调用量下降的幅度与入口原先带来的量对得上。对不上说明还有直连这时候进第二步等于跳过了排查。第二步降级为只读。写路径返回 409读路径返回历史结果或明确提示。观察窗 14 天。判据是写请求占比低于 1%且剩余写请求的 subject 全部在已知名单里名单外冒出新的 subject就地停止晋级。第三步拒绝并给迁移指引。返回 410响应体里带替代能力的名称和迁移文档地址。观察窗 14 天。判据是名单上每个 subject 都有处置结论——已迁移、已确认停用、已失联但有书面确认三者之一410 全部落在名单内。第四步全量拒绝。在网关层直接短路不再进到服务。观察窗 30 天必须跨过一次月末。判据只有一条30 天内非探测流量为 0。阶段返回什么观察窗下限晋级判据回退动作摘入口正常 2007 天曝光为 0调用量降幅与入口量匹配恢复入口开关只读降级写 409、读历史结果14 天写请求低于 1% 且 subject 在名单内开关回到上一步拒绝加指引410 加迁移信息14 天每个 subject 都有处置结论开关回退保留文案全量拒绝410网关层短路30 天非探测流量为 0回滚网关规则⚠️ 代码待验证feature:legacy_assiststage:reject_with_hint# retired_entry | readonly | reject_with_hint | hard_rejectstages:retired_entry:entry_flag:falseapi_mode:normalmin_observe_days:7readonly:api_mode:read_onlywrite_status:409min_observe_days:14reject_with_hint:api_mode:rejectreject_status:410min_observe_days:14hard_reject:api_mode:gateway_short_circuitreject_status:410min_observe_days:30allowlist:-subject:svc-report-batchuntil:2026-11-30# 必填到期自动收紧reason:月末批量任务改造工单在推进-subject:partner_acmeuntil:2026-11-15reason:合同约定的过渡期response:headers:Deprecation:trueLink:https://internal.example/migrate/assist-v2; rel\successor-version\body:code:FEATURE_RETIREDmigrate_to:assist/v2observe:count_by:subject_idexclude_probe:true# 探测请求按 header 排除否则永远有流量这份开关里有两处是踩过坑才加的。until必填——不带到期时间的白名单会永久存在三年后还有人从里面读配置。exclude_probe是把健康检查和监控探测单独排掉否则流量归零这个判据永远不成立你会先怀疑数据再怀疑自己最后把这一条判据删掉。回退要只改一个字段四步都要求回退只改开关所以收口逻辑必须放在网关或独立配置层不能散在业务代码里用条件判断代码里的判断改一次要走发布有风险就不敢回退可回退的动作最后变成了单行道。四、数据怎么处理数据这块最常见的错误是把它当成一件事。实际是三件处理方式完全不同。类别典型存放保留期依据删除方式怎么证明删了对话与记忆会话表、消息表、用户记忆表用户协议与功能用途按用户或会话分批硬删计数对账 主键抽样回查产物与文件对象存储、附件表业务留存要求先标记再删对象最后清引用对象探测全 404 桶清单核对日志与 trace观测平台、审计库审计要求通常不许提前删只能等自然过期过期策略 分区清单软删字段在下线场景里是敌人大多数业务表的删除都是软删deleted_at打一个时间戳查询时过滤掉。这套做法在功能下线时不成立因为下线的要求是数据不存在不是前台看不见。用户提删除请求你答复说删了数据还在库里躺着索引里也还在。如果历史上一直是软删下线阶段要做一次硬删迁移。两件事要注意分区表优先用DROP PARTITION比DELETE快一个量级也不会把 WAL 打爆硬删之后把deleted_at上的索引一起清掉否则这张表还在为不存在的查询维护索引。删除链路与证明一条完整的删除链路是五步标记待删、异步批删、计数对账、主键抽样回查、出证据。前两步是动作后三步是证明。多数团队只做前两步。证明之所以必要是因为删除失败的方式很安静。批删任务因为一行外键冲突回滚了整个批次日志里只有一行 warning对象存储删了大部分剩下那一小撮因为 key 里带特殊字符一直删不掉。⚠️ 代码待验证importdatetimeimportjsondefverify_deletion(table,id_col,sample_n,conn,obj_probeNone):返回一份可归档的删除证据任一项不达标即判定删除未完成withconn.cursor()ascur:cur.execute(fSELECT count(*) FROM{table})aftercur.fetchone()[0]# 抽样清单来自退役 id 表不是从现表里随机取cur.execute(fSELECT{id_col}FROM{table}_retired_ids ORDER BY random() LIMIT %s,(sample_n,),)ids[r[0]forrincur.fetchall()]cur.execute(fSELECT{id_col}FROM{table}WHERE{id_col} ANY(%s),(ids,))hits[r[0]forrincur.fetchall()]evidence{table:table,checked_at:datetime.datetime.now(datetime.timezone.utc).isoformat(),rows_after:after,sampled:len(ids),sample_hits:len(hits),backup_expiry:backup_expiry_of(table),# 备份中最后一份的过期时间passed:after0andnothits,}ifobj_probe:probeobj_probe(ids)# 逐个 HEAD记录状态码evidence[object_probe]probe evidence[passed]evidence[passed]andprobe[all_missing]returnevidence抽样清单必须来自一张退役 id 表而不是从现表里随机取。从现表里取取到的都是还没删掉的样本天然失败从退役表里取才是真正的回查。这张表本身也要有保留期通常比业务数据多留一个复审周期。备份这件事必须写清楚主库删干净了备份里还有。这一点绕不开只能写进下线档案备份保留多少天、到期后是否自动轮转、期间若被要求恢复恢复出来的数据要不要再删一次。合规问的往往就是这一句。五、索引与向量的回收索引回收分两步别名摘除、物理删除。两步之间必须隔一段观察期因为可回退性差一个量级——摘别名是秒级改回来也是秒级物理删除是分钟到小时删完想恢复只能重建重建的代价是重新算一遍向量。别名先摘集合后删别名是调用方唯一该看到的东西。摘掉别名之后任何还在用旧名字的查询会立刻报别名不存在这是一次免费的探测器比翻日志快得多。⚠️ 代码待验证#!/usr/bin/env bashset-euopipefailVDB${VDB:?required}COLLkb_legacy_assist_v3ALIASlegacy_assistAPPLY${APPLY:-0}# 默认只打印确认后再置 1echo 1. 当前别名指向 curl-sS${VDB}/aliases|jq--arga${ALIAS}.[$a] // noneecho 2. 摘别名保留集合可秒级回滚 [${APPLY}1]curl-sS-XPOST${VDB}/aliases/delete\-Hcontent-type: application/json-d{\alias\:\${ALIAS}\}echo 3. 空查询用下线功能的典型 query 打一次命中必须为 0 curl-sS-XPOST${VDB}/query\-Hcontent-type: application/json\-d{\collection\:\${COLL}\,\query\:\典型问题样例\,\top_k\:5}\|jq.hits | lengthecho 4. 观察期满且第 3 步为 0才允许物理删除 if[${APPLY}1][${CONFIRM_DELETE:-0}1];thencurl-sS-XDELETE${VDB}/collections/${COLL}fi第 3 步的空查询是索引回收里唯一的硬判据。摘了别名不等于没有读者有些代码直接写集合名绕过别名。命中为 0 说明业务路径上没人用了不为 0 说明还有另一条路径在读它这时删就是事故而且要等到下一次回答内容出错才会被发现。逻辑删与物理删的差别多数托管向量库的删除接口是逻辑删标记记录不可见空间要等段合并之后才释放。所以删完了和存储降下来了之间有一段延迟可能是小时级。这个延迟带来一个反直觉的结论账单不能当删除成功的判据。账单降了说明合并跑过了账单没降不代表没删。要确认删除看的是删除计数、空查询结果、以及存储计量在一段时间后的回落趋势。删除计数还有个坑接口返回的是受理数不是实际删除数。删除前后各查一次集合总记录数差值对不上就说明期间有写入先停写再删。留着不删的三种成本存储成本按 GB 月算一个中等规模的集合一年也是一笔看得见的钱但这是最小的一笔误召回和合规才是主要成本。误召回成本更高。同一个向量集合经常被多个检索流程共用下线功能的集合如果还挂在共享检索路径上会把已经下线的知识带进新功能的回答里而且不报错。表现是回答里出现了不该出现的内容排查时几乎没人会先怀疑一个早就下线的功能。合规成本最硬。用户要求删除数据你删了主库、忘了索引等于没删。这一条不会当场暴露只会在某次审计里出现。索引上必须有两个标签owner 和 feature。没有这两个标签半年后没人说得清这个集合属于谁、能不能删。标签要在建集合时写事后补的成本是全量扫一遍元数据。完整版资料清单本文用到的调用方盘点查询、收口开关模板和删除证据脚本都整理在里面了扫码即可获取六、配置、提示与凭据的清理配置面上要清四类提示模板、工具注册、密钥与凭据、配额。共同点是没有统一清单散在四个系统里而且都能在服务停掉之后继续产生影响。提示模板与回退链提示模板通常带版本也通常带回退链主版本不可用时退到上一个版本。下线时如果只删了主版本回退链上还挂着旧模板某个请求失败之后会静默退到旧模板用着已经下线的功能描述去生成内容——结果不报错只是答的是另一件事。做法是给模板加deprecated_at读取路径上命中 deprecated 就打一条日志并计数观察期内计数为 0 才允许物理删除。这个计数和流量收口的计数是两回事前者看谁在读配置后者看谁在调接口两边都归零才算收干净。工具注册要从模型侧删这是 AI 功能独有的一个坑。工具定义注册在模型侧handler 在你的服务侧。功能下线时把 handler 改成返回 410工具定义还留着模型仍然会生成对这个工具的调用用户看到的是系统出错了而不是这个功能不做了。正确顺序是先删模型侧的工具定义观察模型输出里的工具名分布是否还出现它再把 handler 摘掉。顺序反了会留出一段窗口模型在生成一个必然失败的调用。密钥、凭据与配额密钥是最容易被忘的一项。功能下线了key 还有效配额还占着账单上还有一条小额费用挂了几个月没人认领。顺序是配额先缩到 0可逆观察一周确认没有 429 投诉→ 吊销 key不可逆必须有工单号→ 删除 secret 条目配置中心与容器环境变量两处都要清。工单号写进下线档案因为半年后审计问这个 key 什么时候失效的只有工单能答。配额还有个现实约束配额按功能申请不会自动归还。下线不退下一个功能申请时批不下来才有人回头找这笔账。七、下线的时间表与验收四个阶段的时长不是拍出来的每个都有外部依赖。公告下限 14 天。依据不是你想多久是调用方的发布节奏客户端要发版、要过审、要等用户升级三段加起来通常超过两周。只读下限 14 天覆盖两个完整的周周期让按周跑的任务至少撞上两次。拒绝下限 14 天必须跨过一次月末或季末。批量任务都堆在那个时候跑错过就得再等一个月。清理下限 30 天因为备份轮转和向量段合并的延迟都在这个量级短于这个数你看到的删除结果还没稳定。四段相加下限 10 周左右。任何两周下线一个功能的方案基本可以断定漏了某类调用方或某类数据。这不是保守是算术。五个判据判据具体标准证据形式常见假通过流量归零连续 30 天非探测请求为 0网关按 subject 的计数报表探测没排除或统计窗口只有 7 天数据清空目标表行数为 0 且抽样无命中对账结果 抽样清单只做了软删count 查的却是视图索引消失别名与集合都不存在空查询命中 0接口返回 查询结果只摘了别名集合仍被直连读取配置零命中30 天内 deprecated 读取计数为 0配置读取打点只查了配置中心漏了容器环境变量调用方结项名单每行都有终态与责任人名单表 确认记录写了已失联但没有书面确认⚠️ 代码待验证{feature:legacy_assist,retired_at:2026-10-25,window:{announce_days:14,readonly_days:14,reject_days:14,cleanup_days:30},criteria:{traffic_zero:{passed:true,days_observed:30,evidence:gw/report/assist-zero},data_purged:{passed:true,rows_after:0,sampled:200,hits:0,evidence:purge/2026-10-20.json},index_removed:{passed:true,alias:null,collection:null,probe_hits:0},config_zero_hit:{passed:true,days_observed:30,evidence:cfg/read-counter},callers_closed:{passed:false,open:[partner_acme]}},residual_risks:[备份中的历史数据于 2027-01 自然过期期间无法单独删除,托管向量库的物理删除只有接口回执无独立核对手段],review_at:2027-04-25}这份档案里callers_closed是 false 也没关系。写清楚是谁、卡在哪、下次复审在什么时候比凑一个全绿的值有用。下线档案的价值在于半年后能回答当初凭什么判断它下线完了不在于好看。这一章没解决的事三件。多租户共享索引的按租户删除。多数向量库没有行级权限只能重建集合再导入剩余租户的数据代价和集合大小成正比集合越大越不敢做最后拖成先留着。第三方托管存储的物理删除无法自证。你只能拿到供应商的删除回执回执和实际存储状态之间没有可验证的链路能做的只是把回执和请求 ID 一起存档。用户要求删除和审计要求保留的冲突在下线场景里会被放大。同一个功能的数据一部分要删、一部分必须留边界只能按表分不能按行分——按行分的规则没人能长期维护。这三件事都不影响下线本身的收口但都要写进档案的残留风险里。不写下一次有人问起你还是只能重新查一遍。完整版资料清单下线阶段的网关取消计数报表、数据对账脚本和下线档案模板都在里面扫码即可获取附表 A关键取舍一览取舍本文结论判断依据位置下线的起点是什么先把五类遗留列出来再动手部署清单不含数据、索引、配置第一章判断下线是否完成问重启后还有谁在用直接问残留物不问动作第一章调用方盘点从哪开始网关日志、鉴权记录、代码搜索三源交叉每个源都有盲区单看会漏第二章日志窗口取多长90 天短于季度周期会漏批量任务第二章拒绝时返回什么4xx 加错误码并计数200 加空结果等于关掉了探测器第二章收口分几步四步不可合并一步到位分不清未迁移与已废弃第三章允许名单要不要到期必须带 until不带到期的白名单会永久存在第三章收口逻辑放哪网关或独立配置层业务代码里改不动就不敢回退第三章软删能否算删除不能下线要求数据不存在不是看不见第四章删除证据怎么取计数对账 退役 id 抽样从现表抽样必然失败第四章备份里的数据写进档案等自然过期无法单独删除只能声明第四章索引回收顺序先摘别名后删集合可回退性差一个量级第五章删除成功的判据删除计数 空查询 计量回落账单有合并延迟不能单独用第五章配置清理的判据读取计数为 0不是文件里没有配置有四份线上临时改的那份最难找第六章工具下线先删哪侧先删模型侧定义否则模型继续生成必然失败的调用第六章凭据处理顺序配额归零、吊销 key、删条目前两步可逆第三步要工单第六章下线总时长约 10 周下限四段各有外部依赖第七章判据写成什么样每条都要有证据形式没有证据的判据会被凑成绿的第七章附表 B术语速查表术语含义遗留停服务之后仍然存在、仍在被使用的资源调用方盘点找出所有仍在请求这个功能的系统与人subject网关或鉴权侧识别调用主体的标识通常对应一份凭据收口分阶段把流量从可用收到不可用的过程观察窗每个收口阶段必须持续的最短时间晋级判据允许进入下一阶段的可检验条件白名单允许在收口后继续调用的主体清单必须带到期时间探测流量健康检查与监控探针发出的请求统计时要排除软删只标记删除时间、不物理移除行退役 id 表记录曾经存在过的主键用于删除后的抽样回查删除证据能证明数据确实不存在的记录与结果别名指向向量集合的稳定名字调用方只该看到它逻辑删标记不可见空间待合并后释放段合并向量库整理存储段的过程物理空间在此之后才释放回退链提示模板在主版本不可用时依次退回的旧版本序列读取打点在配置读取路径上记录的计数用于判断谁还在读写在最后这篇用到的资料写这篇文章时我把几个模型的官方文档、参数表和实测记录都对了一遍顺手整理成几份配套的东西大模型学习路线图从 LLM 基础到 Agent 开发各阶段该学什么、用什么资料大模型全套教程按主题分好的视频与文档清单大模型实战好书24 本附每本适合的阶段资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「大模型」优先通过。拿到之后建议先看学习路线图那一份先定位自己在哪个阶段再决定学什么比一上来就啃框架效率高得多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询