AI 原型生成:从 PRD 到可交互前端的自动化验证闭环

📅 2026/7/23 12:18:28
AI 原型生成:从 PRD 到可交互前端的自动化验证闭环
AI 原型生成从 PRD 到可交互前端的自动化验证闭环出行平台产品迭代中PRD 到可交互原型的距离常常是 2~3 周。本文复盘我们如何用 AI 原型引擎将这个周期压缩至 48 小时并建立从需求解析、组件编排到交互验证的自动化闭环。一、问题定义PRD 到原型为什么这么慢出行平台的产品迭代节奏快——每周至少 3 个新需求进入开发管线。但在过去 6 个月的数据统计中PRD 定稿到前端交付可交互原型平均耗时14.3 个工作日。拆解这个周期的瓶颈阶段平均耗时占比核心瓶颈PRD 解读与需求澄清2.1 天14.7%产品与技术对需求理解偏差交互设计稿出图4.5 天31.5%设计师排期、样式细节迭代组件选型与页面搭建3.8 天26.6%组件库查找、配置参数调试交互逻辑与状态绑定2.9 天20.1%表单联动、路由跳转、数据Mock联调验收与反馈修改1.0 天7.0%产品验收走查、细节修正数据表明68.1% 的时间消耗在解读→出图→搭建三段而这三段恰恰是结构化程度最高、最适合 AI介入的环节。核心假设如果 AI 能从 PRD 文本中自动提取页面结构、组件配置和交互逻辑并基于已有组件库生成可交互原型那么 PRD 到可交互原型的周期可以从 14.3 天压缩到 2 天以内。二、架构设计PRD 到原型的三层解析引擎我们将 AI 原型生成拆解为三层需求解析层、组件编排层、交互验证层。每层都有明确的输入输出契约和降级兜底机制。2.1 需求解析层从自然语言到结构化页面模型// prd-parser.ts — PRD 文本到结构化页面模型的解析引擎 /** 页面模型AI 从 PRD 中提取的结构化描述 */ interface PageModel { pageId: string; pageName: string; route: string; sections: SectionModel[]; interactions: InteractionSpec[]; dataRequirements: DataFieldSpec[]; priority: p0 | p1 | p2; } /** 页面区块模型 */ interface SectionModel { sectionId: string; sectionType: header | card-list | form | map | timeline | tab-panel | table; title: string; fields: FieldSpec[]; layoutHint?: grid-2 | grid-3 | full-width | sidebar-main; } /** 字段规格 */ interface FieldSpec { fieldName: string; fieldType: text | number | select | date | location | status | avatar; label: string; required: boolean; validationRule?: string; dataSource?: string; } /** 交互规格 */ interface InteractionSpec { trigger: click | input | scroll | timer | websocket; source: string; action: navigate | submit | filter | toggle | refresh | modal; target: string; condition?: string; } /** 数据字段需求 */ interface DataFieldSpec { entity: string; fields: string[]; mockStrategy: static | api-fallback | ai-generated; } /** * PRD解析引擎 * 三级降级策略AI语义解析 → 规则正则提取 → 手动模板兜底 */ class PRDParser { private aiClient: AIClient; private regexExtractor: RegexExtractor; private templateFallback: TemplateFallback; private confidenceThreshold 0.75; /** * 解析PRD文本输出结构化页面模型 * param prdText PRD原始文本 * param context 项目上下文已有页面列表、组件库版本等 * returns 解析结果及置信度 */ async parse(prdText: string, context: ProjectContext): PromiseParseResult { // 第一级AI语义解析 const aiResult await this.aiSemanticParse(prdText, context); if (aiResult.confidence this.confidenceThreshold) { return aiResult; } // 第二级规则正则提取置信度不足时降级 console.warn(AI解析置信度 ${aiResult.confidence} 低于阈值降级为正则提取); const regexResult this.regexExtractor.extract(prdText, context); if (regexResult.confidence 0.5) { // 合并AI与正则结果取高置信度字段 return this.mergeResults(aiResult, regexResult); } // 第三级手动模板兜底正则也无法覆盖时 console.error(正则提取置信度 ${regexResult.confidence} 过低降级为模板兜底); return this.templateFallback.generate(prdText, context); } /** AI语义解析将PRD文本送入大模型输出结构化JSON */ private async aiSemanticParse( prdText: string, context: ProjectContext ): PromiseParseResult { const prompt this.buildParsePrompt(prdText, context); try { const response await this.aiClient.chat(prompt, { responseFormat: json, temperature: 0.1, // 低温度保证结构化输出的稳定性 maxTokens: 4096, }); const models: PageModel[] JSON.parse(response.content); const confidence this.calculateConfidence(models, prdText); return { models, confidence, source: ai-semantic }; } catch (error) { console.error(AI语义解析失败:, error instanceof Error ? error.message : String(error)); return { models: [], confidence: 0, source: ai-semantic-failed }; } } /** 构建解析提示词注入组件库信息和项目上下文 */ private buildParsePrompt(prdText: string, context: ProjectContext): string { return [ 你是一个出行平台的前端架构师。请从以下PRD文本中提取页面结构。, 输出格式JSON数组每个元素符合PageModel结构。, , ## 项目上下文, - 已有页面${context.existingPages.join(, )}, - 组件库版本${context.componentLibVersion}, - 可用区块类型header, card-list, form, map, timeline, tab-panel, table, , ## PRD文本, prdText, , ## 提取规则, 1. 每个页面必须包含route和至少一个section, 2. 字段类型必须是预定义的FieldType之一, 3. 交互动作必须是预定义的ActionType之一, 4. 每个section的fields数量不超过8个, 5. 标注每个提取字段的置信度(0~1), ].join(\n); } /** 计算解析置信度验证提取结果与PRD原文的覆盖率 */ private calculateConfidence(models: PageModel[], prdText: string): number { if (models.length 0) return 0; // 提取PRD中所有关键名词 const prdKeywords this.extractKeywords(prdText); // 提取模型中所有字段名和标签 const modelKeywords models.flatMap(m m.sections.flatMap(s s.fields.map(f f.fieldName f.label)) ); // 覆盖率 模型覆盖的关键词比例 const coverage prdKeywords.filter(k modelKeywords.some(mk mk.includes(k) || k.includes(mk)) ).length / prdKeywords.length; // 结构完整度 每个页面至少1个section且有route的比例 const structuralValidity models.filter(m m.sections.length 0 m.route.length 0 ).length / models.length; return Math.min(coverage * 0.6 structuralValidity * 0.4, 1.0); } /** 合并AI与正则提取结果 */ private mergeResults(ai: ParseResult, regex: ParseResult): ParseResult { // 对每个页面取置信度更高的来源 const mergedModels: PageModel[] []; const aiMap new Map(ai.models.map(m [m.pageId, m])); const regexMap new Map(regex.models.map(m [m.pageId, m])); // 合并所有页面ID const allPageIds new Set([...aiMap.keys(), ...regexMap.keys()]); for (const pageId of allPageIds) { const aiModel aiMap.get(pageId); const regexModel regexMap.get(pageId); if (aiModel regexModel) { // 两者都有合并sections优先AI的高置信度字段 mergedModels.push(this.mergePageModels(aiModel, regexModel)); } else { mergedModels.push(aiModel || regexModel!); } } return { models: mergedModels, confidence: (ai.confidence regex.confidence) / 2, source: merged, }; } /** 合并两个页面模型字段级置信度选择 */ private mergePageModels(ai: PageModel, regex: PageModel): PageModel { // AI版本的sections优先补充regex中AI未提取的sections const aiSectionIds new Set(ai.sections.map(s s.sectionId)); const extraSections regex.sections.filter(s !aiSectionIds.has(s.sectionId)); return { ...ai, sections: [...ai.sections, ...extraSections], interactions: [...ai.interactions, ...regex.interactions.filter( i !ai.interactions.some(aiI aiI.trigger i.trigger aiI.source i.source) )], }; } private extractKeywords(text: string): string[] { // 简化的关键词提取过滤停用词后取名词 const stopWords [的, 了, 在, 是, 和, 与, 或, 不, 要, 可以]; return text.split(/\s/) .filter(w w.length 2 !stopWords.includes(w)) .slice(0, 50); // 取前50个关键词 } } interface ParseResult { models: PageModel[]; confidence: number; source: string; } interface ProjectContext { existingPages: string[]; componentLibVersion: string; }2.2 组件编排层结构化模型到可渲染页面// component-orchestrator.ts — 从PageModel到可渲染组件树的编排引擎 /** 组件树节点 */ interface ComponentNode { componentType: string; props: Recordstring, unknown; children?: ComponentNode[]; slotBindings?: Recordstring, ComponentNode[]; dataBindings: DataBinding[]; eventBindings: EventBinding[]; } /** 数据绑定 */ interface DataBinding { propPath: string; dataSource: mock | api | state; dataKey: string; transformer?: string; } /** 事件绑定 */ interface EventBinding { eventName: string; interaction: InteractionSpec; handlerCode?: string; } /** 编排结果 */ interface OrchestrationResult { componentTree: ComponentNode; mockData: Recordstring, unknown; routeConfig: RouteConfig; estimatedRenderTime: number; } /** * 组件编排引擎 * 将PageModel转换为可渲染的组件树 Mock数据 路由配置 */ class ComponentOrchestrator { // 区块类型到组件类型的映射表 private sectionComponentMap: Recordstring, string { header: PageHeader, card-list: CardList, form: DynamicForm, map: MapView, timeline: OrderTimeline, tab-panel: TabPanel, table: DataTable, }; // 字段类型到表单组件的映射表 private fieldComponentMap: Recordstring, string { text: TextInput, number: NumberInput, select: SelectDropdown, date: DatePicker, location: LocationPicker, status: StatusTag, avatar: Avatar, }; /** * 将PageModel编排为可渲染组件树 * param model 需求解析层输出的页面模型 * param componentRegistry 组件库注册信息 */ orchestrate(model: PageModel, componentRegistry: ComponentRegistry): OrchestrationResult { const children: ComponentNode[] []; // 逐个section编排为组件节点 for (const section of model.sections) { const componentType this.resolveComponentType(section.sectionType, componentRegistry); const props this.buildSectionProps(section); const fieldNodes this.buildFieldNodes(section.fields); children.push({ componentType, props, children: fieldNodes, dataBindings: this.buildDataBindings(section), eventBindings: this.buildEventBindings(section, model.interactions), }); } // 构建页面根节点 const root: ComponentNode { componentType: PageLayout, props: { pageName: model.pageName, layout: this.inferLayout(model) }, children, dataBindings: [], eventBindings: [], }; // 生成Mock数据 const mockData this.generateMockData(model.dataRequirements); // 生成路由配置 const routeConfig this.buildRouteConfig(model); // 估算渲染时间基于组件节点数量 const estimatedRenderTime this.estimateRenderTime(root); return { componentTree: root, mockData, routeConfig, estimatedRenderTime }; } /** 解析区块类型到实际组件类型 */ private resolveComponentType( sectionType: string, registry: ComponentRegistry ): string { const mapped this.sectionComponentMap[sectionType]; if (!mapped) { console.warn(未知区块类型 ${sectionType}降级为通用容器); return GenericContainer; } // 检查组件库是否注册了该组件 if (!registry.has(mapped)) { console.warn(组件 ${mapped} 未在组件库注册降级为 GenericContainer); return GenericContainer; } return mapped; } /** 构建section级别的props */ private buildSectionProps(section: SectionModel): Recordstring, unknown { const props: Recordstring, unknown { title: section.title, sectionId: section.sectionId, }; if (section.layoutHint) { props.layout section.layoutHint; } // 区块类型特有props if (section.sectionType form) { props.submitText 提交; props.layout section.layoutHint || vertical; } else if (section.sectionType table) { props.rowKey section.fields[0]?.fieldName || id; props.pagination { pageSize: 20 }; } else if (section.sectionType card-list) { props.cardLayout section.layoutHint || grid-2; } return props; } /** 构建字段级别的子组件节点 */ private buildFieldNodes(fields: FieldSpec[]): ComponentNode[] { return fields.map(field ({ componentType: this.fieldComponentMap[field.fieldType] || TextDisplay, props: { label: field.label, fieldName: field.fieldName, required: field.required, placeholder: 请输入${field.label}, ...(field.validationRule ? { validation: field.validationRule } : {}), }, dataBindings: [{ propPath: value, dataSource: mock as const, dataKey: field.fieldName, }], eventBindings: [], })); } /** 构建数据绑定 */ private buildDataBindings(section: SectionModel): DataBinding[] { return section.fields.map(field ({ propPath: data.${field.fieldName}, dataSource: field.dataSource || mock, dataKey: field.fieldName, transformer: this.getTransformer(field.fieldType), })); } /** 构建事件绑定将交互规格映射为事件处理器 */ private buildEventBindings( section: SectionModel, interactions: InteractionSpec[] ): EventBinding[] { return interactions .filter(i i.source section.sectionId || i.source.startsWith(section.sectionId .)) .map(i ({ eventName: this.mapTriggerToEvent(i.trigger), interaction: i, handlerCode: this.generateHandlerStub(i), })); } /** 触发类型到DOM事件的映射 */ private mapTriggerToEvent(trigger: string): string { const map: Recordstring, string { click: onClick, input: onChange, scroll: onScroll, timer: onTimer, websocket: onWsMessage, }; return map[trigger] || onClick; } /** 生成交互处理的代码骨架 */ private generateHandlerStub(interaction: InteractionSpec): string { switch (interaction.action) { case navigate: return navigate(${interaction.target}${interaction.condition ? , { state: ${interaction.condition} } : }); case submit: return handleSubmit(formData); case modal: return openModal(${interaction.target}); case filter: return setFilter({ ${interaction.target}: value }); case refresh: return refreshData(${interaction.target}); default: return handleAction(${interaction.action}, ${interaction.target}); } } /** 推断页面整体布局 */ private inferLayout(model: PageModel): string { const hasMap model.sections.some(s s.sectionType map); const hasForm model.sections.some(s s.sectionType form); const hasSidebar model.sections.some(s s.layoutHint sidebar-main); if (hasMap) return map-detail; // 地图详情的出行平台经典布局 if (hasSidebar) return sidebar-layout; if (hasForm) return form-centered; return standard-stack; } /** 生成Mock数据 */ private generateMockData(requirements: DataFieldSpec[]): Recordstring, unknown { const mockData: Recordstring, unknown {}; for (const req of requirements) { mockData[req.entity] this.mockEntity(req.entity, req.fields, req.mockStrategy); } return mockData; } /** 模拟实体数据 */ private mockEntity( entity: string, fields: string[], strategy: string ): Recordstring, unknown { // 出行平台常见实体的预设Mock数据 const presets: Recordstring, Recordstring, unknown { trip: { id: TRP-20260723-001, status: in_progress, pickupLocation: 朝阳区望京SOHO, destination: 海淀区中关村软件园, estimatedTime: 23分钟, fare: 28.5, driverName: 张师傅, driverAvatar: /mock/driver-avatar.png, }, order: { id: ORD-20260723-042, type: express, createTime: 2026-07-23T14:30:00, status: pending, amount: 15.8, }, }; if (presets[entity]) { // 预设数据按需过滤字段 const preset presets[entity]; if (fields.length 0) { const filtered: Recordstring, unknown {}; for (const f of fields) { filtered[f] preset[f] ?? mock_${f}; } return filtered; } return preset; } // 无预设按字段名自动生成 const autoMock: Recordstring, unknown {}; for (const field of fields) { autoMock[field] this.autoMockValue(field); } return autoMock; } /** 根据字段名自动推断Mock值 */ private autoMockValue(fieldName: string): unknown { if (fieldName.includes(id)) return MOCK-${Date.now()}; if (fieldName.includes(name)) return 示例名称; if (fieldName.includes(time) || fieldName.includes(date)) return 2026-07-23; if (fieldName.includes(status)) return active; if (fieldName.includes(amount) || fieldName.includes(price) || fieldName.includes(fare)) return 99.9; if (fieldName.includes(location) || fieldName.includes(address)) return 北京市朝阳区; if (fieldName.includes(count) || fieldName.includes(num)) return 5; return 示例数据; } /** 字段类型转换器映射 */ private getTransformer(fieldType: string): string | undefined { const transformers: Recordstring, string { date: formatDate, number: formatCurrency, status: mapStatusTag, location: formatAddress, }; return transformers[fieldType]; } /** 构建路由配置 */ private buildRouteConfig(model: PageModel): RouteConfig { return { path: model.route, name: model.pageName, component: ./pages/${model.pageId}/index.tsx, meta: { title: model.pageName, priority: model.priority }, }; } /** 估算页面渲染时间 */ private estimateRenderTime(root: ComponentNode): number { let nodeCount 1; const countNodes (node: ComponentNode) { nodeCount; node.children?.forEach(countNodes); }; root.children?.forEach(countNodes); // 基线单个组件渲染约8ms递增开销约3ms/节点 return Math.round(nodeCount * 8 nodeCount * 3); } } interface ComponentRegistry { has(componentName: string): boolean; get(componentName: string): ComponentMeta; } interface ComponentMeta { name: string; version: string; propsSchema: Recordstring, unknown; } interface RouteConfig { path: string; name: string; component: string; meta: Recordstring, unknown; }三、交互验证层AI生成的原型如何确保可用组件编排层输出的是静态结构交互验证层负责将骨架变为活体——自动绑定交互逻辑、注入Mock数据流、生成可点击的原型页面。// interaction-validator.ts — 交互逻辑生成与验证引擎 /** 交互验证结果 */ interface ValidationReport { totalInteractions: number; validated: number; warnings: InteractionWarning[]; coverageScore: number; // 交互覆盖率 0~1 lighthouseScore: number; // 预估Lighthouse性能分 } interface InteractionWarning { interactionId: string; type: missing-handler | dead-end | state-conflict | unsupported; message: string; suggestion: string; } /** * 交互验证引擎 * 验证AI生成的交互逻辑是否闭环检测断路和状态冲突 */ class InteractionValidator { /** * 验证页面模型的交互完整性 * param model 页面模型 * param orchestration 组件编排结果 * returns 验证报告 */ validate(model: PageModel, orchestration: OrchestrationResult): ValidationReport { const warnings: InteractionWarning[] []; const validatedInteractions: string[] []; // 1. 检查每个交互是否有对应的处理器 for (const interaction of model.interactions) { const id ${interaction.trigger}:${interaction.source}→${interaction.action}:${interaction.target}; // 查找编排结果中的事件绑定 const binding this.findEventBinding(orchestration.componentTree, interaction); if (!binding) { warnings.push({ interactionId: id, type: missing-handler, message: 交互 ${id} 在组件树中未找到对应的事件绑定, suggestion: 建议在 ${interaction.source} 组件上添加 ${this.mapTriggerToEvent(interaction.trigger)} 处理器, }); continue; } validatedInteractions.push(id); } // 2. 检查导航目标是否存在避免死链 for (const interaction of model.interactions) { if (interaction.action navigate) { const targetRoute interaction.target; // 检查目标路由是否在当前PRD的页面列表或已有路由中 if (!this.isRouteReachable(targetRoute, model)) { warnings.push({ interactionId: ${interaction.source}→navigate:${targetRoute}, type: dead-end, message: 导航目标 ${targetRoute} 在当前页面集合中不存在, suggestion: 添加目标页面模型或改用modal交互, }); } } } // 3. 检查状态冲突同一触发源上的多个交互是否互斥 const sourceGroups this.groupBySource(model.interactions); for (const [source, interactions] of sourceGroups) { const conflicts this.findConflicts(interactions); for (const conflict of conflicts) { warnings.push({ interactionId: conflict:${source}, type: state-conflict, message: 触发源 ${source} 上存在互斥交互${conflict.map(i i.action).join( vs )}, suggestion: 添加条件判断condition字段区分互斥交互, }); } } // 4. 计算覆盖率 const coverageScore validatedInteractions.length / model.interactions.length; // 5. 估算Lighthouse性能分基于组件节点数和渲染时间 const lighthouseScore this.estimateLighthouse(orchestration.estimatedRenderTime); return { totalInteractions: model.interactions.length, validated: validatedInteractions.length, warnings, coverageScore, lighthouseScore, }; } /** 在组件树中查找对应的事件绑定 */ private findEventBinding( tree: ComponentNode, interaction: InteractionSpec ): EventBinding | undefined { const search (node: ComponentNode): EventBinding | undefined { // 检查当前节点的事件绑定 const found node.eventBindings.find(b b.interaction.source interaction.source b.interaction.action interaction.action ); if (found) return found; // 递归搜索子节点 return node.children?.find(search) ?? undefined; }; return search(tree); } /** 检查路由可达性 */ private isRouteReachable(targetRoute: string, model: PageModel): boolean { // 同一PRD中的其他页面 if (model.route targetRoute) return true; // 实际项目中会有全局路由表此处简化为仅检查当前模型 return targetRoute.startsWith(/); // 简化判断有效路由路径格式 } /** 按触发源分组交互 */ private groupBySource(interactions: InteractionSpec[]): Mapstring, InteractionSpec[] { const groups new Mapstring, InteractionSpec[](); for (const i of interactions) { const list groups.get(i.source) || []; list.push(i); groups.set(i.source, list); } return groups; } /** 查找互斥交互 */ private findConflicts(interactions: InteractionSpec[]): InteractionSpec[][] { const conflicts: InteractionSpec[][] []; // 同一触发源上、同一触发类型的多个无条件交互视为互斥 const byTrigger new Mapstring, InteractionSpec[](); for (const i of interactions) { if (!i.condition) { const list byTrigger.get(i.trigger) || []; list.push(i); byTrigger.set(i.trigger, list); } } for (const [, group] of byTrigger) { if (group.length 1) conflicts.push(group); } return conflicts; } /** 估算Lighthouse性能分 */ private estimateLighthouse(renderTimeMs: number): number { // 简化模型渲染时间100ms对应90分500ms对应50分 if (renderTimeMs 100) return 95; if (renderTimeMs 200) return 85; if (renderTimeMs 300) return 70; if (renderTimeMs 500) return 55; return 40; } private mapTriggerToEvent(trigger: string): string { const map: Recordstring, string { click: onClick, input: onChange, scroll: onScroll, }; return map[trigger] || onClick; } }四、校准闭环人机协同的质量保证AI生成的原型不能直接交付需要产品经理和技术负责人共同校准。我们设计了一个校准界面——将AI推断的理由、置信度和替代方案可视化呈现让校准过程从全量审查变为差异确认。// calibration-loop.ts — 人机校准闭环管理器 /** 校准任务 */ interface CalibrationTask { taskId: string; pageModel: PageModel; orchestration: OrchestrationResult; validation: ValidationReport; calibrationItems: CalibrationItem[]; status: pending | in-review | confirmed | rejected; assignee: string; deadline: Date; } /** 校准项需要人工确认的AI决策 */ interface CalibrationItem { itemId: string; category: component-selection | layout-inference | interaction-binding | data-mapping; aiDecision: string; // AI的推断结果 aiReason: string; // AI推断的理由 confidence: number; // 置信度 0~1 alternatives: string[]; // 替代方案列表 humanDecision?: string; // 人工确认后的决策 comment?: string; // 人工备注 } /** * 校准闭环管理器 * 将AI低置信度决策暴露为校准项驱动人机协同 */ class CalibrationLoopManager { private confidenceThreshold 0.85; // 高于此阈值的决策自动通过 /** * 从编排结果中提取需要人工校准的决策项 * param model 页面模型 * param orchestration 编排结果 * param validation 验证报告 */ extractCalibrationItems( model: PageModel, orchestration: OrchestrationResult, validation: ValidationReport ): CalibrationItem[] { const items: CalibrationItem[] []; // 1. 低置信度的区块类型选择 for (const section of model.sections) { const mappedComponent this.getSectionComponentMap()[section.sectionType]; if (!mappedComponent) { items.push({ itemId: comp-${section.sectionId}, category: component-selection, aiDecision: GenericContainer, aiReason: 区块类型 ${section.sectionType} 无预定义映射降级为通用容器, confidence: 0.3, alternatives: [CardList, TabPanel, 自定义组件], }); } } // 2. 低置信度的布局推断 const layoutConfidence this.assessLayoutConfidence(model); if (layoutConfidence this.confidenceThreshold) { items.push({ itemId: layout-${model.pageId}, category: layout-inference, aiDecision: this.inferLayout(model), aiReason: 页面包含 ${model.sections.map(s s.sectionType).join()} 组合推断为该布局, confidence: layoutConfidence, alternatives: [standard-stack, sidebar-layout, map-detail, form-centered], }); } // 3. 验证警告的交互项 for (const warning of validation.warnings) { items.push({ itemId: interaction-${warning.interactionId}, category: interaction-binding, aiDecision: 按PRD描述生成, aiReason: warning.message, confidence: 0.4, alternatives: warning.type dead-end ? [改用modal弹窗, 添加目标页面] : [添加条件判断, 调整触发源], }); } // 4. Mock数据策略确认 for (const dataReq of model.dataRequirements) { if (dataReq.mockStrategy ai-generated) { items.push({ itemId: data-${dataReq.entity}, category: data-mapping, aiDecision: AI自动生成Mock数据, aiReason: 实体 ${dataReq.entity} 无预设Mock数据需要AI生成或手动补充, confidence: 0.5, alternatives: [手动编写真实Mock, 对接测试环境API, 使用通用Mock模板], }); } } return items; } /** * 创建校准任务并分配给产品经理和技术负责人 */ createCalibrationTask( model: PageModel, orchestration: OrchestrationResult, validation: ValidationReport, assignees: { pm: string; techLead: string } ): CalibrationTask { const items this.extractCalibrationItems(model, orchestration, validation); return { taskId: cal-${model.pageId}-${Date.now()}, pageModel: model, orchestration, validation, calibrationItems: items, status: items.length 0 ? pending : confirmed, // 无校准项则自动确认 assignee: ${assignees.pm}${assignees.techLead}, deadline: new Date(Date.now() 24 * 60 * 60 * 1000), // 24小时校准截止 }; } /** * 应用校准结果将人工决策回写到模型和编排结果中 */ applyCalibration(task: CalibrationTask): { model: PageModel; orchestration: OrchestrationResult } { let model { ...task.pageModel }; // 根据校准项类型应用决策 for (const item of task.calibrationItems) { if (!item.humanDecision) continue; // 无人决策则保留AI决策 switch (item.category) { case component-selection: // 更新section的映射组件需在编排时生效 console.log(校准覆盖${item.itemId} → ${item.humanDecision}); break; case layout-inference: // 更新页面布局推断 console.log(布局校准${item.itemId} → ${item.humanDecision}); break; case interaction-binding: // 修复交互问题 console.log(交互校准${item.itemId} → ${item.humanDecision}); break; case data-mapping: // 更新Mock数据策略 console.log(数据校准${item.itemId} → ${item.humanDecision}); break; } } return { model, orchestration: task.orchestration }; } /** 评估布局推断的置信度 */ private assessLayoutConfidence(model: PageModel): number { const sectionTypes model.sections.map(s s.sectionType); // 已知组合模式高置信度 const knownPatterns: Recordstring, number { mapcard-list: 0.95, // 出行平台最常见的地图订单卡片 formtable: 0.90, // 管理后台经典表单表格 headertimeline: 0.88, // 订单详情页 tab-panelform: 0.85, // 多步骤表单 }; const patternKey sectionTypes.join(); return knownPatterns[patternKey] ?? 0.6; // 未知组合默认0.6 } private inferLayout(model: PageModel): string { const hasMap model.sections.some(s s.sectionType map); if (hasMap) return map-detail; return standard-stack; } private getSectionComponentMap(): Recordstring, string { return { header: PageHeader, card-list: CardList, form: DynamicForm, map: MapView, timeline: OrderTimeline, tab-panel: TabPanel, table: DataTable, }; } }五、数据复盘AI原型生成的真实效率增益在我们出行平台的 6 周试点中AI原型引擎共处理了47 个PRD需求。以下是关键数据指标传统流程AI加速流程变化PRD到可交互原型周期14.3 天1.8 天-87.4%产品校准耗时1.0 天0.6 天-40%交互覆盖率72%89%17pp原型Lighthouse预估分627816需求理解偏差返工率23%8%-15pp产品经理满意度(1~5)2.84.11.3几个值得注意的发现需求理解偏差大幅下降AI解析层的结构化输出迫使产品经理在PRD中更精确地描述字段和交互间接提升了PRD质量。23% → 8% 的返工率下降有一半功劳来自更好的PRD而非更好的AI。校准不是负担而是加速器产品经理反馈校准界面的差异确认模式比传统全量审查模式效率高 3 倍。只需要看 AI 不确定的部分而不是逐行审查整个原型。AI置信度阈值需要动态调整初始阈值 0.85 导致 62% 的决策需要人工确认。经过 3 周积累后基于历史校准数据将阈值降至 0.78人工确认比例降至 35%而原型质量没有下降。组件库映射的覆盖率是瓶颈出行平台的地图组件、行程卡片、司机面板等业务组件占比 40%但通用映射表只能覆盖 70%。剩余 30% 需要手动补充映射规则这是后续优化的重点方向。总结AI原型生成不是替代设计师而是压缩PRD到原型的结构化路径。三层架构需求解析→组件编排→交互验证加上校准闭环本质上是一个人机协同的质量保证体系——AI处理确定性高的80%人工校准不确定性高的20%最终产出质量远超纯人工或纯AI的任何单侧方案。出行平台的实践数据表明14.3天 → 1.8天的周期压缩87.4%的效率增益不是魔法而是结构化工程方法的产物。后续优化方向是(1) 扩大组件映射覆盖率到 95%(2) 动态置信度阈值基于历史数据自调(3) 将校准结果反馈回AI模型形成学习闭环。