首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >人人皆可做一个OS #Gemini OS:实时解析、渲染与交互

人人皆可做一个OS #Gemini OS:实时解析、渲染与交互

作者头像
mixlab
发布2026-03-24 21:42:16
发布2026-03-24 21:42:16
990
举报

shadow:AI编程,本质上就是在构建Agent:Context、LLM、Tools、GUI。

今年初兴起的 Vibe Coding(凭感觉编程)正是这一趋势的鲜明体现——开发者只需描述软件的大致功能与使用体验,即可自动生成可运行的应用,编程过程从“精确地实现逻辑”转向“直观地描绘意图”。

这标志着软件开发范式迎来了根本性转变,人机交互也随之进入实时响应与高度个性化的新阶段。我们不禁反思:软件为何必须被预先完整构建?未来的软件或许将不再是一个个冻结的二进制实体,而更像是一篇篇动态文档,清晰阐述了其核心功能与交互逻辑。最终,将由如 OS.ai 这样的智能系统进行实时解析、渲染与交互,让软件从“制造出来的产品”彻底转变为“随时可被唤起的能力”。

Gemini OS 这个案例,代表着这一发展趋势 ⤵️ :

Gemini OS

一个创新的桌面操作系统模拟器。其核心特点是,所有应用程序的用户界面(UI)并非预先编码,而是由Gemini大语言模型根据用户交互实时生成。当用户点击图标或按钮时,应用会捕捉该操作,连同历史记录一起发送给Gemini。模型随即以流式传输方式返回新的HTML内容,动态渲染出应用界面,实现了高度动态和可扩展的人机交互体验。

架构与数据流

该应用使用 React 和 TypeScript 构建,并采用 Tailwind CSS 进行样式设计。其核心逻辑可以分解为一个持续循环的流程:

1 用户互动: 您点击屏幕上的一个可交互元素(例如,“记事本”图标)。

2 互动捕捉: GeneratedContent 组件中的一个中央事件监听器会捕捉到这次点击。它会将关于被点击元素的重要信息收集到一个 InteractionData 对象中,包括:一个唯一的 ID (data-interaction-id),元素的类型和文本内容,以及当前的应用程序上下文(例如,'notepad_app')。

3 状态管理:InteractionData 对象被发送到主组件 App 中。这次新的互动被添加到一个名为 interactionHistory 的数组中。这个历史记录至关重要,因为它为 LLM 提供了您之前操作的上下文。在等待下一步时,应用程序会显示一个加载动画。

4 API 服务:interactionHistory 数组被传递给 streamAppContent 函数。这个函数会构建一个详细的提示(Prompt) 发送给 Gemini API。这个提示是整个操作的“大脑”,它包含:

  • 系统指令: 一套非常长且详细的规则,告诉模型它的角色(一个操作系统)、如何格式化其响应(必须是纯 HTML)、应该使用哪些特定的 CSS 类进行样式设计,以及如何通过添加 data-interaction-id 属性来使新元素可交互。
  • 互动上下文: 对您最近一次点击的总结,以及您之前的互动列表。
  • 提示被发送到 gemini-2.5-flash 模型,并使用流式 API 。

5 内容生成与流式传输:Gemini 模型处理提示并开始为新的 UI 生成 HTML。因为是流式传输,响应会以小数据块(chunks)的形式被逐步发送回来,而不是等整个响应完成后一次性发送。App 组件接收这些数据块,并将它们追加到其 llmContent 状态中。这使得新的 UI 会在屏幕上逐块出现,就像文本被逐字打印出来一样。

6 渲染:llmContent 字符串(HTML)通过 React 的 dangerouslySetInnerHTML 属性直接渲染到一个 div 中。

7 特殊的脚本处理:如果来自 LLM 的 HTML 包含任何 <script> 标签(例如在“游戏”应用中使用),它会找到这些标签并重新执行它们。正是这个机制,使得模型能够即时生成功能齐全、自包含的 JavaScript 游戏。

8 循环重复:新的 UI 现在已经显示在屏幕上,应用程序等待您的下一次互动,届时整个周期将再次开始。

特殊脚本处理

如何让语言模型生成的、包含在HTML里的<script>标签(例如游戏代码)能够被浏览器执行。

这是一个非常关键的环节,因为出于安全原因,浏览器不会执行通过dangerouslySetInnerHTML(或innerHTML)插入到页面中的script>标签内的JavaScript代码。我们的应用必须绕过这个限制。

下面是具体的处理流程:

1 触发时机

脚本处理逻辑只在两个条件同时满足时才会执行:

A 加载完成: 必须等待所有HTML内容从Gemini API流式传输完毕。如果在内容还没加载完时就处理,可能会执行不完整的代码。

B 内容已更新: 组件会记录上一次处理过的htmlContent。只有当新的htmlContent与上一次不同时,才会重新执行脚本处理,这是一种性能优化,避免了不必要的重复执行。

2 处理步骤

一旦触发,代码会执行以下操作:查找所有脚本 (container.getElementsByTagName('script')):

首先,代码会在刚刚通过dangerouslySetInnerHTML渲染出来的DOM内容中,查找并获取所有的<script>元素。

此时,这些脚本标签虽然存在于DOM树中,但它们是“惰性”的,里面的代码不会被执行。 遍历并“激活”脚本: 代码会遍历找到的每一个“惰性”脚本(我们称之为oldScript)。

对于每一个oldScript,它会执行一个“克隆替换”的技巧

a. 创建新脚本 (document.createElement('script')): 创建一个全新的、空的<script>元素(newScript)。

b. 复制属性: 将oldScript上的所有HTML属性(例如 id, type等)都复制到newScript上。

c. 复制内容 (newScript.text = oldScript.innerHTML): 将oldScript标签内部的JavaScript源代码(innerHTML)复制到newScript的text属性中。

d. 替换节点 (oldScript.parentNode.replaceChild(newScript, oldScript)): 这是最关键的一步。在DOM中,用我们刚刚创建的newScript替换掉原来的oldScript。

3 原理核心

这个“克隆替换”技巧之所以有效,是因为:通过 document.createElement 创建并手动插入到DOM中的脚本节点,会被浏览器视为合法的、需要执行的脚本。 因此,通过这个替换操作,我们欺骗了浏览器,让它认为这是一个正常的、动态添加的脚本,从而触发了JavaScript的解析和执行。

总结

简单来说,整个流程就是:等待LLM生成完整的HTML。在渲染出的内容里找到所有不会自动执行的<script>标签。为每个标签创建一个“替身”,把代码和属性都复制过去。用这个能被浏览器执行的“替身”换掉原来的标签。

正是这个机制,使得由语言模型动态生成的、包含完整逻辑的JavaScript游戏(如贪吃蛇)能够在我们的应用中真正地运行起来。

Prompt 工程

github.com/shadowcz007/gemini-os

现在,你可以用 vibe coding 试试了!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 无界社区mixlab 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Gemini OS
    • 架构与数据流
  • 特殊脚本处理
    • 1 触发时机
    • 2 处理步骤
    • 3 原理核心
    • 总结
  • Prompt 工程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档