如果你最近在关注 AI 应用开发,会发现一个现象:很多人把大模型接进 App 之后,界面还是老样子——固定的页面、固定的表单、固定的列表,聊天框像补丁一样粘在页面角落。这其实还算不上 AI 原生应用,最多算“AI 增强应用”。真正让我觉得有意思的,是把界面本身变成 AI 的输出结果:AI 理解用户意图之后,动态决定这一屏应该展示什么、用什么组件、信息怎么排布,这就是 AI 原生应用的自适应界面。
这篇文章会从概念讲起,然后完整走一遍从需求拆解、架构设计、关键代码到踩坑修复的实施流程。内容偏工程落地,适合已经能调用大模型 API、想做深度集成的团队或个人开发者。我会结合一个“AI 出行助手”的实际例子展开,也会讲清楚我理解的“AI 原生应用架构成熟度”分几个阶段,方便你对照自己项目到底处在哪个位置。
1. 项目定位与设计思路拆解
1.1 AI 原生应用与传统应用的本质区别
先说一个容易被忽略的判断标准。普通业务系统里,AI 只是某个功能模块:比如客服页面调用模型回答用户问题,或者运营后台用模型做内容分类。界面结构和业务流程还是人肉设计好的,AI 不参与“界面长什么样”的决策。
而 AI 原生应用正好反过来:模型不仅是业务逻辑的执行者,还在某种程度上是体验的编排者。用户进入产品之后,系统先通过多轮对话理解真实目标,再动态生成操作界面。比如用户说“下周去杭州出差,帮我订一个离客户近、能开发票的酒店”,传统 App 会给一个巨大的酒店筛选页,用户自己拖着十几个筛选项慢慢调;AI 原生应用则可能直接渲染出“三个候选酒店 + 一栏离客户公司的距离提示 + 发票信息确认卡片”。后者更贴近任务,也更省事。
所以,从产品设计的第一天起,“界面是变量而不是常量”这个理念,就必须成为团队的共识。它影响到数据建模、接口设计、测试策略,甚至 UI 组件的写法。
1.2 自适应界面到底“自适应”什么
绝大部分人听到自适应界面,第一反应是响应式布局——根据屏幕宽度调整卡片排列。那是 Web 1.0 就有的问题。AI 原生应用里的“自适应”,是指界面要适配下面三个维度:
- 用户意图:用户想要筛选航班,还是想要改签,界面逻辑完全不一样。
- 对话上下文:上一轮用户预付了款,这一轮再说“我要取消”,系统要能理解是取消刚才的订单。
- 数据状态:当查询结果为空、接口报错、或需要二次确认时,界面必须能随机应变,不能出现空白页或死路。
换个更通俗的说法:传统界面是“产品经理预设好所有路径”,自适应界面是“AI 根据用户当下的一句话临场铺路”。这就要求我们把“界面结构”和“界面内容”拆开,把每一种可能出现的界面形态抽象成可被描述、可被传输、可被校验的数据结构。
1.3 AI 原生应用架构成熟度:你的项目在第几层
“AI 原生应用架构成熟度”这个说法,我把它定义为:AI 在多大程度上接管了应用的状态流转和界面生成决策。按我的经验,可以粗略分五个阶段:
| 成熟度 | 阶段名称 | 典型表现 | 架构核心 |
|---|---|---|---|
| L0 | 无 AI | 所有界面/流程硬编码,AI 没接入 | 传统 MVC/MVVM |
| L1 | 对话浮层 | 聊天机器人悬浮在固定页面上,界面仍由开发人员静态定义 | 聊天组件 + 知识库 |
| L2 | 模板拼装 | 预置若干页面模板,AI 按意图选择某一套渲染 | 意图分类 + 模板路由 |
| L3 | Schema 驱动 | AI 生成结构化界面描述,前端渲染器动态渲染 | 界面描述协议 + 动态渲染 |
| L4 | 模型原生编排 | AI 跨页面编排流程,自主拆解任务、调度多个 Agent,界面实时更新 | 多 Agent 编排 + 全链路状态管理 |
大部分宣称在做 AI 应用的产品,其实只到 L1。做到 L2 的已经不多。真正想去到 L3,就必须建设一套界面描述协议。这篇文章主要围绕 L3 如何落地,最后会聊到向 L4 演进时的一些思考。把这个成熟度框架放在团队里还有一个好处:不同岗位能很快对齐“我们现在做的是哪个阶段的事”,避免前端等后端定义死页面、后端等模型直接吐可执行代码这种两头乱的状态。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心机制设计:让界面跟上用户意图
2.1 为什么选择“UI Schema 中转”,而不是让 AI 直接写代码
一开始做这个项目时,我走过弯路。我的第一版思路是:让模型直接输出 JSX 或者 HTML,前端拿到之后 dangerouslySetInnerHTML 直接渲染。结果只跑了半天就放弃了。问题很明显:模型生成的代码质量不稳定,一旦引入了它自创的组件库、或者调用了不存在的事件方法,页面就白屏;更可怕的是安全不可控,模型可能在一句话的引导下输出包含外部资源链接的脚本,等于把 XSS 的大门打开。
后来我把方案调整为:模型不直接生成代码,而是生成一份高度结构化的 UI Schema(界面描述)。前端有一个“渲染器”,根据 Schema 里的 type 字段到组件注册表里找到对应组件,再填充数据渲染出来。
画个对比就清楚了:
- AI 直接输出代码 = 让一个外聘顾问直接进你的生产环境改代码,速度快但翻车了没兜底。
- AI 输出 Schema = 顾问只写一份“需求描述+建议方案”,经验丰富的工程团队去实现,安全且可控。
用 Schema 中转还有一个额外好处:可以校验。模型输出如果不符合 JSON Schema,我们可以在渲染前拦截并做修复或降级处理。而代码字符串无法结构化校验,除非你起一个沙箱环境去编译运行,成本很高。
2.2 设计一份“最小可用”的界面描述协议
界面描述协议是整套系统的地基。它要覆盖常见业务场景,又不能把组件库的每个属性都暴露给模型,否则模型会无所适从。我的做法是定义一套组件白名单,每个组件有固定的 schema,模型只能从白名单里做组合。
所谓“最小可用”,我理解包含这几类组件:
- 信息展示型:标题、段落、图片、卡片、列表、表格、统计指标
- 操作交互型:按钮(支持点击后触发预定义动作)、输入框(提交后回到对话)
- 容器布局型:垂直堆叠、横向排列、分组面板、弹窗
- 特殊场景型:表单生成器、时间轴、状态提示、错误页
实际项目里,我给每个组件分配一个唯一的 type 名称。模型产出的最高层是一个 page 容器,里面有序地放各个区块。整个输出的核心数据结构如下:
json复制{
"schemaVersion": "1.2",
"page": {
"type": "stack",
