在多模态大模型(MLLM)的训练中,数据不仅决定了模型能力的上限,更决定了模型的“思维方式”。对于 SVG 这种特殊的模态——它既是视觉图像,又是代码文本(XML)——数据工程的复杂度远超纯文本或纯像素图像。
互联网(Common Crawl, GitHub, Icon Repositories)是最大的 SVG 矿藏,但它同时也是一个充斥着冗余代码、无效引用和非标准语法的沼泽。一个视觉上是圆形的图案,在 SVG 源码中可能被写作 <circle>,也可能是 <path>,甚至可能是一个应用了极坐标变换的 <rect>。如果你直接将原始 Web SVG 喂给模型,模型将不得不浪费大量参数去记忆 XML 的千奇百怪的写法,而不是学习图形的几何本质。
本章将带你构建一条完整的 ETL(Extract, Transform, Load)流水线。我们将深入探讨如何从 HTML 废墟中挖掘 SVG,如何通过规范化(Canonicalization)将 SVG 的“熵”降到最低,如何处理复杂的 CSS 依赖,以及如何利用现有的 VLM(视觉大模型)生成高质量的合成文本对齐数据。完成本章后,你将拥有构建一个百万级高质量 SVG-Text 配对数据集的能力。
网页中的 SVG 并非总是以 .svg 文件的形式存在。为了最大化数据量,我们需要针对三种形态制定不同的采集策略:
这是最容易采集的形式,通常通过 <img src="icon.svg"> 或 <object data="graph.svg"> 引用。
<?xml ...?> 头。asset_42.svg,毫无意义)。alt 属性、周边 <caption> 或父级 <div> 的文本,作为元数据。直接嵌入在 HTML DOM 树中的 <svg>...</svg> 代码块。
class="css-xyz",且高度依赖外部 CSS 渲染颜色。.cls-1 { fill: red } 转换为 fill="red"),否则提取出的 SVG 往往是一片漆黑。这是现代前端开发的常见模式。一个 SVG 文件作为一个“容器”,内部包含数十个 <symbol id="icon-user">,页面通过 <use xlink:href="#icon-user"> 来显示。
<symbol> 提取出来,包裹上 <svg> 根标签,并将原容器 <defs> 中的公共资源(如渐变、滤镜)复制到新文件中,形成独立的训练样本。[ 采集难度分级 ]
Easy: .svg 文件下载
Medium: <symbol> 解包与资源依赖解析
Hard: Inline SVG 的 CSS 样式计算与属性内联
并不是所有 <svg> 标签里的内容都是我们想要的。在进入模型之前,必须进行严格的清洗。
<image href="data:image/png;base64..." />。
<image> 标签覆盖的面积。如果 <image> 面积超过 ViewBox 的 80%,或者文件体积的 90% 都是 Base64 字符串,直接丢弃。这是“伪 SVG”。安全清洗:
SVG 是 XML,支持脚本。必须移除所有 <script> 标签、onclick/onload 等事件属性。这不仅是为了安全,也是因为生成模型不需要学习交互逻辑。
xmlns:inkscape、adobe:save-meta 等编辑器私有数据。移除 data-* 属性。移除注释 <!-- ... -->。这些不仅消耗 Token,还可能让模型过拟合到特定的编辑器特征上。这是本章最核心的技术点。规范化的目标是:对于同样的视觉输出,强制模型只看到一种标准的代码表达。
不同 SVG 的坐标系千差万别。有的 ViewBox 是 0 0 24 24,有的是 0 0 1024 768,有的是 -50 -50 100 100。
0 0 256 256)。padding 填充。SVG 允许在 Group (<g>) 或 Path 上应用 transform="translate(x,y) rotate(a) scale(s)"。这对模型理解几何极其不友好(模型需要在大脑中进行矩阵乘法才能知道线条真正画在哪里)。
transform 属性。SVG 有 <rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon> 等基础形状。
<path d="...">。SVG 编辑器经常生成 10.0000000001 这样的坐标。
10.0),甚至在 256x256 的尺度下直接取整。这能显著减少 Token 长度,且肉眼几乎不可见差异。在文本层面,SVG 是一长串字符。但在模型眼中,它应该是一串结构化的 Token。
命令与参数分离:
原始:M10 20L30 40
处理后:<M> <10> <20> <L> <30> <40>
建议在清洗阶段就在数字和命令之间插入空格,方便 BPE(Byte Pair Encoding)分词器处理。
相对坐标 vs 绝对坐标:
有了干净的 SVG 代码,我们还需要配对的文本(Prompt)。Web 数据的天然文本质量极差,我们需要多层次的对齐策略:
| 来源 | 质量 | 数量 | 描述 |
|---|---|---|---|
| Alt / Title | 低 | 极大 | 只有关键词,如 “search icon”。适合做 Keyword-to-SVG。 |
| Surrounding Text | 中 | 大 | 网页正文。噪音大,需用 NLP 提取关键词。 |
| OCR / Detection | 高 | 中 | 对 SVG 渲染图运行 OCR,提取图中的文字,作为文本提示的一部分。 |
| 合成数据 (Synthetic) | 极高 | 需计算成本 | 这是 SOTA 的关键。 |
合成数据流水线(The Synthetic Pipeline):
SVG 数据存在严重的同源相似性。一个网站的 50 个图标通常由同一个设计师用同一种风格绘制。
github.com 的所有 SVG 都在训练集。twitter.com 的所有 SVG 都在测试集。<rect x="10" y="20" width="50" height="30" />。请写出将其转换为 <path d="..."> 后的指令序列。
viewBox="0 0 100 50"。如果我们要将其归一化到 256 x 256 的正方形画布中并保持居中,原始坐标 (50, 25) 在新画布中的坐标应该是多少?
<script>alert('xss')</script> 和正常的图形数据。icon_v2_final_final.svg。设计一个简单的正则表达式或逻辑,将其转化为可用的文本标签。
<g transform="translate(10, 10)">
<g transform="scale(2)">
<path d="M 0 0 L 10 0" />
</g>
</g>
请描述如何通过矩阵运算,计算出 path 最终的绝对坐标。
<text>Hello</text>)时,我们面临一个两难选择:是保留 <text> 标签让模型学习排版,还是将其转换为轮廓(Outline/Path)?请分析这两种策略在 MLLM 训练中的优缺点。
defs 与 use
<path> 时一切正常,但渲染出来缺少部分图形。<defs> 里,通过 <use> 引用。如果不解析 <use> 标签并将其展开(Instantiate),你的数据集就是残缺的。use 节点的递归展开逻辑,将引用的图形实体化到当前位置。fill-rule 属性决定了复杂路径的内部填充逻辑。如果规范化时丢失了这个属性,或者混合了不同 fill-rule 的路径。nonzero 规则,或者在模型输入中显式包含 fill-rule token。currentColor
fill="currentColor",这是为了让图标颜色跟随父级文字颜色。在独立提取时,currentColor 默认解析为黑。currentColor 替换为一个随机深色或标准黑色,或者保留该 Token 作为一个特殊的可控变量。lxml 的 recover=True 模式,或者在使用 Parser 前先用正则进行“脏修复”。对于无法修复的坏文件,直接 try-catch 丢弃,千万不要让脏数据中断数据处理流水线。