在个人应用中巧妙融合AI与UI
本文介绍了Millwright——一种三层数据契约架构,使模型生成的分析结果在不接触标记、样式或DOM的情况下渲染。通过类型化的结果构件、语义化版本控制的看板以及仅允许添加的导航页面,确保安全、可审计且可撤销的AI集成。
本文探讨了如何在个人应用中安全地将AI生成的动态内容融入用户界面,而不让AI模型直接操作标记、样式或DOM。作者介绍了其应用millfolio中的一项名为Millwright的功能,该功能采用三层数据契约架构,将模型输出转化为可安全渲染的UI组件。
第一层是构件层。构件的内容由小型沙盒程序生成,这些程序同样用于处理一次性查询。程序从不返回HTML或Markdown,而是返回版本化的JSON信封,其中包含类型化的数据块,例如文本、表格、关键绩效指标(KPI)、时间/类别序列、份额饼图以及离线比例符号地图。每个值都有明确的类型,例如货币值以{raw, text}形式传递,客户端根据数字和格式化字符串分别使用,无需从显示字符串中解析。这种“可信外壳”不变量确保程序只产生数据,而外壳管理所有交互。当表格列标记为商家或标签时,外壳会自动将单元格转换为指向Vault记录的深层链接,程序无法注入脚本或链接。因为契约中根本没有位置放置这些元素。
第二层是看板层。看板本身是一个语义化的版本化规范文档,包含有序的构件列表,每个构件有ID、标题、大小提示和指向计算程序的指针。编辑操作(调整大小、编辑程序、删除构件)会生成新的内容寻址版本(基于字节的16位十六进制FNV-1a哈希),并追加到版本日志中。当前看板只是该日志中的一个指针,因此撤销只需移动指针,编辑出错不会破坏早期版本。在接受任何候选规范之前,无论来自内联编辑器还是模型,都会经过验证器检查:构件ID必须路径安全且唯一、引用的程序必须存在、远程URL被直接拒绝、结构限制被强制执行。模型提出,验证器决定。
第三层是页面层。一组构件可以提升为页面,获得自己的顶级导航按钮,与Ask和Vault并列,解散页面则将其构件返回看板。页面使用相同的规范文档(pages[]部分)、相同的版本控制和验证器,但有一条额外规则:导航变更是仅添加的。生成的编辑可以添加页面,但绝不能重命名或移除内置标签。用户依靠检查模型行为的UI部分(如Ask、Vault)本身不能被模型编辑。
为什么采用分层而不是让模型直接编写UI?显而易见的替代方案是让模型生成HTML/JSX并沙箱化,但其缺点包括无法进行差异比较、无法结构验证、无法通过移动指针还原,而且每次渲染都涉及安全决策。三层数据层提供了相反的权衡:每个模型贡献都是可检查、可版本化、可验证和可拒绝的文档,而像素始终由随应用发布的代码绘制。这种分层也使得公共演示安全可靠:演示看板使用相同机制处理合成数据,编辑保存在浏览器的localStorage中——相同的哈希算法、验证器和外壳。
总结:Millwright通过严格的数据契约和分层架构,实现了安全、可审计且用户可控的AI集成,避免了AI直接操作UI带来的安全风险和不可预测性。用户可以在demo.millfolio.app体验编辑并撤销功能。