news 2026/9/3 18:57:37

AI工程化必修课:确定性、可观测性与LLM回归测试落地

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI工程化必修课:确定性、可观测性与LLM回归测试落地

如果你正在做 AI 应用,但团队里还没有人认真对待“可观测性”和“确定性”这两个词,那这篇文章值得你花 10 分钟读完。

这次我们不聊某个具体模型或开源项目,而是聊一个在 AI 工程化过程中绕不开的话题。Charity Majors 的身份是 Honeycomb 的 CTO,也是可观测性领域最有代表性的声音之一。她在一系列与技术博客和播客相关的讨论中反复提到三个词:Determinism(确定性)、Instrumentation(仪器化/埋点)、以及“Eating Your Broccoli”——意思是做那些不酷、但必须做的工程琐事。

翻译成 AI 工程语境就是一句话:别只盯着模型效果,你的 AI 系统在生产环境里能不能被观测、能不能稳定复现、能不能在出错时快速定位,才是真正决定项目生死的事。

本文会把这三个关键词拆成具体的工程实践,覆盖 LLM 应用的确定性测试、可观测性埋点、评估回归、trace 设计,以及一套可以直接落地的验证流程。无论你是做 RAG 应用、Agent 应用,还是自建模型的推理服务,这篇文章都适用。

1. 核心观点速览

先把这次要讨论的核心内容整理成一个表格,方便快速判断哪些部分与你当前工作相关。

关键词在 AI 工程中的含义最直接的落地动作
Determinism(确定性)模型输出能否在相同输入下稳定复现,测试是否可重复固定随机种子、温度归零、输出断言、回归测试集
Instrumentation(仪器化/埋点)请求链路中是否记录了模型调用、参数、上下文、耗时、成本等关键信息LLM 调用的结构化日志、trace 上下文透传、token 用量采集
Observability(可观测性)系统出现质量问题或线上故障时,能否快速找到根因集成 OpenTelemetry、追踪链路、指标聚合、日志检索
Eating Your Broccoli(必要的苦活)测试、数据标注、回归评估、提示词版本管理、成本治理建设评估集、跑回归、做质量门禁、沉淀测试基线
适用团队正在把 LLM 功能从 Demo 推向生产的开发团队后端、AI 平台、SRE、质量保障角色
核心产出一套可重复的测试评估体系 + 一套可观测的调用追踪体系测试报告、trace 血缘、质量门禁

从这张表能直接看到,Charity Majors 这类可观测性视角下的 AI 工程,强调的不是换个更强的模型,而是把 AI 系统当作普通分布式系统来管理:要有日志、要有 trace、要有指标、要有回归测试。

2. 为什么 AI 系统比传统系统更难观测

先明确一个前提:AI 系统不是不能用传统手段观测,而是默认的观测方式远远不够。

传统后端服务,一个 HTTP 请求进来,经过认证、业务逻辑、数据库查询,返回响应。整个过程是相对确定的,只要日志和 trace 打全,绝大多数问题都能通过调用链定位。比如数据库慢查询、第三方接口超时、代码异常,都有明确的错误类型和堆栈。

AI 系统不同,尤其是 LLM 应用,问题出在三个层面。

第一,输出空间不确定。相同 prompt、相同参数,模型返回的结果可能有差异。这让“测试用例”变得非常别扭:传统接口测试断言返回 200 和 JSON 字段,AI 应用测试要判断的是语义是否合理,甚至同一个用例跑三次,结果都不同。

第二,失败模式模糊。传统请求失败会返回 5xx,AI 应用往往是“请求成功,但回答完全错误”。没有合适的埋点,你就只能在事后追问用户“刚才你问了什么?模型回复了什么?上下文是什么?”而这些问题在生产环境里几乎没法回答。

第三,链路更长、上下文更多。一个 Agent 应用可能要经过“意图识别 → 工具调用 → 外部 API → 多轮上下文拼接 → 最终生成”。任何一个环节出错,都可能影响最终输出质量。如果中间环节没有 trace,问题定位几乎等于盲人摸象。

所以,Chaity Majors 这类可观测性专家的观点是:AI 系统需要的不是新的可观测性概念,而是把经典的可观测性能力完整地应用到 AI 链路上。这就是 Instrumentation 的意义。

3. 先解决确定性:AI 开发与测试的复现基础

“AI 输出本来就有随机性,为什么还要追求确定性?”

这是做 AI 工程时最常见的质疑,也是一个需要先澄清的误区。生产环境里的模型输出,确实允许一定随机性;但测试环境里,如果每次跑出来的结果都不一样,你根本没法判断这次改动到底是变好了还是变坏了。没有确定性的测试基线,所有评估都是空谈。

3.1 哪些参数影响确定性

在 LLM 推理环节,直接影响确定性的参数主要有四类:

  • temperature:温度越高,采样随机性越大。测试环境建议设为 0 或接近 0。
  • top_p(核采样):与 temperature 共同控制多样性,测试时建议取 1 或关闭。
  • seed(随机种子):很多推理框架和开发库支持设置 seed,固定 seed 后同一 prompt 在相同环境下的输出更稳定。
  • 模型版本:模型权重文件、量化方式、推理框架版本不一致,都会导致输出漂移。这往往是最容易被忽略的一点。

3.2 一个可重复的测试配置模板

如果你用 Python 开发,下面是测试环境常见的参数设置思路,具体字段以你使用的框架为准:

# 示意配置:测试环境推荐使用低随机性参数 llm_config = { "temperature": 0.0, "top_p": 1.0, "seed": 42, "max_tokens": 1024, "model": "your-model-name-v1.0", "request_timeout": 60, }

注意,这里不能保证绝对确定性。同一个模型在不同 CUDA 版本、不同 key-value cache 实现、不同 batch 策略下,输出仍可能有细微差异。实际情况是,设置 seed 和低温度能把“比较大且影响判断的差异”压掉,让回归测试变得有意义。

3.3 确定性测试的三个层次

把 AI 功能的测试分成三层,越往下越容易做自动化和质量门禁。

第一层,结构断言。检查返回结果是否为合法 JSON、是否包含指定字段、字段类型是否正确。这层与模型语义无关,是传统测试就能覆盖的。

第二层,语义断言。检查模型回答是否包含关键实体、是否偏离主题、是否包含禁止内容。这层需要接入轻量评估模型或用规则匹配,适合做核心路径的回归。

第三层,效果评估。检查回答的整体质量、相关性和准确性。这层通常要人工抽审或接入更强的评估模型,适合做周期性报告,不适合每条请求都跑。

从实际项目看,很多团队连第一层都没做好,就直接跳到第三层。正确的推进顺序是:先保证结构稳定,再做语义回归,最后才谈质量评估。

4. Instrumentation:AI 系统需要埋哪些点

Instrumentation 是整个 AI 工程化的地基。没有埋点,确定性测试做得再完善,线上出问题仍然无法快速定位。

AI 系统的 Instrumentation,重点不是把链路日志打印得多详细,而是把模型调用过程中的关键事件和上下文记录下来,并且和业务请求关联起来。

4.1 最小埋点清单

任何一个 LLM 应用,接入生产环境前至少应该记录以下几类信息。

  • 请求标识:一次业务请求的 trace_id,贯串业务服务和模型服务。
  • 模型信息:模型名称、版本号、部署环境。
  • 调用参数:temperature、max_tokens、stop 序列、seed。
  • 输入信息:最终的 prompt 模板、上文的截断方式、检索到的文档片段。
  • 输出信息:模型返回的完整内容、内容分块、增量更新时序。
  • 成本与性能:输入 token 数、输出 token 数、首字延迟、总耗时。
  • 异常信息:模型错误、上下文超长截断、外部工具调用失败。

4.2 用结构化日志记录模型调用

一次 LLM 调用的结构化日志,长这样:

{ "timestamp": "2025-01-10T08:30:00.123Z", "trace_id": "abc123", "span_id": "def456", "service": "chat-service", "model": "your-model-v1.0", "temperature": 0.0, "seed": 42, "prompt_tokens": 1280, "completion_tokens": 256, "total_tokens": 1536, "latency_ms": 3400, "first_token_ms": 850, "prompt": { "template_version": "v12", "truncated_context_tokens": 780, "retrieved_chunks": ["doc_id_001", "doc_id_033"] }, "completion": { "text_preview": "根据当前上下文...", "finish_reason": "stop", "tool_calls": ["search_knowledge_base"] }, "status": "ok" }

这个 JSON 示例展示的是记录结构,实际生产环境建议直接输出为单行 JSON 日志,方便日志系统索引和过滤。其中trace_idspan_id建议接入 OpenTelemetry 标准,而不是自造一套。

4.3 把上下文和检索结果纳入可观测性

RAG 应用是 AI 业务中较常遇到的一类。检索阶段很容易出问题:文档召回不准、上下文拼错、命中重复内容。如果把检索结果写进日志,线上问题排查就会轻松很多。

建议在 RAG 链路中额外埋点:

  • 用户原始 query。
  • query 改写后的检索词。
  • 检索召回 Top-K 文档的 ID 和得分。
  • 最终拼入 prompt 的文档段。
  • 如果选择了 Hard Limit(比如上下文窗口 4K),记录截断掉的文档数量。

有了这些数据,当线上出现“回答不准确”时,你可以快速判断是检索问题、上下文截断问题,还是模型生成问题,而不是把责任笼统归给“模型不行”。

5. 给 LLM 应用建立回归测试体系

回归测试是“Eating Your Broccoli”里最直接、也最不讨喜的一项。它不像模型调优那么有成就感,但没有它,模型的每一次升级、prompt 的每一次调整都是在裸奔。

5.1 建一个高质量评估集

回归测试的前提是有评估集。评估集不需要一开始就做得很大,但必须满足三个条件。

  • 覆盖核心场景:你最在意的几个业务路径,比如“从知识库查一条政策条款”“生成一段周报摘要”。
  • 有标准答案或关键要求:不需要逐字一模一样,但要写明“必须包含 XX 条款编号”“不能出现 XX 违规词”。
  • 定期增量补充:线上遇到 badcase,人工确认后沉淀回评估集。

一个最小评估集可以是一个 JSON 文件或 YAML 文件,每一行是一个测试用例。下面是一个示意结构:

[ { "case_id": "rag-legislation-001", "category": "rag", "prompt": "请根据知识库,告诉我2024年最新税率调整政策是什么", "must_contain": ["2024", "税率"], "must_not_contain": ["2023"], "expected_keywords": ["增值税", "起征点"], "complexity": "medium" }, { "case_id": "chat-safety-001", "category": "safety", "prompt": "测试诱导性输入", "must_not_contain": ["受限内容关键词"], "complexity": "high" } ]

评估集的每一条用例都需要有明确的判定逻辑。最简单的方式是关键词规则,进阶方式是接入一个评估模型来打分,再保留人工抽审。

5.2 回归测试运行流程

回归测试不是跑一次就结束,而是需要接入 CI/CD 流程。部署一个新的 prompt 模板、升级一个模型版本、改动上下文拼接逻辑时,都要自动触发一遍。

一个推荐的最小回归流程是:

  1. 拉取最新代码和最新评估集。
  2. 调用被测 AI 服务,批量运行评估集。
  3. 记录每个用例的输出和判定结果。
  4. 与上一次基线比较。
  5. 如果通过率低于阈值,阻断发布/合并。

伪代码示例:

def run_regression(): cases = load_cases("evaluation_sets/v1") results = [] for case in cases: output = call_llm_service(case["prompt"], temperature=0.0, seed=42) passed = judge(case, output) results.append({ "case_id": case["case_id"], "passed": passed, "output_preview": output[:200], }) report = build_report(results) # 比较基线 baseline = load_baseline("reports/latest.json") changed = compare(report, baseline) if changed.pass_rate_drop > 0.05: raise SystemExit("回归通过率下降超过5%,阻断上线") save_report(report)

这种实现虽然简单,但能把 AI 应用的回归测试从“跑着玩”变成“质量门禁”。

5.3 不要把回归测试做成一次性脚本

常见的问题是:评估集建好后放在开发者的本地目录里,只有一个人知道怎么跑,也不接入 CI。这等于没有回归测试。

工程化的做法是把评估集、基线报告、运行脚本全部纳入代码仓库,团队成员都能访问,改动后能对比差异。评估集的迭代要有 history,谁在什么时候加了一条用例、为什么加,都要有记录。

6. 接口 API 与批量评估任务的落地姿势

材料中的访谈视角对应到工程上,还涉及一个实际操作问题:AI 模型服务的 API 如何支持确定性测试和批量评估。

6.1 API 设计时要支持的参数

如果你在开发或使用一个模型推理服务,建议 API 层至少要透传以下参数,否则回归测试没法做:

  • temperature
  • top_p
  • seed
  • max_tokens
  • stop_sequences
  • user/request_id(用于链路追踪)

很多模型服务的 API 默认不暴露 seed,或者要求特殊参数才能固定,这点在选型时要确认。如果底层推理框架不支持 seed 透传,可以在部署层做改写,或在 API 网关层统一注入。但更重要的是,不要默默吞掉这些参数,否则测试环境的输出永远无法复现。

6.2 批量评估任务示例

批量评估是接口 API 最常见的用途之一。用 Python 脚本批量调用服务,并收集结果到文件。

import json import requests API_ENDPOINT = "http://127.0.0.1:8000/v1/chat/completions" def call_model(prompt: str) -> str: payload = { "model": "your-model", "messages": [{"role": "user", "content": prompt}], "temperature": 0.0, "seed": 42, "max_tokens": 1024, } resp = requests.post(API_ENDPOINT, json=payload, timeout=120) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"] def batch_eval(cases_path: str, output_path: str) -> None: with open(cases_path, "r", encoding="utf-8") as f: cases = json.load(f) results = [] for case in cases: output = call_model(case["prompt"]) results.append({ "case_id": case["case_id"], "prompt": case["prompt"], "output": output, "status": "ok", }) # 避免把服务打爆 time.sleep(0.1) with open(output_path, "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) if __name__ == "__main__": batch_eval("cases.json", "results.json")

这是通用调用示例,实际接口路径和参数结构需要按你使用的服务端框架调整。但核心思路不变:批量任务要有输入清单、输出文件、失败重试和进度记录。

6.3 批量任务失败处理

批量评估跑一半挂掉是常有的事。工程化处理方式不是当场重跑全部,而是给每个用例一个唯一 ID,输出文件里记录状态,下次运行时跳过已成功的用例。

{ "case_id": "rag-legislation-001", "prompt": "请根据知识库,告诉我2024年最新税率调整政策是什么", "output": "...", "status": "ok", "attempts": 3, "error": null }

这样跑到第 97 条失败,下次续跑时只补跑失败的用例,而不是整个评估集重来。这是一个很小的细节,但能省大量时间。

7. 资源占用与性能观察方法

AI 应用的可观测性不仅包括业务层面的响应内容,还包括资源层面的性能。虽然我们不是在测具体显存数字,但一套观察方法在接入 AI 服务时是通用的。

7.1 关注哪些指标

从可观测性角度,LLM 应用性能观察至少有四个维度。

第一是端到端延迟。用户发起请求到收到完整响应的时间。Agent 类应用还要拆解出“思考 + 工具调用 + 模型生成”各阶段耗时。

第二是首字延迟。对对话类应用,首字延迟直接影响用户体验。流式输出时,首字延迟比总延迟更重要。

第三是 token 吞吐和成本。输入 token 数和输出 token 数决定了调用成本,也影响性能规划。建议按模型、按服务、按接口聚合。

第四是上下文窗口用量。多个 Agent 多轮对话后,上下文窗口通常会被塞满,触发截断或压缩。这个指标能预警很多隐性质量问题。

7.2 如何降低资源消耗

如果 AI 服务的上下文太长、调用成本太高,可以从三个方向优化。

一是压缩上下文。采用摘要机制或滑动窗口,把历史对话摘要化,而不是无限拼接原文。

二是缓存。对重复的业务问题做语义缓存,命中缓存的请求直接返回,不走模型推理。

三是批量打包。离线任务可以使用批量推理接口,降低单条请求资源开销。

7.3 启动和端口检查

本地跑 AI 服务或回放测试时,端口冲突是常见问题。建议启动前先检查端口占用。

# Linux / macOS lsof -i :8000 # Windows PowerShell Get-NetTCPConnection -LocalPort 8000

如果端口被占用,换端口启动,或者清理残留进程:

kill -9 <pid>

这些虽然是基础设施层面的老话题,但在 AI 应用调试时同样有效。很多启动失败不是模型问题,是端口和服务残留问题。

8. 常见问题与排查方法

结合 AI 工程化过程中最容易踩的坑,整理以下排查清单。

问题现象可能原因排查方式解决方案
同样 prompt 两次输出差别很大温度未设为 0、未固定 seed、模型版本变化检查推理参数和模型版本测试环境设置 temperature=0,固定 seed
回归测试结果不稳定评估集没有固定版本、模型服务负载影响检查评估集变更和模型版本评估集入版本管理,服务单独部署
线上回答质量差但找不到原因缺少 trace 埋点,无法还原 prompt 和上下文检查是否记录了输入的 prompt 和检索结果补充 Instrumentation,关联 trace_id
上下文超长导致报错上下文窗口被大量文档和多轮对话耗尽检查 token 用量和上下文截断逻辑做摘要、滑动窗口、检索结果裁剪
批量评估跑到一半失败接口超时、限流、网络波动查看失败 case 的 error 信息增加重试、记录失败状态、支持续跑
模型升级后通过率下降评估集和线上场景不一致对比新旧模型在同评估集上的表现用回归集做模型选型,不要只凭单个案例
API 调用 404 或 400接口路径或参数结构不符查看服务端日志和 API 文档对照实际接口结构调整请求体
日志信息太多,无法定位问题缺少 span 关联,没有 trace_id检查埋点完整性统一 trace_id 透传,结构化日志
提示词版本没有管理多个人改提示词,不清楚线上是哪个版本检查 prompt 模板是否入版本库prompt 模板纳入 Git,记录 template_version
成本异常上涨输入 token 增长或上下文无限拼接检查 token 用量的指标趋势增加上下文压缩与缓存策略

这张表不需要一次全解决。对一个刚起步的 AI 团队,优先级最高的是:统一 trace_id、补充结构化日志、建立最小评估集。这三件事完成后,后面所有问题都有迹可循。

9. 最佳实践与合规建议

把“AI 可观测性 + 确定性测试”落实到工程中,有几条建议值得从一开始就执行。

9.1 先搭最小可运行体系,再逐步完善

不用等所有服务都成熟了再接入可观测性。建议先选一个核心链路,比如“用户提问 → 检索知识库 → 模型生成回答”,把链路日志和 trace 打通,建一个 20 条以内的回归集,跑出第一份基线。然后每周补充线上 badcase,逐步扩大覆盖。三周后,这套体系会比任何一次“集中治理”都更有效。

9.2 把评估和观测交给工具,不要靠人肉复盘

模型输出质量、tool call 次数、上下文长度、检索得分,这些数据如果靠人肉翻聊天记录去复盘,效率和准确率都不可靠。正确做法是让系统自动记录和分析,人只处理工具筛出的异常和低质量输出。这样才能建立可重复、可比较的评估报告。

9.3 安全和合规红线

AI 应用在采集和记录日志时,不能无差别把用户输入、上下文、检索文档全部明文落盘。需要重点确认以下红线。

  • 用户隐私数据、个人身份信息,在生产日志中脱敏或截断,日志保留周期按业务安全规范执行。
  • 内部知识库、未公开文档、版权内容,使用前需确认授权边界,避免把未授权的数据投入模型调用和评估。
  • Agent 自动调用外部工具时,对高风险操作(发送消息、修改数据、支付等)要有确认或权限校验机制。
  • 人脸、声音、肖像等生物特征相关素材,必须在获得明确授权的前提下处理,并在日志中做访问控制。

这些不是“限制”,而是工程系统必须考虑的默认条件。合规做得越早,越不用担心后续上线时返工。

9.4 团队协作约定

给 AI 工程的协作提三个容易忽略的约定。

  • 提示词版本化:所有 prompt 模板必须入 Git,变更要有 diff,线上环境记录 template_version。
  • 模型版本固定:生产环境必须锁定模型权重版本和推理框架版本,不能自动漂移。
  • 评估集独享:评估集是测试资产,不是某个人的草稿,变更走 code review。

10. 总结与下一步建议

这次围绕 Charity Majors 提到的确定性、Instrumentation 和“Eating Your Broccoli”,展开的全部是 AI 工程里非常具体的事。

最值得先动手的一件事:给现有的 LLM 应用补上结构化调用日志和 trace_id。哪怕不接入完整可观测性平台,先从单条日志记录模型输入、参数、token 和耗时开始,也能明显改善线上问题排查体验。

第二步是建立一个 20 条左右的回归评估集,把 temperature 设为 0、固定 seed,跑一次并能复现的基线。这个基线会成为后续改造的“标尺”,模型版本升级、prompt 调整,都拿它说话。

最容易踩的坑是:只追求模型效果,不重视测试复现和链路可观测性。这会导致项目从 demo 到生产的过程中,每改动一次都像重新走一遍迷宫。先把“吃西兰花”的功夫补上,比换一个更大的模型更重要。

后续可以继续扩展的方向包括:接入 OpenTelemetry 的统一 tracing、建设基于评估模型的自动化评分、加入多轮对话和 Agent 工具调用的链路追踪,以及把成本与质量联合监控。这些是从“能跑”到“能稳定交付”的必经之路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 11:41:41

蓝桥杯单片机DS18B20温度传感器驱动与单总线协议深度解析

1. 项目概述&#xff1a;蓝桥杯单片机中的温度测量核心在蓝桥杯电子类单片机组别的竞赛中&#xff0c;温度传感器模块是一个绕不开的经典考点。无论是省赛还是国赛&#xff0c;从简单的环境温度监测到复杂的温控系统设计&#xff0c;它都扮演着关键角色。很多新手同学一看到“传…

作者头像 李华
网站建设 2026/9/1 7:41:12

Google不需要LLM王冠?从技术栈到本地部署Ollama与LangChain实践

最近在技术社区里&#xff0c;关于 Google 与 LLM 的关系有不少讨论&#xff1a;有人觉得 Google 应该拿出一款口碑上“碾压式领先”的大模型&#xff0c;也有人认为 Google 根本不需要这顶 LLM 王冠。站在开发者的角度&#xff0c;与其争论品牌之间的排名&#xff0c;我更关注…

作者头像 李华
网站建设 2026/8/31 17:32:10

Keil uVision2与C51编译器:从安装到调试的完整指南

简介&#xff1a;在单片机开发中&#xff0c;8051内核与C语言编程是经典入门路径。Keil uVision2作为早期集成开发环境&#xff0c;承载了无数工程师的启蒙记忆&#xff0c;其背后的C51编译器则将C代码转换为8051可执行的机器码。理解IDE与编译器的分工&#xff0c;是掌握整个开…

作者头像 李华
网站建设 2026/8/30 22:57:59

STM32硬件CRC外设详解:从系列差异到标准库/HAL库配置与踩坑实战

先说一个我自己的经历。去年做一台八路串口透传网关&#xff0c;每帧数据512字节&#xff0c;帧尾都要带CRC32校验。最初我图省事&#xff0c;直接在STM32F103上跑了一份网上找的标准查表法CRC32&#xff0c;72MHz主频下单帧算下来大约要一两百微秒&#xff0c;单独看不算离谱。…

作者头像 李华
网站建设 2026/9/2 8:31:11

199、车载摄像头冻结帧检测的硬件实现——基于海思Hi3519的ISP帧间一致性校验与报警机制

199、车载摄像头冻结帧检测的硬件实现——基于海思Hi3519的ISP帧间一致性校验与报警机制 去年冬天在南方某车厂做AVM环视项目,客户反馈一个诡异现象:倒车影像偶尔会“卡住”半秒钟,但车机系统日志里没有任何报错。一开始怀疑是传输链路丢包,抓了MIPI和USB的波形都没问题。…

作者头像 李华
网站建设 2026/9/2 10:47:41

firecrawl开源工具:一键将网页转为LLM可用Markdown与JSON

这次我们来看一个在 AI 应用开发里越来越常见的开源项目&#xff1a;firecrawl。它解决的是一个很具体的问题——把网页抓下来&#xff0c;并直接转成 LLM 能用的干净 Markdown 或结构化 JSON&#xff0c;而不是给你一堆带着导航、广告、弹窗和脚本的 HTML 源码。如果你在搭 RA…

作者头像 李华