
这次我们来看一个偏研究向、但工程含量很高的话题Long-term Measurements: Towards a Longitudinal Understanding of Human-AI Interactions。直白地说这是一套“长期测量人机交互”的研究框架和工程方案核心目标是持续记录用户与 AI 工具之间的每一次交互用几周、几个月甚至跨年度的数据回答一个常见但很难回答的问题用户到底有没有从 AI 工具中获得稳定价值。这个话题和传统评测方法最大的区别在于加入了时间维度。传统做法是发问卷、做用户访谈、安排固定任务看完成时间这类方法能抓住第一印象但抓不住长期变化。长期测量要关注的是使用频率如何波动、提示词怎么演化、模型更新前后行为是否跳变、用户是否出现过度依赖或技能退化。这些数据一旦积累起来对 AI 产品评测、LLM 应用迭代和用户研究都非常有价值。这篇文章不完全是对某个开源仓库的使用教程更多是把研究主题落成一套可执行的工程方案。我会给出测量指标体系、事件数据建模、ClickHouse 存储设计、纵向分析 SQL、批量回填任务以及隐私合规建议。如果你正在做 AI 产品评测、LLM 应用用户研究、RAG 助手的数据分析或者想从零搭建一个交互日志平台可以直接照着这套框架搭建一个最小可运行闭环。1. 核心方案速览项目类型人机交互研究方法 数据工程方案研究对象AI 工具对话机器人、编程助手、RAG 系统、智能客服与用户的长期交互过程关键技术事件埋点、遥测上报、批量 ETL、ClickHouse 存储、纵向统计与趋势分析主要功能交互日志采集、行为指标计算、长期趋势分析、模型版本归因、用户分层推荐部署资源服务端 4 核 CPU / 16G 内存起步存储按事件量扩展估算方法见第 9 节显存 / GPU 需求非必须仅当分析链路中需要本地跑大模型做自动标注时才需要 GPU支持平台Web 前端、浏览器插件、IDE 插件、桌面客户端、移动端取决于埋点 SDK 的适配范围启动方式事件接入服务 分析数据库 定时分析任务 可视化看板是否支持 API支持提供事件上报 REST API 和指标查询接口是否支持批量任务支持包括历史日志回填、日聚合、留存计算、趋势检验适合场景AI 产品评测、LLM 工具用户研究、编程助手行为分析、RAG 问答质量监测需要先说明的是这个标题本身是一个研究方向不是一个可以 clone 下来直接启动的开源仓库。文章里给出的所有架构和数据 schema都是围绕该主题设计的一套通用参考实现读者可以根据自己的业务场景替换事件字段、存储组件和分析逻辑。2. 为什么需要长期测量短期评估的三个盲区2.1 第一印象掩盖真实使用用户第一次使用 AI 工具时表现往往是最好的。新功能带来的新鲜感、对模型能力的期待、测试任务的简单性都会让短期评估数据偏高。一个典型的例子是 AI 编程助手新手在演示场景里看到自动补全觉得很惊艳但真实项目里上下文复杂、代码库庞大一周后的实际采纳率可能明显下降。如果只在用户接触工具的第一周做测量得到的是“新鲜感曲线”而不是“稳定使用曲线”。长期测量通过记录连续使用窗口可以区分“用户觉得工具新鲜”和“用户认为工具真正有用”这两种完全不同的状态。2.2 单点快照无法区分新奇效应与稳定习惯人机交互研究中有一个常见现象叫新奇效应用户在刚开始接触新系统时参与度和绩效都会异常升高一段时间后回落到真实水平。一次性的实验研究很难排除这个效应因为它只截取了一个时间截面。长期测量通过时间序列数据可以观察指标从上升到回落、再到平稳的完整过程。比如某个功能上线后第一周 DAU 很高第二周回落第四周开始重新上升。前者是好奇后者才说明用户找到了稳定的使用价值。没有长期数据这两者根本无法区分。2.3 模型迭代效果缺少时间纵深证据AI 工具的模型版本升级非常频繁每次升级都可能影响用户行为。短期评估只能回答“升级前后那几天指标有没有变化”但无法回答“这种变化是临时的还是可持续的”。长期测量配合版本发布记录可以做前后对比、中断时间序列分析甚至评估用户行为对新版本是否出现适应期。比如新模型输出的回答更长第一天用户可能不适应导致采纳率下降一周后用户学会了利用更长答案的行为模式采纳率回升并超过旧版本。只有时间维度的数据能清晰呈现这样完整的演变过程。3. 适用场景与使用边界3.1 适合谁AI 产品经理和数据分析师需要对 AI 功能做持续效果评估而不是只看上线一周的数据。LLM 应用开发团队想知道模型更新、提示词模板调整、上下文长度改动对用户行为的影响。HCI 研究方向的学生和研究员需要收集真实交互日志验证关于人机协作、信任、依赖的假设。企业级 AI 平台团队需要建立统一的行为指标口径输出周报、月报和用户分层。3.2 不适合什么一次性可用性测试如果想快速知道按钮好不好找、流程是否顺畅直接做任务测试加访谈更高效不需要搭建一套长期测量系统。小样本个案研究如果只有几个用户做深度访谈比堆积日志数据更有价值长期测量在大样本下才有统计意义。高频细粒度语义分析日志只能告诉你用户提交了什么、采纳了什么要给生成内容做质量评分通常还需要额外的模型标注链路。3.3 权益与合规红线长期测量必然涉及用户行为数据这是敏感数据。方案设计时必须提前考虑合规边界用户需要知情同意明确告知采集范围和用途用户 ID 必须做不可逆哈希处理日志中不落明文标识遵循数据最小化原则只采集回答研究问题所必需的字段敏感内容如代码全文、聊天完整文本要采样采集或脱敏处理数据加密存储内部访问权限最小化按研究周期设定保留期限到期自动销毁。这部分不是可选项。没有合规设计的长期测量系统数据积累越多风险越大。4. 测量指标体系设计长期测量的第一步是定义指标。指标不是越多越好而是要先回答研究问题再反推需要哪些字段。这里给出一套分层指标框架按参与度、交互行为、产出效果、长期变化四个维度组织。4.1 参与度指标指标名定义说明DAU / WAU / MAU日 / 周 / 月活跃用户数判断整体使用规模人均会话数平均每个活跃用户每天发起的会话数量反映使用密度连续使用天数用户连续活跃的天数衡量用户粘性会话间隔分布相邻两次会话之间的时间间隔判断使用节奏功能覆盖率使用过核心功能的用户占比评估功能引导效果流程完成率从打开工具到完成一次有效交互的用户比例反映上手门槛4.2 交互行为指标指标名定义说明提问次数每个会话中提交提示词的次数衡量任务复杂度和依赖度提示词长度平均字符数或 token 数用户是否学会提供更多上下文建议采纳率采纳建议数 / 收到建议数衡量 AI 输出是否符合预期采纳后修改率采纳后继续编辑的比例反映输出质量的接近程度重新生成率同一任务重新生成的次数反映首次输出命中率会话放弃率没有完成动作的会话占比判断交互失败情况上下文引用率主动粘贴代码、文档到对话框的会话占比RAG 场景下很有参考价值4.3 产出效果指标指标名定义说明任务完成事件用户明确标记完成或关闭成功任务需要客户端埋点定义明确的成功信号任务耗时从首个提示词到完成事件的时长衡量 AI 对工作效率的影响输出质量评分人工抽样评分或模型自动评分建议对样本做人工核对返工率完成任务后短时间内再次修改的比例判断一次性完成质量生成文本修正量采纳后用户修改的编辑距离可以量化“AI 输出离可用还差多少”4.4 长期变化指标指标名定义说明周同比 / 月环比指标相对上一周期变化率快速发现异常波动新用户首周曲线新用户注册后 7 天的行为变化评估新手引导效果留存队列按注册周分组观察 D7/D30 留存衡量长期价值AI 依赖指数在无 AI 辅助的对照测试中完成任务的能力变化监测技能退化风险疲劳信号交互频率下降、负向反馈增多、会话时长缩短判断用户是否流失模型切换频率用户在不同模型或工具之间切换的次数反映产品竞争力和迁移成本指标定义好之后每个指标都必须对应到具体的事件字段和计算口径。比如“采纳率”的分子是哪个事件、分母是哪个事件必须在数据集市层统一。5. 技术架构与数据采集方案5.1 整体架构长期测量系统在架构上可以拆成五层客户端采集层Web SDK、浏览器插件、IDE 插件、桌面客户端负责在用户交互时生成事件。传输接入层统一的上报网关接收客户端事件做格式校验、限流和鉴权。消息缓冲层Kafka、Redpanda 或 Redis Streams用于削峰填谷防止突发流量打垮存储。存储计算层ClickHouse 或 PostgreSQL 存储事件明细定时任务做聚合计算。分析与可视化层Grafana、Superset 或自研看板输出留存、趋势、分层报告。对于中小规模场景可以省略消息队列客户端直接批量上报到网关网关写入数据库。当每日事件量超过百万级时再引入 Kafka 做缓冲。5.2 事件模型设计事件是整个系统的核心数据单元。建议所有事件统一使用以下结构保证兼容性和可扩展性{ event_id: a3f8cc21-8d12-4a68-9b2e-7f3c8a91b1d2, session_id: session_20250115_093211_7f34, user_hash: u_9f2c81ab4e67, event_type: prompt_submit, event_version: 1, at: 2025-01-15T09:23:12.00008:00, client: { app: vscode_plugin, version: 1.2.0, platform: macos, locale: zh-CN }, payload: { prompt_length_chars: 234, prompt_tokens: 118, context_type: code_file, context_tokens: 1280, target_language: python } }关键设计原则event_id全局唯一便于去重和排查session_id用来串联一次任务中的多个事件user_hash必须是脱敏后的匿名标识不能在事件里携带用户名、邮箱等明文event_type统一为小写字符串按业务定义例如prompt_submit、completion_returned、completion_accept、completion_rejectat统一使用带时区的 ISO 8601 格式存储层再统一转换为 UTCpayload是业务字段容器新增采集项不需要改主结构只需扩展 payload。5.3 埋点要点不要在 UI 线程同步发送事件要放到后台队列异步批量上报网络失败时事件写入本地缓存下次启动重试发送每条事件尽量控制体积大文本字段要采样或截断不要采集密码、API Key、私人文件内容客户端 SDK 要提供开关允许用户关闭遥测。6. 数据存储与处理流程6.1 存储选型事件日志属于写多读少、按时间查询的数据适合使用列式存储。推荐优先考虑 ClickHouse原因是对高吞吐写入、时间分区和聚合查询支持好。中小规模也可以用 PostgreSQL但要注意事件表需要按时间做分区避免单表过大。6.2 ClickHouse 示例表CREATE TABLE interaction_events ( event_id String, session_id String, user_hash String, event_type LowCardinality(String), event_version UInt8, payload_json String, client_app LowCardinality(String), client_version String, platform LowCardinality(String), at DateTime64(3, UTC) ) ENGINE MergeTree() PARTITION BY toYYYYMM(at) ORDER BY (user_hash, at);这里把user_hash放在排序键前面是因为长期分析经常要按用户分组看行为轨迹。如果业务更偏重时间范围扫描可以改成ORDER BY (at, user_hash)需要按实际查询模式权衡。6.3 批量 ETL 与回填历史日志回填是长期测量系统最常见的批量任务。从本地 JSON 文件导入的通用脚本示例如下import json import glob from clickhouse_driver import Client client Client(host127.0.0.1, databaseanalytics) def process_file(path: str): with open(path, r, encodingutf-8) as f: events json.load(f) rows [( e[event_id], e[session_id], e[user_hash], e[event_type], e.get(event_version, 1), json.dumps(e.get(payload, {}), ensure_asciiFalse), e.get(client, {}).get(app, ), e.get(client, {}).get(version, ), e.get(client, {}).get(platform, ), e[at] ) for e in events] client.execute( INSERT INTO interaction_events (event_id, session_id, user_hash, event_type, event_version, payload_json, client_app, client_version, platform, at) VALUES, rows ) for path in sorted(glob.glob(./logs/**/*.json, recursiveTrue)): try: process_file(path) print(fprocessed {path}) except Exception as exc: print(ffailed {path}: {exc})这个脚本在单文件解析失败时不会中断整个回填流程适合作为第一版批量任务。正式环境建议加上分批提交和失败重试队列。7. 纵向数据分析方法数据积累起来之后分析才是真正产生价值的部分。纵向分析的目标是发现“随时间变化的规律”常用的方法可以归为下面三类。7.1 趋势分析先计算每日核心指标观察整体走势。一个通用查询是把活跃用户数、提示词提交数和平均生成 token 数按天聚合出来SELECT toDate(at) AS day, countDistinct(user_hash) AS dau, countIf(event_type prompt_submit) AS prompt_count, avgIf( JSONExtractInt(payload_json, completion_tokens), event_type completion_returned ) AS avg_completion_tokens FROM interaction_events WHERE at now() - toIntervalDay(90) GROUP BY day ORDER BY day;趋势数据不要只看绝对大小要看变化方向和波动幅度。可以用移动平均平滑掉短期噪声再观察整体上升或下降趋势。如果希望做统计意义上的显著性判断可以考虑 Mann-Kendall 趋势检验它不要求数据服从正态分布适合处理行为指标。7.2 留存与生存分析停留存是长期测量最核心的内容。按注册周给用户分组分别计算第一周、第二周、第四周的活跃比例可以得到一条留存衰减曲线。进一步可以做生存分析计算“用户在系统内持续活跃的中位时间”定位流失高发节点。在分析过程中要注意区分“用户不用了”和“用户只是短期内工作模式变了”。配合用户访谈或小样本调研可以给数据变化提供解释。7.3 版本变更归因当模型版本升级时可以用中断时间序列分析评估升级前后的指标变化。基本思路是以上线时间为分割点分别拟合前后两段趋势比较水平变化和斜率变化。这个方法能部分排除自然波动的干扰。如果模型版本同时涉及多个用户群体还可以设计分组对比实验一部分用户看到新版本另一部分维持旧版本观察行为差异。不过要注意AI 产品行为数据受季节、工作任务、产品推广等多重因素影响分析结论需要谨慎表述。8. 接口 API 与批量任务8.1 事件上报 API事件上报接口建议设计成批量提交的形式。一次请求携带多条事件减少网络往返降低网关压力。curl -X POST http://127.0.0.1:8380/api/v1/events \ -H Content-Type: application/json \ -d events.json请求体示例{ app_id: ai_copilot, client_id: plugin_1.2.0, events: [ { event_id: a3f8cc21-8d12-4a68-9b2e-7f3c8a91b1d2, session_id: session_20250115_093211_7f34, user_hash: u_9f2c81ab4e67, event_type: prompt_submit, event_version: 1, at: 2025-01-15T09:23:12.00008:00, payload: { prompt_length_chars: 234 } } ] }网关服务收到请求后先校验event_id是否重复再校验event_type是否在白名单内最后把事件写入消息队列或数据库返回201 Created。8.2 Python 批量上报脚本import requests def send_events(events: list, endpoint: str http://127.0.0.1:8380/api/v1/events): payload { app_id: ai_copilot, client_id: plugin_1.2.0, events: events } resp requests.post(endpoint, jsonpayload, timeout5) resp.raise_for_status() return resp.status_code if __name__ __main__: with open(mock_events.json, r, encodingutf-8) as f: event_list json.load(f) status send_events(event_list) print(status)如果客户端有大量历史本地日志可以参考第 6 节的回填脚本先把日志解析成统一事件结构再分批上传。8.3 批量分析任务批量任务是长期测量系统的主要消费方通常按每日 / 每周调度每日聚合任务计算 DAU、人均会话数、采纳率等核心指标每周留存任务按注册周分组计算 D7/D30 留存每月归因任务关联模型版本发布记录输出变更前后指标对比异常检测任务对核心指标做动态阈值判断触发告警。批量任务要记录执行状态、影响行数和耗时失败后支持断点重跑。建议用 Airflow、DolphinScheduler 或简单的 cron 加状态表来实现不要把所有逻辑塞进一个无限循环脚本里。9. 资源占用与性能观察9.1 吞吐量估算长期测量系统需要考虑的第一个问题是“我会积累多少数据”。可以用一个简单模型估算变量示例值总用户数1000人均日会话数10每会话事件数30日事件总量30 万单事件原始大小约 1 KB日原始数据量约 300 MB月度原始数据量约 9 GB单事件 1KB 是保守估算实际大小取决于 payload 里塞了多少字段。生产环境中需要拿真实 JSON 序列化后测量。9.2 性能观察指标运行期建议重点观察以下内容上报接口 QPS确认突发流量没有击穿网关消息队列积压量积压持续增长说明下游写入能力不足ClickHouse 写入吞吐和合并任务耗时看板查询响应时间长周期大范围查询容易超时批量任务执行时长避免任务还没跑完下一次调度又开始了。9.3 降低负载的手段相似事件合并成一条批量记录上报对明细数据进行分层采样比如大文本内容只保留 10% 样本按天分区并定期归档超过 180 天的明细数据到冷存储对高频查询指标做物化视图避免每次从明细全量聚合清理重复上报的事件event_id去重逻辑要放在写入链路最前面。10. 常见问题与排查方法问题现象可能原因排查方式解决方案客户端事件完全没有上报SDK 未初始化或上报开关被关闭检查客户端启动日志和 SDK 初始化代码确认初始化顺序核对配置开关部分事件丢失批量请求超时或本地缓存没重试查看网关接收日志和客户端缓存目录增加重试机制缩小批量大小事件乱序本地缓存重发导致旧事件晚到对比事件产生时间和入库时间增加顺序号写入时按顺序去重报表里出现 1970 年数据时间字段传了空值或时间戳单位错误检查客户端at字段格式统一使用 ISO 8601 并服务端兜底校验ClickHouse 查询越来越慢分区粒度过大或排序键不合理查看查询计划确认命中了哪些分区调整分区粒度优化排序键批量回填任务卡住单文件数据量大或下游写入阻塞查看任务日志、数据库写入延迟分批提交增加重试和断点续跑DAU 严重虚高用户被重复计算检查用户哈希字段是否稳定确认用户哈希算法和存储一致性隐私字段泄露到日志payload 结构设计包含了多余字段审核事件字段清单和日志输出移除非必要字段增加日志脱敏排查长期测量系统的问题关键是先看链路走到哪一步。标准方法是客户端日志确认事件生成 → 网关日志确认接收 → 数据库确认落表 → 聚合作业确认输出 → 看板确认展示。每一步都留下状态日志问题就能快速定位到某一层。11. 最佳实践与工程建议先小规模试运行。先接 50 个真实用户跑两周确认事件字段、上报链路、聚合 SQL 都没有问题再大规模铺开。事件结构要版本化。字段可以新增但不要轻易修改已有字段的语义。每个事件带event_version旧版本事件也能回溯兼容。指标口径集中管理。把“采纳率”“留存率”的计算逻辑收敛到统一的模型层不要在各处各写一套 SQL。保留一条最小可运行链路。即使后续加了 Kafka、复杂 ETL也要能回到“客户端直连数据库”的简单模式方便调试和兜底。批量任务必须可重跑。记录每次任务的输入输出版本任务失败后可以重新执行不产生重复数据。不要为了采集而采集。每个字段都要能对应到一个具体研究问题否则只会增加存储成本和合规压力。建立数据删除流程。用户提出删除申请时要有能力一键清除该用户相关的所有明细和派生数据。涉及人脸、声音、私人代码、对话内容时逐项确认授权。如果系统采集的是用户自己生成的内容必须在采集前充分告知并提供撤回渠道。发布研究报告时做好聚合和脱敏。任何可反推个体用户的指标都不应该输出到公开报告。12. 总结与下一步长期测量人机交互本质上是在建一套“AI 产品的时间显微镜”。它的核心价值不是看某一天指标有多高而是看指标如何随时间演变帮助产品团队和研究者从数据上回答信任、依赖、留存、技能变化这类深层问题。如果你准备从零开始建议从最简闭环跑起客户端埋点生成事件 → 上报到统一接口 → 写入 ClickHouse → 每日聚合看板。先把这一条链路跑通再逐步增加留存队列、版本归因、异常告警和自动化报告。最容易踩的坑反而不是技术而是事件字段定义不统一和隐私合规没提前设计。只要这两条线守住后续的数据积累和分析都会顺畅很多。