用 GPT 进行设计系统知识蒸馏:从文档到结构化规则的自动提取
用 GPT 进行设计系统知识蒸馏:从文档到结构化规则的自动提取
一、100 页设计规范 PDF 躺在共享文件夹里吃灰
公司有一套完整的设计规范:PDF 文档 100 页,包含了按钮规格、间距规则、色彩使用指南、状态机定义……每个新入职的前端都需要读一遍。事实是:没人读完过。真实开发流程是"凭感觉写 → Code Review 时被设计走查打回 → 翻 PDF 找对应规则 → 修改"。
问题不在文档的内容质量,在于文档的形态。人类阅读 PDF 很舒服,但机器无法消费。如果每一条设计规则都能被解析为结构化的可执行约束(JSON 格式),就能在 CI 中自动检查、在 IDE 中实时提示。
知识蒸馏(Knowledge Distillation)在 ML 领域指"大模型的知识压缩到小模型",但在设计系统场景中,它的意思是:把非结构化的设计文档蒸馏为结构化的规则库。
二、文档 → 规则的蒸馏管道
蒸馏的核心不是"用 LLM 重新写文档",而是让 LLM 从已有文档中提取规则。LLM 擅长做的是:从一段自然语言描述中识别出"主语-谓语-宾语",映射为"设计元素-约束类型-约束值"。
三、蒸馏工具实现
// knowledge-distillation/distiller.ts
// 设计系统知识蒸馏引擎
// 从设计文档中自动提取结构化规则
import fs from 'fs';
import path from 'path';
/** 单条设计规则的结构化表示 */
interface DesignRule {
/** 规则 ID,唯一标识 */
id: string;
/** 规则类型 */
category: 'color' | 'spacing' | 'typography' | 'component' | 'layout' | 'animation';
/** 规则适用对象:'.btn', 'h1', 'input' 等 */
target: string;
/** 约束的属性:'font-size', 'border-radius', 'color' 等 */
property: string;
/** 约束的运算符 */
operator: 'eq' | 'in' | 'range' | 'gte' | 'lte' | 'oneOf';
/** 约束值 */
value: string | string[] | { min: number; max: number };
/** 原始文档引用(可追溯) */
source: string;
/** 蒸馏置信度 0~1 */
confidence: number;
/** 能否自动执行 */
autoEnforceable: boolean;
}
/**
* 从 Markdown 设计文档中蒸馏规则
*
* 策略:分三步走——
* 1. 按章节分割文档(每个 ## 标题为一个规则域)
* 2. 每段送入 LLM 进行结构化提取
* 3. 合并、去重、评分
*/
async function distillFromMarkdown(markdownPath: string): Promise<DesignRule[]> {
const content = fs.readFileSync(markdownPath, 'utf-8');
const sections = splitIntoSections(content);
const allRules: DesignRule[] = [];
for (const section of sections) {
const prompt = buildDistillationPrompt(section);
// 调用 LLM API(此处为接口示意,实际使用 OpenAI/Anthropic API)
const rules = await callLLMForRules(prompt);
allRules.push(...rules);
}
return mergeAndDeduplicate(allRules);
}
/**
* 将 Markdown 按 ## 标题分割为章节
*/
function splitIntoSections(markdown: string): Array<{ title: string; content: string }> {
const sections: Array<{ title: string; content: string }> = [];
const lines = markdown.split('\n');
let currentTitle = '';
let currentContent: string[] = [];
for (const line of lines) {
if (line.startsWith('## ') && !line.startsWith('### ')) {
if (currentTitle) {
sections.push({ title: currentTitle, content: currentContent.join('\n') });
}
currentTitle = line.replace('## ', '').trim();
currentContent = [];
} else {
currentContent.push(line);
}
}
if (currentTitle) {
sections.push({ title: currentTitle, content: currentContent.join('\n') });
}
return sections;
}
/**
* 构建蒸馏 Prompt
*
* 核心指令:从设计文档片段中提取结构化规则
* 输出格式:JSON 数组
*
* Prompt 设计要点:
* 1. 明确输出 schema——约束 LLM 只能输出合法 JSON
* 2. 提供 few-shot 示例——帮助 LLM 理解期望格式
* 3. 要求置信度——让下游能区分"明确的规则"和"推测的规则"
*/
function buildDistillationPrompt(section: { title: string; content: string }): string {
return `
你是一个设计系统知识蒸馏助手。请从以下设计规范文本中提取结构化规则。
## 输出格式
每条规则为 JSON 对象,包含以下字段:
{
"category": "color|spacing|typography|component|layout|animation",
"target": "规则适用的设计元素(如 .btn, h1, input, .card 等)",
"property": "约束的 CSS 属性(如 font-size, border-radius, color)",
"rule": "具体的约束描述(如 字体大小 14px, 圆角 4px, 间距使用 8px 倍数)",
"confidence": 0.0-1.0 之间的置信度(原文明确提及=1.0,从上下文推断=0.5-0.8)
}
## Few-shot 示例
输入:
"所有主按钮的圆角为 4px,hover 时背景色加深 10%"
输出:
[
{
"category": "component",
"target": ".btn-primary",
"property": "border-radius",
"rule": "border-radius: 4px",
"confidence": 1.0
},
{
"category": "component",
"target": ".btn-primary:hover",
"property": "background-color",
"rule": "background-color 需比默认态深 10%",
"confidence": 0.9
}
]
## 章节标题
${section.title}
## 章节内容
${section.content}
请仅输出 JSON 数组,不要输出其他内容。
`.trim();
}
/**
* 调用 LLM 提取规则(示意实现)
* 实际需要替换为 OpenAI/Anthropic SDK 调用
*/
async function callLLMForRules(prompt: string): Promise<DesignRule[]> {
// 实际实现中,这里调用 GPT-4/Claude API
// const response = await openai.chat.completions.create({
// model: 'gpt-4',
// messages: [{ role: 'user', content: prompt }],
// temperature: 0.1, // 低温度确保输出稳定
// response_format: { type: 'json_object' }
// });
// return JSON.parse(response.choices[0].message.content);
// 示意返回
return [];
}
/**
* 合并去重:多条规则指向同一个约束时,保留置信度最高的
*/
function mergeAndDeduplicate(rules: DesignRule[]): DesignRule[] {
const map = new Map<string, DesignRule>();
for (const rule of rules) {
// 生成去重 key:category + target + property 的组合
const key = `${rule.category}:${rule.target}:${rule.property}`;
if (!map.has(key) || map.get(key)!.confidence < rule.confidence) {
map.set(key, { ...rule, id: key });
}
}
return Array.from(map.values());
}
// knowledge-distillation/rule-to-lint.ts
// 将蒸馏出的规则转换为可执行的 Stylelint/ESLint 规则
interface LintRuleGenerator {
generateStylelintRule(rule: DesignRule): string;
generateESLintRule(rule: DesignRule): string;
}
/**
* 将设计规则转换为 Stylelint 自定义规则代码
*/
function designRuleToStylelint(rule: DesignRule): string {
switch (rule.category) {
case 'color':
return generateColorLintRule(rule);
case 'spacing':
return generateSpacingLintRule(rule);
case 'typography':
return generateTypographyLintRule(rule);
default:
return `// TODO: ${rule.category} 类型的规则暂不支持自动生成`;
}
}
/**
* 生成颜色规则(示例:检查是否使用了 Tokens 之外的颜色值)
*/
function generateColorLintRule(rule: DesignRule): string {
return `
// 自动生成于设计系统知识蒸馏
// 规则来源:${rule.source}
// 置信度:${rule.confidence}
module.exports = {
rules: {
'color-no-untokenized': {
meta: {
messages: {
rejected: '颜色值应使用设计 Token,不允许硬编码颜色'
}
},
create(context) {
return {
Declaration(node) {
if (node.prop.includes('color') || node.prop === 'background') {
// 检查值是否为 hex 或 rgb(非 var() 形式)
if (/^#[0-9a-fA-F]{3,8}$/.test(node.value) ||
/^rgb/.test(node.value)) {
context.report({
node,
message: \`颜色 "\${node.value}" 应替换为设计 Token\`
});
}
}
}
};
}
}
}
};
`.trim();
}
function generateSpacingLintRule(rule: DesignRule): string {
return `
// 间距必须是 4px 的倍数
// 来源:${rule.source}
module.exports = {
rules: {
'spacing-multiple-of-4': {
create(context) {
return {
Declaration(node) {
const spacingProps = ['margin', 'padding', 'gap'];
if (spacingProps.some(p => node.prop.includes(p))) {
const match = node.value.match(/(\\d+)px/g);
if (match) {
for (const val of match) {
const num = parseInt(val);
if (num % 4 !== 0 && num !== 0) {
context.report({
node,
message: \`间距 \${num}px 不是 4px 的倍数,建议使用 \${Math.round(num/4)*4}px\`
});
}
}
}
}
}
};
}
}
}
};
`.trim();
}
function generateTypographyLintRule(rule: DesignRule): string {
return '';
}
四、蒸馏的准确性边界
LLM 会"发明"文档中不存在的规则。这是蒸馏最大的风险。降低幻觉的策略:
- 温度参数设 0.1(接近确定性输出)
- 要求引用原文(每条规则附带
source字段,指向原始文档的具体段落) - 置信度 < 0.8 的规则必须人工 Review,不能直接入库
公式和数值关系 LLM 处理得很差。"主色加深 10%"这种规则,LLM 可能正确提取为 darken(primary, 10%),也可能理解为 primary 的 L 分量减少 10——完全是不同的结果。数值型规则只适合做"提取",不适合让 LLM 做"计算"。
文档更新后蒸馏的增量处理。不是每次文档变更都全量蒸馏。更好的方案:对比新旧文档,只对变更的章节重新蒸馏,避免"改了一个按钮的圆角 → 重新蒸馏整个 100 页文档"。
五、总结
设计系统的知识蒸馏是从"人可以读懂"到"机器可以执行"的翻译过程。三个步骤:
- 文档分段——按章节切分设计规范文档
- LLM 结构化提取——将自然语言规则转为 JSON 格式的约束对象
- 规则编译器——将 JSON 约束编译为 Stylelint/ESLint 规则、CI 脚本、IDE 提示
蒸馏不是替代设计文档。文档依然是人阅读的"真理源",蒸馏出的规则库是文档的"可执行镜像"。两者不是竞争关系,而是主从关系——文档变更 → 重新蒸馏 → 规则库同步更新。
更多推荐

所有评论(0)