如何让 Chat 知道当前页面的信息
想让 Chat 真正理解用户正在看的页面,不能只靠截图,也不能只靠后端数据。更稳的做法是把截图、页面数据接口和未提交状态数据联合起来,形成完整 context。
- AI
- Chat
- UI
- Context
- Architecture
如果你想在一个产品里接入 chat 或 agent,一个非常核心的问题是:
怎么让它知道“用户当前正在看的这个页面,到底是什么”。
很多系统一开始都会低估这件事,觉得只要把页面截图丢给模型,或者把当前页面的接口数据给模型看一下,就差不多了。
但真到复杂页面里,你很快会发现:
- 截图只能看到一部分
- 数据接口只覆盖已保存状态
- 页面上很多临时交互状态,后端根本还不知道
所以如果目标是真正让 chat 理解当前页面,最稳的思路不是只押一种来源,而是把几种不同来源的上下文联合起来。
我更推荐一个简单的框架:
- 截图
- 数据
- 状态数据
三者联合提供当前页面的 context。
一、截图:最容易实现,但天然不完整
截图通常是最先想到的方案。
原因很简单:
- 容易实现
- 不需要强耦合业务代码
- 对任何页面都适用
- 很适合作为通用兜底方案
从工程角度看,截图方案确实很有吸引力。你只要能拿到当前页面的可视区域,就已经能给模型提供一部分语义线索,比如:
- 当前页面大概是什么类型
- 页面里有哪些模块
- 用户当前停留在哪个区域
- 哪些文案、按钮、表格、图表正在被展示
但截图的问题也很明显。
1. 截图可能不全
用户当前页面很可能是长页面、滚动页面、分栏页面、弹窗叠层页面,或者带折叠区的复杂工作台。
这时候一张截图往往只能覆盖:
- 当前可视区域
而覆盖不了:
- 页面上方已经滚过去的信息
- 页面下方还没滚到的信息
- 被 tab、折叠、弹窗或 hover 隐藏的信息
2. 截图的语义理解不够稳定
截图是视觉输入,不是结构化输入。
模型虽然能看图,但很多关键细节仍然容易丢:
- 字很小
- 表格过密
- 某些字段只是视觉上相邻,但真实上并不属于同一对象
- 图表能看出趋势,却看不出精确数据
所以截图适合提供“感知层 context”,但不适合单独承担精确理解。
3. 截图拿不到真实对象 ID
这点尤其关键。
截图可以告诉模型“这里像是一个订单详情页”,但它通常不能稳定告诉模型:
- 当前订单的真实
id是什么 - 对应后端该查哪个对象
- 页面上的某个卡片对应哪个具体业务实体
所以截图的优势很明确:
- 容易实现
- 覆盖面广
- 通用性强
但它的缺点也很明确:
- 可能不全
- 准确性不足
- 不足以承载精确业务操作
二、数据:给 chat 一个可追溯的业务对象入口
如果想让 chat 不只是“看懂页面大概在干什么”,而是真的能围绕当前页面做可靠分析、检索和操作,那就必须补第二层:
数据。
最关键的一步,是给当前页面注册一个明确的项目 ID,或者更广义地说,注册当前页面正在围绕哪个业务对象展开。
比如:
- 当前页面的项目
id - 当前文档
id - 当前报表
id - 当前工单
id - 当前会话
id
一旦这个页面对象 ID 明确了,chat 才能进一步做稳定的数据获取。
这里真正重要的不是“把所有数据都塞进 prompt”,而是:
- 注册当前页面对象 ID
- 告诉 agent 可用的数据接口
- 让 agent 能按需拉取关联数据
这意味着页面和 chat 系统之间,最好有一层显式契约,例如:
- 当前页面主对象是谁
- 可调用哪些数据接口
- 哪些接口返回摘要数据
- 哪些接口返回详情数据
- 哪些接口可以继续展开子对象
这样做的优势是:
- 业务语义更准确
- 可以追溯到真实后端对象
- 可以补全截图看不到的信息
- 可以避免模型纯靠视觉猜测
但这层数据也有一个天然边界:
它通常只能代表“已提交、已持久化”的状态。
也就是说,后端知道的是系统里当前保存了什么,而不一定知道用户此刻正在前端改什么。
三、状态数据:补上“用户此刻正在编辑什么”
很多页面最关键的信息,恰恰不在截图里,也不在后端数据库里,而在前端运行时状态里。
比如:
- 表单里刚改了一半、还没提交的字段
- 拖拽后尚未保存的布局顺序
- 多选器里已经选中但还没提交的对象
- 过滤器、排序器、时间范围等临时视图状态
- 当前展开的 tab、折叠区、hover 目标、选中的图表点
这些信息如果不给 chat,它就会发生一种很典型的错位:
- 它知道数据库里是什么
- 也大概知道用户页面长什么样
- 但它不知道用户此刻真正关心的是哪一块、正在改哪一块
所以第三层必须补的是:
未提交的临时状态数据。
这是很多 chat 接入失败的根因之一。系统以为自己已经把页面对象和截图都给模型了,但模型还是回答得不够贴合当前交互。原因不是模型太笨,而是上下文漏了“当前前端状态”。
这层状态数据适合包含:
- 当前页面 route 参数
- 当前选中的对象 ID
- 当前表单草稿值
- 当前筛选条件
- 当前 tab / 面板 / 弹窗状态
- 当前用户焦点所在区域
这样,chat 才能理解:
- 用户不是在问整个项目
- 而是在问这个项目里当前打开的这个页面
- 甚至是这个页面里当前编辑到一半的这一块内容
四、为什么 1、2、3 必须联合提供
真正稳定的页面 context,不应该依赖单一来源,而应该把三种来源组合起来。
它们各自解决的问题并不一样:
- 截图:提供视觉感知和页面布局线索
- 数据:提供真实业务对象和后端可追溯信息
- 状态数据:提供用户此刻正在操作的临时前端状态
这三者缺一都会有明显短板。
只有截图,没有数据,问题会变成:
- 看起来理解了页面,但不能稳定落到真实业务对象
只有数据,没有截图,问题会变成:
- 知道对象是什么,但不知道页面此刻是怎么呈现的
只有后端数据,没有前端状态,问题会变成:
- 知道系统里保存了什么,但不知道用户当前正在改什么
所以更稳的方案不是三选一,而是:
1、2、3 联合提供当前页面的 context。
五、一个更实用的上下文分层
如果把这件事再工程化一点,我会把页面上下文拆成三层:
1. 感知层
- 页面截图
- 当前可视区域
- 页面结构摘要
这一层负责回答:
- 用户当前大概看到了什么
2. 业务层
- 页面主对象 ID
- 关联数据接口
- 可拉取的结构化业务数据
这一层负责回答:
- 这个页面真实对应什么业务对象
3. 交互层
- 未提交表单状态
- 当前筛选和选择状态
- 当前焦点、弹窗、tab、草稿
这一层负责回答:
- 用户此刻正在操作什么
当这三层一起存在时,chat 才真正拥有接近“站在用户当前页面里思考”的能力。
六、设计重点不是把更多数据塞进去,而是把 context 分层组织好
很多系统一遇到上下文不足,就会本能地想:
- 那就多传一点
- 那就把整页 DOM 都给模型
- 那就把所有接口数据全塞进去
这通常不是好办法。
因为真正的问题往往不是“量不够”,而是“结构不对”。
更合理的做法是显式区分:
- 哪些是视觉线索
- 哪些是结构化业务数据
- 哪些是前端临时状态
再根据任务按需组合给 chat。
比如:
- 问页面布局或视觉问题时,截图权重更高
- 问业务对象详情时,数据接口权重更高
- 问“我刚刚改的这块内容有没有问题”时,状态数据权重更高
这样,系统给模型的就不是一坨混乱上下文,而是一组有分层、有职责的页面语义来源。
结语
让 chat 知道当前页面的信息,本质上不是“喂一张图”这么简单。
真正可靠的做法是同时提供三类 context:
- 截图
- 数据
- 状态数据
截图解决的是容易接入和视觉感知,数据解决的是真实业务对象和可追溯性,状态数据解决的是用户当前正在编辑和操作的临时上下文。
只有 1、2、3 联合起来,chat 才真正更有机会理解“当前页面”。