跳到主要内容

59 篇博文 含有标签「ux」

查看所有标签

P99 是产品决策,而非基建决策

· 阅读需 10 分钟
Tian Pan
Software Engineer

在几乎每一个发布 AI 功能的团队中,都会上演这样一种“仪式”:有人运行负载测试,看着 p99 延迟攀升并超过 2 秒,然后提交了一个工单:“让它快一点。”这个工单落到了基建(infra)团队手中。他们调整批处理大小(batch sizes),增加 GPU,争论调度器(scheduler),最终费尽心思将这个数字降到了 1.4 秒。每个人都点头认可。p99 被“解决”了。

整个过程都建立在一个错误的前提之上。这个前提认为延迟目标是系统的一个既定事实——是基建团队发现并为之优化的一个物理常数。事实并非如此。目标是一个选择,而且是一个产品层面的选择。什么才算“足够快”,完全取决于用户等待时界面的表现,而界面并不在基建团队的设计范围内。

聊天并非最佳界面:为什么你的智能体不应只是一个文本框

· 阅读需 9 分钟
Tian Pan
Software Engineer

有一个数据足以让人们停止“增加一个聊天机器人”的条件反射:在很大一部分 AI 功能中,大多数打开聊天窗口的用户从未发送过一条消息。据报道,大约有 60% 的用户在发送第一条消息前就放弃了,而相比之下,当同样的能力被封装在带有示例和一键启动点的设计好的空白状态(empty state)中时,用户的参与度要高得多。模型并没有失败。答案从未生成,因为问题从未被提出。用户打开一个空白框,看着闪烁的光标,然后离开了。

我们选择聊天界面是因为它是阻力最小的路径,而不是因为它就是正确的界面。当语言模型可以进行对话的那一刻,“与 AI 交流”就变成了“使用 AI”的代名词,每个产品团队都继承了同样的默认设置:一个文本框,一个发送按钮,以及一个模型会搞定剩下一切的承诺。对于大多数智能体(agent)实际承担的工作来说,这种默认设置其实是错误的。

聊天是一个不错的 输入原语 (input primitive)。但它是一个糟糕的 操作环境。这是两个不同的概念,将它们混为一谈会导致你在需要控制面板的地方只交付了一个闪烁的光标。

为什么你无法为智能体设置进度条

· 阅读需 11 分钟
Tian Pan
Software Engineer

你发布过的每一个进度条都建立在一个假设之上:你知道分母。上传一个 40 MB 的文件?分母就是 40 MB。安装 212 个包?分母就是 212。进度条是诚实的,因为在工作开始之前,总工作量是已知的。

智能体(Agent)从根本上打破了这个假设。它执行的不是预定的步骤列表——它在执行过程中不断发现剩余的工作。它读取一个文件,结果发现了另外三个值得读取的文件。它运行测试,测试失败了,于是引发了一个谁也没计划过的调试分支。原来的第 4/7 步变成了第 4/19 步,偶尔又会变成第 4/4 步,因为最后三步被证明是不必要的。对于智能体来说,计算完成百分比(Percent-complete)并不难,而是“未定义”。在工作完成之前没有分母,而一旦完成,答案永远是 100%。

然而看看我们发布的产品:预示即将完成的加载动画(spinners)、爬到 90% 就卡住的进度条、在原本需要 8 分钟的任务进行到第 2 分钟时显示“即将完成……”的标签。这些都是小小的谎言,而且用户能识破它们。有趣的交互设计问题不是如何更逼真地伪造进度,而是当工作的持续时间在结构上无法预知时,诚实的安抚(honest reassurance)应该是什么样子的。

那些将模型未完成的残缺回答存入数据库的流式 UI

· 阅读需 12 分钟
Tian Pan
Software Engineer

这份事后分析读起来像是一份幻觉报告。一名用户根据一份语气笃定的建议采取了行动,但结果证明该建议是错误的——这种错误在模型正常完成输出的情况下是不会出现的。然而,追踪记录显示模型并未完成输出。在预期的 800 个 Token 中,供应商连接在第 412 个 Token 时断开了。客户端的错误处理程序记录了这次失败。但随着 Token 的到达,持久化的部分消息已被写入对话历史,在用户的 UI 中看起来与其他完整的回答毫无二致。于是用户采信了它。支持团队将该工单归类为内容质量问题,花了整整两周时间才将其转交给平台团队。

这条链路中没有任何环节属于模型故障。模型对生成的 412 个 Token 表现得非常正确。失败的原因在于流式 UI 和持久化对话历史在“什么才算是一条消息”的问题上产生了隐秘的分歧。而正是这种流式传输本应缓解的故障模式,导致这一分歧成为了权威记录。

这是乐观渲染(Optimistic Rendering)与持久化存储之间的契约。大多数聊天产品只是从教程或框架中继承了这种模式,而从未将其视为一项契约,这种鸿沟最终表现为一系列看似模型 Bug 实则不然的尾部故障。

用户习以为常的“你确定吗?”确认步骤

· 阅读需 11 分钟
Tian Pan
Software Engineer

确认对话框是 AI agent 工具箱中最廉价的安全层。它由一个字符串、一个按钮和一个回调函数组成。提议增加这一功能的项目经理在散会时,坚信该 agent 现在是安全的。开发它的工程师用一个下午就把它发布上线了。负责审计的合规检查员勾选了通过选项。而那天早上第七次看到它的用户,在眼睛还没读完标题之前,鼠标就已经移到了“确认”按钮上。

不到一周,确认步骤就不再是一个决策点,而变成了一种节奏。Agent 问:“你确定要发送这封邮件吗?”,用户回答“是”,就像别人打喷嚏时随口回一句“保重”一样自然。终有一天,Agent 会提议一个真正错误的动作——错误的收件人、错误的金额、错误的语气——而用户会带着之前确认那六个正确动作时同样的自动化反应去确认它。邮件发出后,团队写下一份事后分析,称之为“用户操作失误”。

这不是用户错误。这是系统误把“点击”的存在当成了“同意”的存在。

那个教会用户永远不要打断智能体的中断 UI

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的流式智能体上的中断按钮点击率仅为 0.4%。产品团队看到这个数字,得出的结论是该功能正按预期运作——大多数生成内容不需要中断,实现方案没问题,发布吧,继续下一个任务。而实际的解读应该是,这个中断按钮教会了你的用户不要去按它。在使用产品不到一周的时间里,他们就发现按下停止键会丢弃已生成的片段、清除上下文,并把他们丢回到一个空的输入框中。他们学到的教训是:宁愿忍受一个糟糕的回答,也不愿冒着丢失整个对话脉络的风险。

这 0.4% 不是使用信号,而是厌恶信号。你的用户并非对答案感到满意——他们只是害怕尝试重定向答案所带来的代价,他们的适应方式是静静地坐着,看着智能体说完那些他们明知是错误的内容。工程团队将“停止生成”视为模型调用的取消。而用户将其视为“重定向,而非重启”。这两种定义从未达成一致,导致产品发布了一个在长对话中悄悄剥夺用户主动权的功能。

Agent 循环从搜索框偷走的延迟预算

· 阅读需 13 分钟
Tian Pan
Software Engineer

发布指标看起来很干净。回答质量提升了,引用率上升了,评估套件全绿。那个用基于 Agent 的检索器替换旧关键词搜索的团队发布了产品,赢得了胜利,然后转向了下一个项目。六周后,有人注意到该界面的周活跃用户数下降了 12%,但没人能找到性能回归。其实并没有回归。Agent 运行正常。用户离开是因为以前在 200 毫秒内就能给出答案的搜索框,现在需要 4 秒钟,而发布回顾中没有任何内容涉及到这方面的预算。

这就是延迟预算转移问题,而且几乎没有人会画出能捕捉到这一问题的组织架构图。搜索框不仅仅是一个函数调用。它是与用户神经系统签订的一份为期三十年的契约:输入、查看结果、扫视、点击。200 毫秒的响应并不是某个仪表盘上的性能指标——它是当结果送达时,用户的注意力仍然留在屏幕上的原因。当搜索框背后的团队用 Agent 循环替换关键词索引时,函数调用表面看起来是一样的,但新调用的 SLA 处于一个完全不同的范畴。延迟预算从拥有索引的团队转移到了拥有 Agent 的团队,又从拥有 Agent 的团队转移到了用户身上,而唯一参加会议的只有用户。

自相矛盾的流式响应

· 阅读需 9 分钟
Tian Pan
Software Engineer

模型在第一句说“答案是肯定的”。到了第三段,它又改口说“实际上,经过反思,不——原因如下”。最终状态是正确的。但用户已经离开了。他们读了第一段,将其视为答案,并在模型完成修正之前就付诸行动了。你的评估认为该回答是正确的。但你的用户得到的却是错误的。

这是流式传输 UX 所隐藏的失败模式。逐字渲染(Token-by-token rendering)将每个区块都视为既定事实,但模型并没有“提交”(commit)的概念。在模棱两可的话语和结论之间没有边界,也没有信号表明“接下来的两段将推翻我刚才说的话”。界面将中间状态作为最终状态发布,且回答越长,这种差距就越严重。

对话中途耗尽的 Token 预算:为什么免费用户觉得你的模型变笨了

· 阅读需 12 分钟
Tian Pan
Software Engineer

我认识的一位产品经理,花了两周时间排查公司 AI 写作助手的流失激增。免费用户的会话长度骤降 30%,客服收件箱挤满了"你们的模型以前很聪明,现在变懒了"的各种变体,团队第一反应是把锅甩给同一周上线的模型升级。模型其实没有变。变的是财务在季度中途悄悄收紧了按用户分配的 Token 预算,应用在用户跨过新阈值时,正在静默截断系统提示词、丢弃工具调用、缩短回答。从用户的座位看,AI 退化了。从仪表板看,一切正常。两边都对,这就是失败模式。

这种模式现在到处都是。ChatGPT 免费版触达上限后会切到一个更小的模型,产品里除了"接下来一段时间回答可能会短一点"之外没有任何标识。Anthropic 的免费层行为类似。你在任何一家之上做功能,再叠加一层自己的按用户 Token 预算用来控成本,于是你串联了两道隐形悬崖——平台的,加上你的——而用户只看到一个聊天框,无从分辨自己刚才到底踩到了哪一道。

那位通过反复试验摸清你 Prompt 的高级用户

· 阅读需 10 分钟
Tian Pan
Software Engineer

此刻,你的产品里有一位用户,体验远好于中位数用户。不是因为他付得更多,不是因为他在不同的订阅层,也不是因为他被分到了某个特殊的实验组。他通过耐心地试探,发现这个 AI 功能只要换种方式提问,就会给出漂亮的回答。他知道哪些动词能触发结构化输出。他知道一个词的追问会得到精简版本,一整句话则会得到展开版本。他知道某些话题如果不包装成假设性问题,助手就会戒备起来。这一切,你的网站上没有一处写过。他是逆向工程出来的。

有意思的不是这种用户存在,而是这种用户现在成了你的产品文档。你的 AI 功能跟用户之间签了一份契约——一份没公开的契约,完全编码在系统 prompt 里——而了解这份契约的唯一方式就是反复试验。只有一小部分用户有耐心去做这些试验。其余人拿到的是一个更糟糕的产品。

在用户说"是"之前就已提交的流式响应

· 阅读需 11 分钟
Tian Pan
Software Engineer

用户正在阅读 Agent 流式输出的推理过程。在 token 1200 附近,模型决定调用 send_email,然后 create_ticket,再 kick_off_deploy。用户看到部分输出并意识到 Agent 误解了请求,在停止按钮上慢了半秒。邮件已经发出,工单已经创建,部署已经在跑。停止按钮取消的是下一个 token,而非上一个 token 的后果。

Bug 不在取消处理程序里。Bug 是那个假设——从团队路线图上所有其他流式 UI 借来的假设——即"逐步渲染的输出"就是"逐步可逆的输出"。工具调用并不遵守这个契约。它们是时间点上的提交,流式层一边欢快地触发它们,响应的其余部分还在生成中,而取消按钮无法沿着线路追赶它们。

这是那种没人认领的失败模式,因为它存在于两个团队各自干净交付的接缝处。UX 团队上线了流式,因为用户研究中表现更好;平台团队上线了工具调用,因为框架支持。两个团队都没有开过会问:当响应已经离开大楼时,"停止"应该是什么意思?

流式 Token 是无法收回的承诺

· 阅读需 10 分钟
Tian Pan
Software Engineer

模型已经向用户屏幕推送了 70% 听起来很自信的回答。接着,它即将进行的工具调用返回了错误、无结果或 429 错误。现在你必须在两种损失之间做出选择:让模型通过编造剩余部分来优雅地结束,或者在句子中间戛然而止,且没有体面的方式撤回。这两种都不是修复 —— 它们都是损害。

这是流式传输 UX 中没人考虑过成本的部分。流式传输被描绘成一种感知延迟的胜利:首个 Token 时间 (TTFT) 是核心指标,用户更早开始阅读,应用显得充满活力。但这种描绘忽略了你推送的每一个 Token 都是一种承诺。你发布了一个你还不知道是否正确的答案草稿,而你系统的后半部分还没有运行完毕。当它运行结束并产生分歧时,你的 UI 没有原生方法来撤回已经显示的内容。