生成式 UI 的 Prompt 链设计从需求描述到多组件页面的一次性生成一、生成式 UI 的核心挑战生成式 UI 指的是通过自然语言描述直接产出可运行的前端界面。与生成单一代码片段不同一个完整的页面通常包含多个异构组件表单、表格、图表、导航它们之间存在数据流依赖和布局约束。单一 prompt 难以覆盖所有细节容易产生布局错乱、数据绑定缺失或组件冲突。解决思路是将生成过程拆分为一条Prompt 链——多个职责明确的子 prompt 按序执行前一个环节的产出作为后一个环节的输入约束。这类似于编译器的多阶段处理词法分析、语法分析、语义分析、代码生成层层递进每一步缩小不确定性。二、Prompt 链的五阶段架构flowchart TB A[用户需求描述] -- B[阶段1: 需求解析] B -- C[结构化页面描述 JSON] C -- D[阶段2: 布局规划] D -- E[布局树 组件清单] E -- F[阶段3: 组件生成] F -- G[独立组件代码片段] G -- H[阶段4: 数据流绑定] H -- I[组件间状态/通信代码] I -- J[阶段5: 组装与校验] J -- K[完整可运行页面] K -- L{编译校验} L --|通过| M[输出页面] L --|失败| N[错误反馈] N -- B2.1 阶段一需求解析将自然语言转化为结构化的页面描述消除歧义。# prompt_chain/stage1_parse.py import json from typing import Optional STAGE1_SYSTEM_PROMPT 你是一个前端需求分析师。将用户的自然语言需求解析为结构化的页面描述。 输出必须为严格 JSON 格式不包含代码块标记。 STAGE1_USER_TEMPLATE 用户需求 {user_input} 请输出以下 JSON 结构 {{ pageTitle: 页面标题, description: 页面功能描述, components: [ {{ id: 唯一标识, type: 组件类型(form/table/chart/nav/card/list/other), description: 组件功能, dataSource: 数据来源描述, interactions: [交互行为1, 交互行为2] }} ], dataFlow: [ {{ from: 源组件id, to: 目标组件id, trigger: 触发事件, description: 数据传递描述 }} ] }} def parse_requirement(user_input: str, llm_call) - dict: 将用户需求解析为结构化描述。 Args: user_input: 用户的自然语言需求 llm_call: LLM 调用函数 Returns: 结构化的页面描述字典 Raises: ValueError: 解析结果不符合预期结构时 prompt STAGE1_USER_TEMPLATE.format(user_inputuser_input) response llm_call( systemSTAGE1_SYSTEM_PROMPT, userprompt, temperature0.1, # 低温度保证输出稳定 ) try: parsed json.loads(response) except json.JSONDecodeError as e: raise ValueError(f阶段一输出非法 JSON: {e}) required_keys {pageTitle, components, dataFlow} missing required_keys - set(parsed.keys()) if missing: raise ValueError(f阶段一输出缺少必要字段: {missing}) return parsed2.2 阶段二布局规划基于组件清单生成响应式布局方案。# prompt_chain/stage2_layout.py STAGE2_SYSTEM_PROMPT 你是一个前端布局架构师。根据组件清单输出响应式布局方案。 使用 CSS Grid 或 Flexbox 语义描述。输出严格 JSON。 def plan_layout(page_desc: dict, llm_call) - dict: 根据组件清单规划布局结构。 Args: page_desc: 阶段一的页面描述 llm_call: LLM 调用函数 Returns: 包含 grid 定义和组件位置映射的布局方案 components_summary [] for comp in page_desc[components]: components_summary.append({ id: comp[id], type: comp[type], weight: primary if comp[type] in (table, chart) else secondary, }) prompt f组件清单 {json.dumps(components_summary, ensure_asciiFalse, indent2)} 输出布局方案 JSON {{ layout: {{ type: grid, columns: 响应式列定义, areas: [ {{name: 区域名, components: [组件id], span: 列跨数}} ] }} }} response llm_call( systemSTAGE2_SYSTEM_PROMPT, userprompt, temperature0.2, ) try: return json.loads(response) except json.JSONDecodeError as e: raise ValueError(f阶段二输出非法 JSON: {e})2.3 阶段三至五组件生成、数据绑定与组装阶段三的组件生成是整条链中代码量最大的环节。与直接从零生成组件不同Prompt 链的优势在于此时已具备完整的上下文——页面描述、布局方案和组件清单。模型可以精确知道当前组件在页面中的位置、它与哪些组件存在数据交互、它的数据源是什么。这些约束条件极大降低了模型自由发挥带来的不确定性。生成过程中需要特别注意两个细节一是组件代码的独立性——每个组件函数应当是自包含的不依赖外部闭包变量二是类型定义的完整性——必须为 Props 输出完整的 TypeScript 接口这是后续阶段四数据绑定和阶段五编译校验的基础。阶段四的数据绑定是出错率最高的环节。问题通常出在两个地方跨组件状态提升的层级判断错误本应提升到父组件的状态被放在了兄弟组件内部以及回调函数签名不匹配源组件触发的事件参数与目标组件期望的不一致。实践中发现在阶段四的 prompt 中显式列出每个数据流的触发事件名和参数类型能将绑定正确率从约 70% 提升至 90% 以上。阶段五的组装与校验是质量把关的最后一道防线。除了基础的 TypeScript 编译检查外建议增加 ESLint 规则校验和如果条件允许基于 Playwright 的端到端截图对比。编译通过只是语法正确截图对比才能验证布局和样式是否与设计预期一致。对于校验失败的情况错误信息应当被结构化地反馈回阶段一或阶段三形成自动修正的闭环。# prompt_chain/stage3_component.py STAGE3_SYSTEM_PROMPT 你是 React TypeScript 前端组件开发专家。 生成生产级别的组件代码包含完整的 Props 类型定义、错误处理和中文注释。 def generate_component( comp_desc: dict, layout_info: dict, llm_call ) - str: 生成单个组件代码。 Args: comp_desc: 组件描述来自阶段一 layout_info: 布局信息来自阶段二 llm_call: LLM 调用函数 Returns: 组件的 React TSX 代码 prompt f请生成以下组件的 React TypeScript 代码 组件信息 - ID: {comp_desc[id]} - 类型: {comp_desc[type]} - 描述: {comp_desc[description]} - 数据源: {comp_desc.get(dataSource, 无)} - 交互: {json.dumps(comp_desc.get(interactions, []), ensure_asciiFalse)} 布局约束组件位于 {layout_info} 区域 要求 1. 使用函数组件 Hooks 2. 包含 Props 的 TypeScript 接口定义 3. 数据加载须有 loading/error 状态处理 4. 关键逻辑添加中文注释 5. 只输出组件代码不包含 import 或 export code llm_call( systemSTAGE3_SYSTEM_PROMPT, userprompt, temperature0.3, max_tokens4096, ) return code三、数据绑定与状态管理组件之间的数据流在阶段四处理。这是生成式 UI 最难的一环——单一组件很容易生成但多个组件的协同关系容易出错。难点主要集中在三个方面首先模型需要理解筛选条件变更 → 表格数据刷新这类间接因果关系而非简单的父子传值其次对于表单提交这类涉及多组件数据聚合的场景模型容易将状态分散在多个组件内部导致提交流程中的数据不一致最后异步数据流如 API 请求的 loading/error/success 三态的处理逻辑容易被模型简化或遗漏。为缓解这些问题阶段四的 prompt 设计了三个关键策略。第一要求模型显式声明全局状态变量而非隐式推导从源头减少歧义。第二数据流的描述必须包含触发事件和参数类型强制模型关注接口契约。第三为每个数据绑定生成双向的实现代码——既包含源组件触发 → 目标组件响应的正向链路也包含目标组件加载完成 → 通知源组件的反向确认覆盖数据交互的完整生命周期。# prompt_chain/stage4_databind.py def generate_data_bindings( components: list, data_flows: list, llm_call ) - dict: 生成组件间的数据绑定代码。 为每个数据流生成状态声明、回调函数和 prop 传递代码。 flows_desc json.dumps(data_flows, ensure_asciiFalse, indent2) comps_desc json.dumps( [{id: c[id], type: c[type]} for c in components], ensure_asciiFalse, ) prompt f组件列表{comps_desc} 数据流定义{flows_desc} 请生成以下内容JSON 格式 {{ globalState: {{ 变量名: {{type: 类型, initialValue: 初始值}} }}, eventHandlers: [ {{ name: 处理函数名, source: 源组件id, target: 目标组件id, implementation: 处理逻辑的完整代码 }} ], componentWiring: [ {{ componentId: 组件id, props: {{prop名: 数据来源或表达式}} }} ] }} response llm_call( system你是前端状态管理专家。, userprompt, temperature0.2, ) return json.loads(response)四、组装与校验阶段# prompt_chain/stage5_assemble.py import subprocess import tempfile import os def assemble_and_validate( components_code: dict, bindings: dict, page_desc: dict, layout: dict, ) - dict: 组装完整页面并执行编译校验。 将各组件代码、数据绑定和布局方案拼接为完整的 .tsx 文件 通过 tsc 进行类型校验。 imports_block import React, { useState, useEffect, useCallback } from react; # 组装各组件代码 components_block for comp_id, code in components_code.items(): components_block f\n// 组件: {comp_id} \n{code}\n # 组装主页面 page_block f // 主页面: {page_desc[pageTitle]} export default function GeneratedPage() {{ const [loading, setLoading] useState(false); const [error, setError] useStatestring | null(null); return ( div classNamegenerated-page {/* 布局和组件在此组装 */} /div ); }} full_code imports_block components_block page_block # 写入临时文件进行类型检查 with tempfile.NamedTemporaryFile( modew, suffix.tsx, deleteFalse ) as f: f.write(full_code) temp_path f.name try: result subprocess.run( [npx, tsc, --noEmit, --strict, temp_path], capture_outputTrue, textTrue, timeout30, ) if result.returncode ! 0: return { success: False, code: full_code, errors: result.stderr[-2000:], # 截取最后 2000 字符 } return {success: True, code: full_code, errors: None} except subprocess.TimeoutExpired: return { success: False, code: full_code, errors: 类型检查超时30秒, } finally: os.unlink(temp_path)五、总结Prompt 链的核心思想是将一个复杂生成任务分解为多个环环相扣的步骤每步处理一个可控的子问题。五个阶段各司其职需求解析消除歧义、布局规划确定骨架、组件生成落代码、数据绑定建立通信、组装校验把质量关。当前方案仍有局限复杂交互如拖拽排序、实时协同的生成质量不稳定跨组件共享状态的自动推断准确率约 70%。后续优化的方向包括引入矢量化的组件库索引提升匹配精度、在阶段五增加端到端的截图对比作为第二道校验屏障。生成式 UI 离输入需求即出页面还有距离但通过工程化的 Prompt 链设计这条路的方向是清晰的。