数据生成系统
1. 概述
1.1 数据生成的重要性
在AI UI生成系统中,数据生成是整个训练流程的起点。高质量的训练数据是模型性能的基础,直接影响最终生成UI的质量和准确性。
1.2 数据生成挑战
1.2.1 数据稀缺性
- UI设计数据获取困难
- 标注成本高
- 数据质量参差不齐
1.2.2 数据多样性
- 需要覆盖多种页面类型
- 需要支持多种主题风格
- 需要包含各种组件组合
1.2.3 数据一致性
- 保持数据结构一致性
- 确保标注标准统一
- 维护数据质量稳定
1.3 解决方案
本系统采用合成数据生成的方法,通过程序化生成大量高质量的Prompt-DSL配对数据,解决数据稀缺和多样性的问题。
2. 数据生成架构
2.1 整体架构
页面模板 -> 变化生成 -> Prompt生成 -> DSL生成 -> 数据验证 -> 数据集输出
│ │ │ │ │
│ │ │ │ │
模板定义 参数变化 自然语言 结构化数据 质量检查
2.2 核心组件
2.2.1 页面模板系统
- 定义标准页面结构
- 支持多种页面类型
- 提供组件配置模板
2.2.2 变化生成器
- 生成页面参数变化
- 控制数据多样性
- 确保覆盖度
2.2.3 Prompt生成器
- 将模板转换为自然语言
- 支持中文表达
- 保持语言自然性
2.2.4 DSL生成器
- 生成结构化UI数据
- 保持数据一致性
- 支持复杂嵌套
3. 页面模板系统
3.1 模板结构
page_templates = {
"home": {
"description": "电商首页",
"sections": [
{
"type": "topbar",
"props": {
"logo": "品牌",
"actions": ["search", "bell"]
}
},
{
"type": "tabs",
"props": {
"items": ["出货", "求货"],
"active": 0
}
},
{
"type": "card-list",
"props": {
"columns": 2,
"card": {"type": "product-card"}
}
},
{
"type": "tabbar",
"props": {
"items": ["home", "search", "plus", "message", "user"]
}
}
]
}
}
3.2 支持的页面类型
3.2.1 首页 (home)
- 用途: 电商应用首页
- 特点: 商品展示、导航功能
- 组件: topbar、tabs、card-list、tabbar
3.2.2 详情页 (detail)
- 用途: 商品详情展示
- 特点: 详细信息、操作按钮
- 组件: topbar、carousel、price、seller、proof、cta
3.2.3 搜索页 (search)
- 用途: 商品搜索和筛选
- 特点: 搜索功能、筛选条件
- 组件: topbar、filters、card-list
3.2.4 个人中心 (profile)
- 用途: 用户个人信息
- 特点: 用户信息、功能菜单
- 组件: topbar、user-info、menu-list
3.2.5 发布页 (publish)
- 用途: 商品发布功能
- 特点: 表单输入、操作按钮
- 组件: topbar、form、cta
3.3 组件配置
3.3.1 顶部栏 (topbar)
{
"type": "topbar",
"props": {
"logo": "品牌名称", # 品牌标识
"title": "页面标题", # 页面标题
"actions": ["search", "bell"] # 操作按钮
}
}
3.3.2 标签页 (tabs)
{
"type": "tabs",
"props": {
"items": ["出货", "求货"], # 标签项
"active": 0 # 激活标签
}
}
3.3.3 卡片列表 (card-list)
{
"type": "card-list",
"props": {
"columns": 2, # 列数
"card": { # 卡片配置
"type": "product-card"
}
}
}
4. 变化生成系统
4.1 变化类型
4.1.1 布局变化
- 列数变化: 1列、2列布局
- 间距变化: 不同的组件间距
- 尺寸变化: 组件大小调整
4.1.2 功能变化
- 搜索栏: 有/无搜索功能
- 标签页: 有/无标签切换
- 操作按钮: 不同的按钮组合
4.1.3 内容变化
- 文本内容: 不同的标题和描述
- 图片数量: 轮播图数量变化
- 菜单项: 不同的菜单选项
4.2 变化生成算法
4.2.1 组合生成
def _generate_variations(self, page_type: str) -> List[Dict[str, Any]]:
"""生成页面变化"""
variations = []
if page_type == "home":
# 列数变化
for columns in [1, 2]:
# 搜索栏变化
for has_search in [True, False]:
# 标签变化
for has_tabs in [True, False]:
variations.append({
"columns": columns,
"has_search": has_search,
"has_tabs": has_tabs
})
return variations
4.2.2 随机采样
def generate_dataset(self, num_samples: int = 1000) -> List[Dict[str, Any]]:
"""生成数据集"""
dataset = []
samples_per_type = num_samples // len(self.page_types)
for page_type in self.page_types:
variations = self._generate_variations(page_type)
for i in range(samples_per_type):
# 随机选择主题和变化
theme = random.choice(self.themes)
variation = random.choice(variations)
# 生成Prompt和DSL
prompt = self._generate_prompt(page_type, theme, variation)
dsl = self._generate_dsl(page_type, theme, variation)
dataset.append({
"instruction": prompt,
"output_json_minified": json.dumps(dsl, ensure_ascii=False, separators=(',', ':'))
})
return dataset
5. Prompt生成系统
5.1 生成策略
5.1.1 模板化生成
- 基于页面模板生成基础描述
- 添加主题风格描述
- 包含具体功能描述
5.1.2 自然语言化
- 使用自然的中文表达
- 保持语言流畅性
- 符合用户习惯
5.2 生成算法
5.2.1 基础描述生成
def _generate_prompt(self, page_type: str, theme: str, variations: Dict[str, Any]) -> str:
"""生成中文Prompt"""
template = self.page_templates[page_type]
base_desc = template["description"]
# 主题描述
theme_desc = {
"obsidian-gold": "黑金风格",
"silver-white": "白银风格",
"minimal": "简约风格"
}[theme]
# 构建Prompt
prompt_parts = [theme_desc, base_desc]
# 添加具体描述
if page_type == "home":
if variations.get("columns", 2) == 1:
prompt_parts.append("单列商品展示")
else:
prompt_parts.append(f"{variations.get('columns', 2)}列商品卡片")
if variations.get("has_search"):
prompt_parts.append("顶部搜索栏")
if variations.get("has_tabs"):
prompt_parts.append("顶部标签切换")
return ",".join(prompt_parts)
5.2.2 多样化表达
# 不同的表达方式
expressions = {
"columns": {
1: ["单列", "一列", "单排"],
2: ["两列", "双列", "并排"]
},
"search": {
True: ["搜索栏", "搜索框", "搜索功能"],
False: []
}
}
5.3 质量保证
5.3.1 语言质量
- 检查语法正确性
- 确保表达自然
- 避免重复表达
5.3.2 内容完整性
- 包含所有关键信息
- 描述准确完整
- 避免遗漏重要细节
6. DSL生成系统
6.1 生成流程
6.1.1 模板复制
def _generate_dsl(self, page_type: str, theme: str, variations: Dict[str, Any]) -> Dict[str, Any]:
"""生成UI-DSL"""
template = self.page_templates[page_type]
# 基础DSL结构
dsl = {
"page": {
"name": f"{page_type}_page",
"theme": theme,
"layout": {
"grid": 12,
"gutter": 16,
"padding": 16,
"bg": "#0E0E0E" if theme == "obsidian-gold" else "#FFFFFF"
},
"sections": []
}
}
return dsl
6.1.2 变化应用
# 根据模板和变化生成sections
for section in template["sections"]:
section_copy = section.copy()
# 应用变化
if section["type"] == "card-list":
section_copy["props"]["columns"] = variations.get("columns", 2)
elif section["type"] == "topbar":
if not variations.get("has_search", True):
if "search" in section_copy["props"].get("actions", []):
section_copy["props"]["actions"].remove("search")
elif section["type"] == "tabs":
if not variations.get("has_tabs", True):
continue
dsl["page"]["sections"].append(section_copy)
6.2 数据结构验证
6.2.1 格式验证
def validate_dsl(self, dsl: Dict[str, Any]) -> bool:
"""验证DSL格式"""
required_fields = ["page"]
if not all(field in dsl for field in required_fields):
return False
page = dsl["page"]
required_page_fields = ["name", "theme", "layout", "sections"]
if not all(field in page for field in required_page_fields):
return False
return True
6.2.2 内容验证
def validate_sections(self, sections: List[Dict]) -> bool:
"""验证sections内容"""
for section in sections:
if "type" not in section:
return False
if "props" not in section:
return False
return True
7. 数据质量控制
7.1 质量指标
7.1.1 数据完整性
- 所有必要字段都存在
- 数据结构完整
- 无缺失值
7.1.2 数据一致性
- 相同类型数据格式一致
- 命名规范统一
- 值域范围合理
7.1.3 数据多样性
- 覆盖所有页面类型
- 包含所有主题风格
- 包含各种变化组合
7.2 质量控制流程
7.2.1 生成时检查
def generate_sample(self, page_type: str, theme: str, variation: Dict) -> Dict:
"""生成单个样本"""
# 生成Prompt和DSL
prompt = self._generate_prompt(page_type, theme, variation)
dsl = self._generate_dsl(page_type, theme, variation)
# 质量检查
if not self.validate_dsl(dsl):
return None
if not self.validate_prompt(prompt):
return None
return {
"instruction": prompt,
"output_json_minified": json.dumps(dsl, ensure_ascii=False, separators=(',', ':'))
}
7.2.2 批量验证
def validate_dataset(self, dataset: List[Dict]) -> Tuple[List[Dict], List[Dict]]:
"""验证数据集"""
valid_samples = []
invalid_samples = []
for sample in dataset:
try:
# 验证JSON格式
dsl = json.loads(sample["output_json_minified"])
# 验证数据结构
if self.validate_dsl(dsl):
valid_samples.append(sample)
else:
invalid_samples.append(sample)
except json.JSONDecodeError:
invalid_samples.append(sample)
return valid_samples, invalid_samples
7.3 数据统计
7.3.1 基础统计
def generate_stats(self, dataset: List[Dict]) -> Dict:
"""生成数据统计"""
stats = {
"total_samples": len(dataset),
"page_type_distribution": {},
"theme_distribution": {},
"avg_prompt_length": 0,
"avg_dsl_length": 0
}
# 统计页面类型分布
for sample in dataset:
try:
dsl = json.loads(sample["output_json_minified"])
page_type = dsl["page"]["name"].split("_")[0]
stats["page_type_distribution"][page_type] = stats["page_type_distribution"].get(page_type, 0) + 1
theme = dsl["page"]["theme"]
stats["theme_distribution"][theme] = stats["theme_distribution"].get(theme, 0) + 1
stats["avg_prompt_length"] += len(sample["instruction"])
stats["avg_dsl_length"] += len(sample["output_json_minified"])
except:
continue
stats["avg_prompt_length"] /= len(dataset)
stats["avg_dsl_length"] /= len(dataset)
return stats
8. 数据分割与保存
8.1 数据分割策略
8.1.1 分割比例
# 默认分割比例
train_split = 0.8 # 训练集 80%
val_split = 0.1 # 验证集 10%
test_split = 0.1 # 测试集 10%
8.1.2 分割算法
def split_dataset(self, dataset: List[Dict]) -> Tuple[List[Dict], List[Dict], List[Dict]]:
"""分割数据集"""
# 随机打乱数据集
random.shuffle(dataset)
total = len(dataset)
train_size = int(total * self.config["data"]["train_split"])
val_size = int(total * self.config["data"]["val_split"])
train_data = dataset[:train_size]
val_data = dataset[train_size:train_size + val_size]
test_data = dataset[train_size + val_size:]
return train_data, val_data, test_data
8.2 数据保存
8.2.1 JSONL格式
def save_jsonl(self, data: List[Dict], file_path: str):
"""保存为JSONL格式"""
with open(file_path, 'w', encoding='utf-8') as f:
for sample in data:
f.write(json.dumps(sample, ensure_ascii=False) + '\n')
8.2.2 批量保存
def save_dataset(self, dataset: List[Dict], output_dir: str):
"""保存数据集"""
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
# 分割数据集
train_data, val_data, test_data = self.split_dataset(dataset)
# 保存为JSONL格式
for split, data in [("train", train_data), ("val", val_data), ("test", test_data)]:
file_path = output_path / f"{split}.jsonl"
self.save_jsonl(data, file_path)
print(f"保存 {split} 数据集: {file_path} ({len(data)} 样本)")
# 保存统计信息
stats = self.generate_stats(dataset)
stats_path = output_path / "dataset_stats.json"
with open(stats_path, 'w', encoding='utf-8') as f:
json.dump(stats, f, ensure_ascii=False, indent=2)
9. 使用示例
9.1 基本使用
from data.generate_synthetic_data import UIDataGenerator
# 创建数据生成器
generator = UIDataGenerator("config/model_config.yaml")
# 生成数据集
dataset = generator.generate_dataset(num_samples=1000)
# 保存数据集
generator.save_dataset(dataset, "data/synthetic")
9.2 自定义配置
# 自定义页面类型
generator.page_types = ["home", "detail", "custom_page"]
# 自定义主题
generator.themes = ["obsidian-gold", "custom-theme"]
# 自定义组件
generator.components["custom"] = ["custom-component"]
9.3 批量生成
# 生成多个数据集
for size in [100, 500, 1000, 5000]:
dataset = generator.generate_dataset(num_samples=size)
generator.save_dataset(dataset, f"data/synthetic_{size}")
10. 最佳实践
10.1 数据质量
10.1.1 模板设计
- 保持模板结构清晰
- 使用一致的命名规范
- 提供完整的组件配置
10.1.2 变化设计
- 确保变化有意义
- 覆盖主要使用场景
- 避免过度复杂化
10.2 性能优化
10.2.1 生成效率
- 使用批量生成
- 避免重复计算
- 合理设置缓存
10.2.2 内存管理
- 分批处理大数据集
- 及时释放不需要的数据
- 使用生成器模式
10.3 扩展性
10.3.1 新页面类型
- 定义新的页面模板
- 实现对应的变化生成
- 更新Prompt生成逻辑
10.3.2 新组件类型
- 扩展组件配置
- 更新渲染逻辑
- 维护向后兼容性
11. 总结
数据生成系统是AI UI生成系统的重要组成部分,它解决了训练数据稀缺和质量问题。通过程序化生成大量高质量的Prompt-DSL配对数据,为模型训练提供了坚实的基础。
11.1 核心特点
- 自动化生成: 程序化生成大量训练数据
- 高质量保证: 严格的数据质量控制和验证
- 多样化覆盖: 支持多种页面类型和主题风格
- 易于扩展: 模块化设计,便于添加新功能
11.2 技术优势
- 效率高: 快速生成大量数据
- 质量稳定: 保证数据一致性
- 成本低: 无需人工标注
- 可控制: 精确控制数据分布
11.3 应用价值
- 解决数据稀缺: 提供充足的训练数据
- 提升模型性能: 高质量数据提升模型效果
- 加速开发: 快速启动模型训练
- 支持迭代: 便于数据集的持续优化
通过合理使用数据生成系统,可以显著提升AI UI生成系统的整体性能和用户体验。