HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • AI 训练手册

    • AI UI生成系统 - 完整学习手册
    • 项目概述与架构设计
    • 环境搭建与快速开始
    • 核心概念与术语
    • 数据生成系统
    • UI-DSL数据格式详解
    • 数据质量与评估
    • LoRA微调技术
    • 完整的模型训练流程
    • 模型推理与优化
    • PNG图片渲染实现
    • Vue页面渲染系统
    • 多主题支持架构
    • FastAPI服务设计
    • Docker部署实践
    • 生产环境运维
    • 项目实战案例
    • 性能优化指南
    • 扩展开发指南
    • API参考文档
    • 配置参数说明
    • 故障排查指南

数据生成系统

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 核心特点

  1. 自动化生成: 程序化生成大量训练数据
  2. 高质量保证: 严格的数据质量控制和验证
  3. 多样化覆盖: 支持多种页面类型和主题风格
  4. 易于扩展: 模块化设计,便于添加新功能

11.2 技术优势

  1. 效率高: 快速生成大量数据
  2. 质量稳定: 保证数据一致性
  3. 成本低: 无需人工标注
  4. 可控制: 精确控制数据分布

11.3 应用价值

  1. 解决数据稀缺: 提供充足的训练数据
  2. 提升模型性能: 高质量数据提升模型效果
  3. 加速开发: 快速启动模型训练
  4. 支持迭代: 便于数据集的持续优化

通过合理使用数据生成系统,可以显著提升AI UI生成系统的整体性能和用户体验。

Prev
核心概念与术语
Next
UI-DSL数据格式详解