京东智能客服备案登记全流程解析:从合规要求到实战指南
图:备案流程总览
法规背景:三句话速览
《互联网信息服务算法推荐管理规定》把“生成合成类算法”纳入备案范围,智能客服的自动回复、商品推荐均算。未备案上线,平台随时可下架接口,业务直接停摆。备案号要像 ICP 号一样挂在页面底部,用户可查、监管可扫。两条路线:直接调用 vs 自建中间件
| 维度 | 直接调用京东开放 API | 自建中间件转发 | |---|---|---|---| | 网络延迟 | 120-180 ms(含 DNS) | 增加 20-40 ms | | 备案责任 | 京东已备案,开发者仅登记“调用方” | 需重新走算法备案,周期 20 个工作日 | | 维护成本 | 0 人/月 | 0.5 人/月(升级、灰度、回滚) | | 敏感词过滤 | 京东内置,不可自定义 | 可插拔自研词库,DFA 算法 0.3 ms/条 | | 数据出境 | 接口在国内,无额外审批 | 若中间件部署在境外,需数据出境评估 |
结论:对日活 <10 万的轻量业务,“直接调用”最省事;对金融、医疗等强合规场景,自建中间件才能把日志、加密、脱敏全捏在手里。
- 核心实现
3.1 备案字段自动化收集
以下脚本每天 02:00 跑定时任务,把算法信息、版本、训练数据规模自动写进 json,供管局表单一键导入。选用 Python 3.9,兼容 Windows 开发机与 Linux 容器。
# auto_collect.py import os, json, logging, hashlib from datetime import datetime from pathlib import Path logging.basicConfig( filename='collect.log', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s' ) def collect(): try: meta = { "algorithm_name": "JimiSmartReply", "version": os.getenv("ALG_VERSION", "2.3.1"), "training_data": { "size": 2180000, "md5": file_md5("/data/corpus/jimi_train.tsv") }, "input_desc": "用户文本", "output_desc": "客服候选答案 Top-3", "update_freq": "weekly" } out = Path("/backup/jimi_alg_meta.json") out.write_text(json.dumps(meta, ensure_ascii=False, indent=2)) logging.info("collect success -> %s", out) except Exception as e: logging.exception("collect failed") raise def file_md5(path: str) -> str: h = hashlib.md5() with open(path, "rb") as f: for chunk in iter(lambda: f.read(1 << 20), b""): h.update(chunk) return h.hexdigest() if __name__ == "__main__": collect()Java 版思路一致,用 Jackson 写 JSON,MD5 计算可复用 Guava 的Hashing.md5()。
3.2 敏感词过滤——DFA 算法落地
DFA(Deterministic Finite Automaton)把词库构造成“树”,扫描一次文本即可,时间复杂度 O(n),n 为文本长度,与词库大小无关。10 万词库、1 万次调用,平均耗时 0.3 ms,CPU 占用 <1%。
# dfa.py import json, logging, time from collections import defaultdict class DFAFilter: def __init__(self): self.keyword_chains = {} self.delimit = '\x00' def add(self, word): word = word.lower() chars = word.strip() level = self.keyword_chains for i, ch in enumerate(chars): if ch in level: level = level[ch] else: node = {} level[ch] = node level = node chars_len = len(chars) if chars_len not in level: level[self.delimit] = chars_len def parse(self, path): with open(path, encoding='utf-8') as f: for line in f: self.add(line.strip()) logging.info("dfa build done, size=%s", len(self.keyword_chains)) def filter(self, text, repl="*"): start = time.time() text = text.lower() chars = text result = [] begin = 0 while begin < len(chars): level = self.keyword_chains step_ins = 0 for char in chars[begin:]: if char in level: step_ins += 1 if self.delimit in level[char]: result.extend([repl] * step_ins) begin += step_ins break level = level[char] else: result.append(chars[begin]) begin += 1 break else: result.append(chars[begin]) begin += 1 cost = (time.time() - start) * 1000 logging.debug("dfa filter cost %.2f ms", cost) return ''.join(result) if __name__ == "__main__": dfa = DFAFilter() dfa.parse("sensitive_words.txt") print(dfa.filter("京东客服真棒"))图:DFA 树状结构示意
3.3 关键交互序列图
用 Mermaid 描述一次用户提问到返回答案的全过程,含敏感词拦截、备案日志落库。
sequenceDiagram participant U as 用户 participant B as 业务后台 participant M as 中间件 participant D as DFA 模块 participant J as 京东接口 U->>B: 发送问题 B->>M: 转发文本 M->>D: 敏感词检测 alt 命中敏感词 D-->>M: 返回*** M-->>U: 提示重新输入 else 通过 M->>J: 调用智能回复 J-->>M: 候选答案 M->>M: 写备案日志(加密) M-->>B: 返回答案 B-->>U: 展示结果 end- 生产环境注意点
4.1 多地域部署的备案同步
- 每个地域独立备案号,但算法版本号必须全局一致,否则被扫到“版本漂移”会被驳回。
- 用 Git tag 做版本源,发版流水线在华北、华东、华南同时写入对象存储,各 region 的备案脚本拉同一份 meta json,保证 md5 一致。
- 若做 A/B 实验,需在备案系统里提前登记“灰度比例”,否则实验流量超过 5% 即视为“算法变更”,需重新提交。
4.2 对话日志加密存储
日志含用户手机号、地址,属敏感个人信息,需加密后落盘。AES-256-GCM 既防篡改又抗重放,Java 示例:
public final class LogCrypto { private static final String ALG = "AES/GCM/NoPadding"; private static final int TAG = 128; public static SealedObject encrypt(Serializable obj, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance(ALG); cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG, IV)); return new SealedObject(obj, cipher); } public static Object decrypt(SealedObject sealed, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance(ALG); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(TAG, IV)); return sealed.getObject(cipher); } }密钥放 KMS,定期轮换;日志文件按天分割,文件名带“算法备案号”方便审计抽查。
- 收工前自查清单
- [ ] 算法名称、版本、用途、训练数据来源已写进 json,md5 可验证。
- [ ] 敏感词库版本与线上运行 jar 包一致,可回溯。
- [ ] 日志加密密钥具备轮换策略,KMS 审计日志开启。
- [ ] 备案系统里“算法类型”选“生成合成-对话生成”,别选错。
- [ ] 页面底部可见备案号,超链接能点进管局详情页。
官方审核常见驳回点
- “训练数据规模”与“语料 md5”不匹配——脚本里把压缩包当原始文件算 md5 了。
- 灰度实验未提前登记——流量切 10% 被扫到,打回重填。
- 日志明文存储——现场扫描硬盘发现未加密,直接不合格。
- 敏感词过滤缺失——演示环境演示了违规词,审核员顺手测试未拦截。
把上面脚本塞进 CI,第一次提交管局后 7 个工作日就能拿到编号。备案不是“多盖一个章”,而是给业务加一道安全阀。跑通这套流程,后面再接入别的算法也能直接复用,算是一次投入、长期受益。祝各位上线不踩雷,审核一次过。