json-render 的 Jev 组合实验:用受限候选集与评估器协议驱动生成式 UI 树

📅 发布时间:2026/9/21 3:20:39
json-render 的 Jev 组合实验:用受限候选集与评估器协议驱动生成式 UI 树
json-render 的 Jev 组合实验用受限候选集与评估器协议驱动生成式 UI 树【免费下载链接】json-renderThe Generative UI framework项目地址: https://gitcode.com/GitHub_Trending/js/json-render本文是 json-renderGenerative UI framework仓库内apps/web官网与 Playground中Jev 组合实验Jev composition experiment的完整技术指南。该实验在 Playground 的/playground页面提供 default / jev 双模型切换让 Jev 模型通过 Vercel AI Gateway 从组件目录中挑选原子候选、组合出一棵可交互的 UI 树并在后续请求中以 add / replace / remove / move 的顺序编辑协议持续迭代。读完本文你将掌握该实验的运行方式、密钥与限额配置、两阶段批处理组合流程、顺序编辑协议以及其底层experimental_*公共 API 的调用契约与实现原理。实验定位一个受目录约束的 UI 组合器apps/web/README.md中明确说明Playground 的/playground页面内置一个 default / jev 切换开关default对应常规的生成式模型通过AI_GATEWAY_API_KEY调用而jev是一个实验选项鼠标悬停或聚焦其信息图标即可看到实验性状态说明。Jev 选项是json-render/core中可复用 APIexperimental_composeSpec与experimental_createEvaluator的参考消费方reference consumerJev 从 Playground 的组件目录catalog与允许的动作绑定action bindings中组合并编辑 UI 树服务端通过 Vercel AI Gateway 完成评估调用Jev 专用密钥为JEV_AI_GATEWAY_API_KEY默认模型继续使用AI_GATEWAY_API_KEY后续追问follow-up以所选版本作为initialSpec可以对树执行新增、替换、删除、移动且早前版本保持原样不变不可变版本历史与 default 模型共用同一套提示输入、版本历史、spec/流式检查器与功能预览共享的/api/generate端点负责流式输出 spec 补丁spec patches与决策元数据。实验的完整设计文档位于 apps/web/lib/jev/README.md其中包含运行方式、架构与限制的权威说明是本文的骨架来源文中所有源码引用均来自当前仓库。运行实验密钥、启动与试玩路径密钥配置在apps/web/.env.local或服务器环境中设置JEV_AI_GATEWAY_API_KEY你的 Vercel AI Gateway 密钥要点来自 apps/web/lib/jev/README.mdPlayground 为 Jev 使用这个专用 Gateway 密钥default 模型继续使用AI_GATEWAY_API_KEYJev 不会回退到 default 模型的密钥未配置时服务端会返回 503见下文Gateway 团队必须放行typesafe-aiprovider无需单独的 TypeSafe API key该密钥只应存在于服务端。核心包中的 experimental-evaluator.ts 对apiKey的注释明确写着Server-side Vercel AI Gateway key. Never expose this in browser code.并在空密钥时直接抛出 A Vercel AI Gateway API key is required.。启动开发服务器从仓库根目录执行pnpm --filter web devapps/web/package.json中dev脚本为portless json-render next dev --turbopack依赖全局工具portless未安装时会提示先执行npm i -g portless。使用命令打印的 portless URL 并追加/playground访问在 HTTPS 代理开启时即为https://json-render.localhost/playground。推荐的试玩流程文档给出的端到端验证路径是选择 Jev → 选择Create account settings示例 → 发送请求 → 编辑姓名、打开通知开关、点击Save changes、再点Reset。需要特别注意的语义约束动作处理器只在用户交互时运行Jev 只负责把动作绑定写入 spec绝不会在生成阶段执行它们表单提交仅做校验并弹出 toast 演示它不会认证用户也不会真的发送消息所有业务数据均为合成数据synthetic。Jev 如何产出 spec两次有限选择 顺序编辑协议Jev 是组合式模型它暴露 Choice、Boolean、Score 三类输出不产出自由格式的 JSON 或散文。因此新 UI 的构建被表达为两批有限选择batches of finite choices完整流程共 5 步第一批select 阶段在一次评估中同时询问根元素root与各独立组件的成员资格问题。互斥的资源变体共享同一个问题同一问题内二选一可复用的配方recipe则给出有界的使用数量。候选值中包含应用自己拥有的状态/动作绑定。组装并校验预览选定内容立即组装、校验并流式输出预览。预览采用目录顺序catalog order与根的默认插槽default slot。当同一配方/资源同时被选为根时根选择优先于推测性成员资格对应 experimental-composition-batch.ts 中if (first.resource first.resource root.resource) continue;以及可重复配方计数中减去根占用的逻辑。第二批layout 阶段针对实际选中集合在第二次评估中询问最终的父级插槽parent slots与同级位置sibling positions。组合树需整体校验包括深度与环再流式输出。相同位置保持目录顺序。若只有一个根、或只有一个子元素且只有单个插槽则无需第二次调用整个流程也不需要单独的 finish 调用。后续追问以当前选中 spec 走顺序编辑协议add新增、replace替换、remove删除、move/reorder移动/重排。替换与移动先选择目标第二次评估再选择合法配方或目标位置。未被要求改变的元素与早前版本保持不变。追踪trace每次评估对应一条 trace批处理 trace 使用select/layout作为操作名独立决策放在answers字段中计时与用量按每次调用计一次。provider 出错或组合布局非法时保留最后一份有效预览并报告失败。Batch 阶段的关键代码见 experimental-composition-batch.tscomposeBatch先并行发起select调用root问题 按资源分组生成的select_N问题立即组装出临时 spec 并yield snapshot()预热预览随后并行发起layout调用parent_id与order_id问题在私有克隆上完成挂载后整体validate再发布。批处理避免了每个组件一次网络往返。作为对比公共 API 也支持strategy: sequential每次只做一个操作以及现有的自定义评估器custom evaluators。值得强调的事实README 原话实验中没有完整的 UI 模板也没有生成式模型调用。示例提示按钮只填充请求文本具体包含哪些元素、顺序、分组、采用哪些动作绑定全部由 Jev 决定外观与行为由 registry 负责序列化 JSON 也不是 Jev 写的而是代码根据选择组装而成。平台必须提供什么原子候选与合成内容组件目录约束了组件名、props 与事件但字符串与数组 props 仍是开放取值。实验用平台自有内容 绑定配方来封堵这一剩余空间具体由 apps/web/lib/jev/grammar.ts 提供17 种组件类型Card、Stack、Grid、Heading、Avatar、Badge、Input、Textarea、Select、Checkbox、Switch、Button、Text、Metric、BarGraph、Table、Separator表单字段、校验规则、标签、合成个人资料与商务数据以及两个允许的目录动作formSubmit与setState。个人资料候选包含头像、显示名、角色、简介、邮箱、所在地与会员徽章全部绑定到平台提供的记录对象platformState.profile例如 Maya Chen / Product designer若干对布局 props 与按钮文案有用的取值请求中的带引号标题会被复制进额外的 Heading 候选中grammar.ts通过prompt.matchAll(/“[”]/g)抽取引号内文本与内置标题列表去重后生成heading_N候选。这些是原子元素候选atomic element candidates而非页面模板。宿主应用完全可以从自己的数据 schema、真实记录、本地化文案与允许的操作中构建同类候选——实验只是把这些值放在grammar.ts里应用则向可复用的 core API 提供自己的候选。目前不支持的场景包括同一字段在多个表单中重复出现、以及任意的全新文本/数据例如要求模型凭空编造一段话或一条新数据。每个候选同时固定了一种组件配置预置好的 revenue BarGraph 可以被选中并移动但想换成 LineGraph 就需要另一个候选。应用既可以把 props 绑定到自己的实时状态也可以按请求动态构造候选数据不必硬编码。Jev 只决定树、分组与区块顺序且只能在这些被提供的配置范围内选择。以grammar.ts中save候选为例可见候选 固定配置 动作绑定的形态add( save, Button: Save changes. Bind press to setState to update the visible saved-status text. Local demo only., Button, { label: Save changes, variant: primary, disabled: false }, action:save, { press: { action: setState, params: { statePath: /status, value: Changes saved locally. }, }, }, );候选的公共契约定义在 experimental-compose.ts 的Experimental_CompositionCandidateid、description、element仅允许type/props/on/visible即原子元素、root是否可作为根默认 true、maxUses默认 1可复用的布局元素可放大数量、resource共享同一 resource 的候选互斥。validateCandidate会对每个候选做严格校验组件必须存在于目录、props 必须通过对应 Zod schema、事件必须在该组件声明的事件列表内、动作必须命中目录actions或内置动作、回调onSuccess/onError也必须引用目录动作——这保证了模型永远无法发明组件或动作。组合器公共 API 与限制experimental_composeSpeccomposeUIapps/web/lib/jev/compose.ts是 Playground 对公共 API 的薄封装其调用即完整呈现了experimental_composeSpec的参数形态核心选项见Experimental_ComposeSpecOptionsexperimental_composeSpec({ catalog: playgroundCatalog, candidates: buildCandidates(prompt), initialSpec, // 后续追问时传入所选版本 initialState: { ...platformState, ...initialSpec?.state }, elementDescriptions: /* 仅共享展示文案 */, prompt, signal, evaluate, // experimental_createEvaluator 默认实现 maxSteps: MAX_ELEMENTS, // 14 maxElements: MAX_ELEMENTS, // 14 maxDepth: 4, context: { platform: Available: a synthetic user profile ... }, instructions: { root, next, parent }, // 应用级构造指引 });各参数的默认值与语义源码注释与校验逻辑参数默认值说明strategybatch新树默认走批处理 select/layoutsequential为一次一个操作maxElements32批处理创建的元素预算含根maxSteps32评估次数预算含顺序化的收尾决策maxDepth8根深度为 1Playground 收紧为 4initialSpec无编辑既有树克隆并校验后才参与评估elementDescriptions无显式共享给评估器的既有元素描述按元素 ID 键控initialState无写入 spec、绝不发给评估器context无显式共享给评估器的应用上下文instructions无root/next/parent三档应用级指引三个数值参数都会先经过positiveInteger校验必须是 ≥1 的安全整数strategy只能是batch或sequential候选 ID 必须匹配/^[a-zA-Z][\w-]*$/且不得为finish/unavailable。值得展开的两个设计点表达式子集组合器 V1 刻意不提供 repeat 作用域、计算函数或自定义指令。checkExpressions只允许$state、$bindState、$and、$or四种以$开头的键且$state/$bindState的值必须是状态路径字符串。因此既有的可编辑 spec 必须使用受支持的表达式子集并构成合法树。隐私边界elementDescriptions只共享定位既有元素所需的展示文案title/text/label/name/direction等字符串 props 与匹配候选的描述绝不共享原始状态、字段输入值、绑定配方、动作参数或渲染器状态。组合器的事件流是一个异步生成器每个step事件携带一棵分离拷贝detached clone的 spec 快照与单步决策choice、parent、slot、confidence、elapsedMs、inputTokenscomplete事件携带最终 spec、全部步骤、总耗时、总输入 token 与stopReasonfinish | limit | unavailable。composeUI在 complete 事件上额外估算美元成本inputTokens * 0.042 / 1e6按每百万 token $0.042 估算token 为 null 时成本也为 null。限额一览Jev 组合器把每次请求的边界写死为README 原文每个新批处理最多14 个元素每个请求最多14 次评估调用嵌套深度最多4 层单次 provider 请求最多10 秒experimental_createEvaluator的timeoutMs默认值 10000整体上限55 秒response.ts 中用AbortSignal.timeout(55000)实现与 route 的maxDuration 60呼应所选 seed初始 spec最多含100 个元素previousSpecSchema中Object.keys(elements).length 100。达到限额、被取消或出错时保留当前预览并标记为 partial部分。共享端点使用 web app 的请求频率限制器minuteRateLimit/dailyRateLimit见 api/generate/route.ts。两个模型都编辑所选版本Clear 重新开始。Stream 标签页会把构造决策与 spec 补丁并列展示。provider 调用与 spec 组装过程从不执行所选 UI 动作——动作只在真实用户交互时由运行时执行。已知局限诚实边界组合器校验树结构与候选值但不保证 Jev 选择了正确的 UI。根选择、分组、何时停止都需要规划能力而这是 Jev 有文档记载的弱点。置信度confidence会被展示但没有质量门多个布局选择可能都合理且并未校准出一个通用阈值。因此文档建议显式命名必需区块例如先要顶部的订单表再要一行 revenue/orders/customer 指标最后要周营收图表。过于简短的请求如带顶部表格的 dashboard可能只选中一张表。后续追问可以移动既有表格而无需重建其数据。推荐的追问示例用户卡片Design a user profile card→Remove the bio或Make the avatar smaller设置页Remove the email notifications switch、Change the heading to Account settings、Move the email field above the name field。服务端共享既有元素的展示标签与匹配候选的描述来识别编辑目标同样不共享原始状态与已输入的字段值。编辑保留所选 spec 的状态与 default 模型流程一致交互式预览状态不会被保存进版本历史。评估器传输层Gateway v4 实验性 evaluation 协议服务端使用 Gateway 的实验性 v4 evaluation 传输模型标识为typesafe-ai/jevexperimental-evaluator.ts。该实现已在ai-sdk/gateway4.0.85上验证通过。它用原生 fetch直连 Gateway 的 evaluation 端点从而避免升级工作区内的 AI SDK 6 依赖、也不必绕过其最小发布年龄限制。协议可能变化文档建议在适当时机迁移到符合资格的 AI SDK evaluation API 并用纯模型字符串plain model string调用。实现要点experimental_createEvaluator校验密钥与timeoutMs1 ~ 2147483647 的整数后返回一个满足Experimental_CompositionEvaluator签名的异步函数请求体为{ state, questions }请求头携带Authorization: Bearer apiKey、ai-gateway-protocol-version: 0.0.1、ai-gateway-auth-method: api-key、ai-evaluation-model-specification-version: 4、ai-model-id: typesafe-ai/jev。响应经 Zod schema 严格解析answers中每个问题必须是{ type: choice, choice }且 choice 必须落在该问题的 criteria 键内置信度来自providerMetadata.typesafe.confidence0~1usage.inputTokens为非负整数。任何越界选择都会抛错从而保证评估器无法输出超出候选集的操作。组合器侧还有evaluateWithSignal兜底即使自定义评估器忽略 abort 信号也会用Promise.race强制中止。评估器的自定义替换能力意味着应用可以不依赖 Gateway只要实现(request: { state, questions, signal }) Promise{ answers, usage? }即可接入任意后端或本地评估逻辑测试即用 scripted 假评估器完成。文件地图与验证命令实验相关文件相对仓库根目录apps/web/lib/jev/grammar.tsPlayground 自有的取值与原子候选packages/core/src/experimental-compose.ts公共、与 provider 无关的组合器packages/core/src/experimental-composition-batch.ts新树的并行成员资格与布局决策packages/core/src/experimental-composition-tree.ts内部 seed 校验与树编辑辅助attach/detach/replaceElement/indexTree 等packages/core/src/experimental-evaluator.ts公共 Gateway 评估器适配器apps/web/lib/jev/compose.ts带 Playground 指令与成本展示的公共 API 消费方apps/web/app/api/generate/route.ts共享的频率受限端点按所选模型分发model typesafe-ai/jev时走createCompositionResponse否则走 default 模型apps/web/lib/jev/response.ts把组合快照适配为 Playground 的 JSONL spec 补丁与决策元数据__meta: decision/__meta: composition/__meta: errorapps/web/components/playground.tsx共享的模型切换、实验信息 tooltip、提示输入、版本历史、实时预览与检查器apps/web/lib/jev/compose.test.ts覆盖结构、动作边界、未知用量、取消与限额的测试。运行验证仓库根目录pnpm exec vitest run packages/core/src/experimental-compose.test.ts packages/core/src/experimental-evaluator.test.ts apps/web/lib/jev/compose.test.ts pnpm type-checkcompose.test.ts用scripted假评估器按脚本依次返回next/parent选择既验证了批处理路径root/select_*/order_*/parent_*问题的应答组装也验证了顺序编辑路径add/replace/remove/move 的决策消耗。对应用接入的启示Jev 组合实验示范了一条与自由生成 JSON spec截然不同的路线把生成问题转化为有限选择问题。应用若要把这类组合器接入自己的产品核心要点可归纳为目录是硬边界组件、props、事件、动作必须全部在 catalog 中声明模型无法越界候选是内容载体真实数据、本地化文案与允许操作都应预构造成原子候选可绑定 live state也可按请求动态生成模型不发明文本与数据两阶段批处理省往返select 并行决定成员资格layout 并行决定挂载点与顺序均按一次调用计费编辑协议是顺序的add 之外replace/move 采用先选目标、再选方案的两段式决策remove 直接删除子树未触达元素保持原样安全与隐私默认成立provider 调用与组装过程不执行任何 UI 动作状态不进评估器共享给模型的只有描述性文案experimental_API 可在任何版本中变化文档明确要求接入方锁定精确版本pin exact versions。对希望从源码继续深入研究的读者建议从 packages/core/src/experimental-compose.ts 的experimental_composeSpec入口读起依次对照 experimental-composition-batch.ts 与 experimental-composition-tree.ts最后用 apps/web/lib/jev/compose.test.ts 中的脚本化评估器反推每一步的状态机行为。【免费下载链接】json-renderThe Generative UI framework项目地址: https://gitcode.com/GitHub_Trending/js/json-render创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考