{
  "id": 581213,
  "title": "10th Place Solution: Flux 1 Dev -> SVG optimization -> Postprocessing",
  "content": "<h1>10th Place Solution: Drawing with LLMs</h1>\n<p><strong>Team:</strong> BERA</p>\n<p>We’re thrilled to have placed 10th in the \"Drawing with LLMs\" competition. Thanks to the organizers and metric team for continuously iterating and improving the challenge and other participants for sharing great work. </p>\n<p>Our solution focuses on <strong>generating high-quality images first</strong>, and then <strong>converting and optimizing them into compact, accurate SVGs</strong> under the tight 10KB constraint. Our pipeline emphasizes image quality, conversion fidelity, and smart selection via the competition's evaluators, the efficiency of the SVG conversion being particularly strong.</p>\n<h2>Pipeline Components</h2>\n<p>Image (Flux-1-Dev + HyperSD + Nunchaku) + SVG (vtracer + svgo + custom geometry simplification + OCR addition) + Selection (VQA + Aesthetic + OCR) + Optional Border Addition</p>\n<h2>Overview of Our Pipeline</h2>\n<ol>\n<li><p><strong>Image Generation (Flux 1 Dev + HyperSD + Nunchaku)</strong></p>\n<ul>\n<li>We used <strong>Flux 1 Dev</strong>, enhanced with <strong>HyperSD LoRA</strong> to reduce inference to <strong>8 steps</strong> from default <strong>50 steps</strong> and <strong>Nunchaku</strong> for loading the transformer part in a much faster version. We quantized all components of the pipeline in <strong>4bit</strong> with BitsAndBytes so that they fit on a <strong>single T4</strong>.</li>\n<li>Initially, we couldn't get parallel generation to run, but switching to the newest Nunchaku dev version resolved the issue.</li>\n<li>Final throughput: ~10 images in ~20 seconds using a single T4.</li></ul></li>\n<li><p><strong>Image → SVG Conversion (vtracer + Path Simplification)</strong></p>\n<ul>\n<li>Each image was converted using <strong>vtracer</strong>, which gave us clean, layered SVGs.</li>\n<li>We applied <strong>geometric simplification</strong> by trimming intermediate points that added negligible curvature:</li></ul>\n<blockquote>\n  <p>e.g., If point B lies within 2 pixels of line A–C, we drop B.</p>\n</blockquote></li>\n</ol>\n<ul>\n<li><p>Compression with <strong>SVGO</strong> followed. We performed <strong>binary search over vtracer parameters</strong> to find the best configuration that used under 10000 bytes.<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2Feb3029c2bf9639f6c4f9e6de666203dd%2FSVG%20compare.png?generation=1748500604684319&amp;alt=media\" alt=\"\n\"></p></li>\n<li><p>This step was expensive and ran <strong>multiprocessed on 4 threads</strong>.</p></li>\n<li><p>We also added  <strong>two small “M” watermark</strong> in black and white to mitigate OCR false positives.</p></li>\n</ul>\n<ol>\n<li><p><strong>Candidate Selection (VQA + Aesthetic Score + OCR Robustness)</strong></p>\n<ul>\n<li>SVGs were scored using the <strong>VQA and Aesthetic evaluators</strong>.</li>\n<li>We ranked all candidates, then searched <em>backwards</em> to find the first image that <strong>passed OCR checks</strong> (a major pain point).</li>\n<li>On the top candidate, we created <strong>two variants</strong>: one original, and one with a <strong>gradient silver border</strong>. We used the best-scoring one.</li></ul></li>\n</ol>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2F1dd4964d416672dccf865060104ebf21%2FOutput%20final.png?generation=1748501085716653&amp;alt=media\" alt=\"Example Output with Gradient Silver Border\"></p>\n<h2>Debugging + Engineering Pain Points</h2>\n<p>We spent <strong>dozens of hours debugging edge cases</strong>, and the new submission format introduced several non-trivial issues:</p>\n<ul>\n<li><p><strong>SVGO</strong>: Wrapped with a custom Python interface and loaded it into a private GitHub repo, then installed it in the dependency manager with PAT (personal acess token). </p></li>\n<li><p><strong>Nunchaku</strong>: Didn’t work via standard install—had to fork and install via GitHub and then still load in the binary manually.</p></li>\n<li><p><strong>Multiprocessing and Execution Graph Dependencies</strong>: Ensuring image generation on cuda:0, SVG conversion and cuda:1 image selection stages didn’t block each other would have been a huge speed improvement but we could not get it to run on the submission server, though it ran in notebooks, on save and even on importing the package.  </p></li>\n</ul>\n<h2>Notes on Generation Behavior</h2>\n<ul>\n<li><strong>Landscapes</strong>: Near-perfect every time. The best modality for our pipeline.</li>\n<li><strong>Fashion</strong>: Challenging—details often lost in SVG conversion due to subtle features.</li>\n<li><strong>Geometry</strong>: Almost hopeless. Across 12+ models, even basic shapes like trapezoids only succeeded ~10% of the time.</li>\n</ul>\n<h2>Alternative Submission (Not Selected)</h2>\n<p>We had another submission that scored much higher on <strong>private LB</strong>, but slightly worse on <strong>public</strong>, so we sadly didn't select it, but maybe it's still interesting for you to hear of these additional improvements:</p>\n<ul>\n<li><p>It involved <strong>prompt rewriting</strong>, passing different forms to different encoders.</p></li>\n<li><p>Initially failed because we sent the <strong>same format</strong> to both:</p>\n<ul>\n<li>CLIP prefers <strong>comma-separated keywords</strong>.</li>\n<li>T5 prefers <strong>natural sentences</strong>.</li></ul></li>\n<li><p>Once separated, prompt rewriting improved performance in niche cases (e.g., animals and food).</p></li>\n</ul>\n<h2>Final Thoughts</h2>\n<p>We learned a lot about image generation pipelines and SVG compression. The challenge pushed us to get creative with pipelines, build interpretable evaluators, and respect tight compute budgets.</p>\n<p>Thanks again to the hosts and congrats to all participan</p>",
  "comments": [
    {
      "id": 3212077,
      "author_name": "Mikhail Golubchik",
      "author_url": "",
      "post_date": "2025-05-29T09:20:49.010000",
      "content": "<p>Solid work. Elegant solutions, especially in \"Image → SVG Conversion\".</p>\n<p>The \"abstract\" category was also really tough for me. There’s definitely potential in using LLMs to help generate those kinds of difficult abstract descriptions. Technically, I managed to mix approaches and even pack it into a working submission — and the geometric images did get higher scores and were selected. But overall, the approach didn’t quite outperform pure SD-based generation for me on the leaderboard.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3215398,
          "author_name": "Raki",
          "author_url": "",
          "post_date": "2025-06-02T06:56:19.867000",
          "content": "<p>Yeah we also ran a hybrid switching between Janus Pro and Flux (Janus Pro being better at abstract). But the additional compute and VRAM requirements gave us a better return when used them for our selection pipeline. </p>",
          "votes": 1,
          "replies": []
        }
      ]
    }
  ],
  "comment_count": 2,
  "messages": [
    {
      "id": 3212000,
      "postDate": "2025-05-29T06:41:16.353Z",
      "content": "<h1>10th Place Solution: Drawing with LLMs</h1>\n<p><strong>Team:</strong> BERA</p>\n<p>We’re thrilled to have placed 10th in the \"Drawing with LLMs\" competition. Thanks to the organizers and metric team for continuously iterating and improving the challenge and other participants for sharing great work. </p>\n<p>Our solution focuses on <strong>generating high-quality images first</strong>, and then <strong>converting and optimizing them into compact, accurate SVGs</strong> under the tight 10KB constraint. Our pipeline emphasizes image quality, conversion fidelity, and smart selection via the competition's evaluators, the efficiency of the SVG conversion being particularly strong.</p>\n<h2>Pipeline Components</h2>\n<p>Image (Flux-1-Dev + HyperSD + Nunchaku) + SVG (vtracer + svgo + custom geometry simplification + OCR addition) + Selection (VQA + Aesthetic + OCR) + Optional Border Addition</p>\n<h2>Overview of Our Pipeline</h2>\n<ol>\n<li><p><strong>Image Generation (Flux 1 Dev + HyperSD + Nunchaku)</strong></p>\n<ul>\n<li>We used <strong>Flux 1 Dev</strong>, enhanced with <strong>HyperSD LoRA</strong> to reduce inference to <strong>8 steps</strong> from default <strong>50 steps</strong> and <strong>Nunchaku</strong> for loading the transformer part in a much faster version. We quantized all components of the pipeline in <strong>4bit</strong> with BitsAndBytes so that they fit on a <strong>single T4</strong>.</li>\n<li>Initially, we couldn't get parallel generation to run, but switching to the newest Nunchaku dev version resolved the issue.</li>\n<li>Final throughput: ~10 images in ~20 seconds using a single T4.</li></ul></li>\n<li><p><strong>Image → SVG Conversion (vtracer + Path Simplification)</strong></p>\n<ul>\n<li>Each image was converted using <strong>vtracer</strong>, which gave us clean, layered SVGs.</li>\n<li>We applied <strong>geometric simplification</strong> by trimming intermediate points that added negligible curvature:</li></ul>\n<blockquote>\n  <p>e.g., If point B lies within 2 pixels of line A–C, we drop B.</p>\n</blockquote></li>\n</ol>\n<ul>\n<li><p>Compression with <strong>SVGO</strong> followed. We performed <strong>binary search over vtracer parameters</strong> to find the best configuration that used under 10000 bytes.<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2Feb3029c2bf9639f6c4f9e6de666203dd%2FSVG%20compare.png?generation=1748500604684319&amp;alt=media\" alt=\"\n\"></p></li>\n<li><p>This step was expensive and ran <strong>multiprocessed on 4 threads</strong>.</p></li>\n<li><p>We also added  <strong>two small “M” watermark</strong> in black and white to mitigate OCR false positives.</p></li>\n</ul>\n<ol>\n<li><p><strong>Candidate Selection (VQA + Aesthetic Score + OCR Robustness)</strong></p>\n<ul>\n<li>SVGs were scored using the <strong>VQA and Aesthetic evaluators</strong>.</li>\n<li>We ranked all candidates, then searched <em>backwards</em> to find the first image that <strong>passed OCR checks</strong> (a major pain point).</li>\n<li>On the top candidate, we created <strong>two variants</strong>: one original, and one with a <strong>gradient silver border</strong>. We used the best-scoring one.</li></ul></li>\n</ol>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2F1dd4964d416672dccf865060104ebf21%2FOutput%20final.png?generation=1748501085716653&amp;alt=media\" alt=\"Example Output with Gradient Silver Border\"></p>\n<h2>Debugging + Engineering Pain Points</h2>\n<p>We spent <strong>dozens of hours debugging edge cases</strong>, and the new submission format introduced several non-trivial issues:</p>\n<ul>\n<li><p><strong>SVGO</strong>: Wrapped with a custom Python interface and loaded it into a private GitHub repo, then installed it in the dependency manager with PAT (personal acess token). </p></li>\n<li><p><strong>Nunchaku</strong>: Didn’t work via standard install—had to fork and install via GitHub and then still load in the binary manually.</p></li>\n<li><p><strong>Multiprocessing and Execution Graph Dependencies</strong>: Ensuring image generation on cuda:0, SVG conversion and cuda:1 image selection stages didn’t block each other would have been a huge speed improvement but we could not get it to run on the submission server, though it ran in notebooks, on save and even on importing the package.  </p></li>\n</ul>\n<h2>Notes on Generation Behavior</h2>\n<ul>\n<li><strong>Landscapes</strong>: Near-perfect every time. The best modality for our pipeline.</li>\n<li><strong>Fashion</strong>: Challenging—details often lost in SVG conversion due to subtle features.</li>\n<li><strong>Geometry</strong>: Almost hopeless. Across 12+ models, even basic shapes like trapezoids only succeeded ~10% of the time.</li>\n</ul>\n<h2>Alternative Submission (Not Selected)</h2>\n<p>We had another submission that scored much higher on <strong>private LB</strong>, but slightly worse on <strong>public</strong>, so we sadly didn't select it, but maybe it's still interesting for you to hear of these additional improvements:</p>\n<ul>\n<li><p>It involved <strong>prompt rewriting</strong>, passing different forms to different encoders.</p></li>\n<li><p>Initially failed because we sent the <strong>same format</strong> to both:</p>\n<ul>\n<li>CLIP prefers <strong>comma-separated keywords</strong>.</li>\n<li>T5 prefers <strong>natural sentences</strong>.</li></ul></li>\n<li><p>Once separated, prompt rewriting improved performance in niche cases (e.g., animals and food).</p></li>\n</ul>\n<h2>Final Thoughts</h2>\n<p>We learned a lot about image generation pipelines and SVG compression. The challenge pushed us to get creative with pipelines, build interpretable evaluators, and respect tight compute budgets.</p>\n<p>Thanks again to the hosts and congrats to all participan</p>",
      "rawMarkdown": "# 10th Place Solution: Drawing with LLMs\n\n**Team:** BERA\n\nWe’re thrilled to have placed 10th in the \"Drawing with LLMs\" competition. Thanks to the organizers and metric team for continuously iterating and improving the challenge and other participants for sharing great work. \n\nOur solution focuses on **generating high-quality images first**, and then **converting and optimizing them into compact, accurate SVGs** under the tight 10KB constraint. Our pipeline emphasizes image quality, conversion fidelity, and smart selection via the competition's evaluators, the efficiency of the SVG conversion being particularly strong.\n\n## Pipeline Components\nImage (Flux-1-Dev + HyperSD + Nunchaku) + SVG (vtracer + svgo + custom geometry simplification + OCR addition) + Selection (VQA + Aesthetic + OCR) + Optional Border Addition\n\n## Overview of Our Pipeline\n\n1. **Image Generation (Flux 1 Dev + HyperSD + Nunchaku)**\n\n   * We used **Flux 1 Dev**, enhanced with **HyperSD LoRA** to reduce inference to **8 steps** from default **50 steps** and **Nunchaku** for loading the transformer part in a much faster version. We quantized all components of the pipeline in **4bit** with BitsAndBytes so that they fit on a **single T4**.\n   * Initially, we couldn't get parallel generation to run, but switching to the newest Nunchaku dev version resolved the issue.\n   * Final throughput: \\~10 images in \\~20 seconds using a single T4.\n\n2. **Image → SVG Conversion (vtracer + Path Simplification)**\n\n   * Each image was converted using **vtracer**, which gave us clean, layered SVGs.\n   * We applied **geometric simplification** by trimming intermediate points that added negligible curvature:\n     > e.g., If point B lies within 2 pixels of line A–C, we drop B.\n* Compression with **SVGO** followed. We performed **binary search over vtracer parameters** to find the best configuration that used under 10000 bytes.![\n](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2Feb3029c2bf9639f6c4f9e6de666203dd%2FSVG%20compare.png?generation=1748500604684319&alt=media)\n\n* This step was expensive and ran **multiprocessed on 4 threads**.\n* We also added  **two small “M” watermark** in black and white to mitigate OCR false positives.\n\n\n3. **Candidate Selection (VQA + Aesthetic Score + OCR Robustness)**\n\n   * SVGs were scored using the **VQA and Aesthetic evaluators**.\n   * We ranked all candidates, then searched *backwards* to find the first image that **passed OCR checks** (a major pain point).\n   * On the top candidate, we created **two variants**: one original, and one with a **gradient silver border**. We used the best-scoring one.\n\n![Example Output with Gradient Silver Border](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3747152%2F1dd4964d416672dccf865060104ebf21%2FOutput%20final.png?generation=1748501085716653&alt=media)\n\n## Debugging + Engineering Pain Points\n\nWe spent **dozens of hours debugging edge cases**, and the new submission format introduced several non-trivial issues:\n\n* **SVGO**: Wrapped with a custom Python interface and loaded it into a private GitHub repo, then installed it in the dependency manager with PAT (personal acess token). \n\n* **Nunchaku**: Didn’t work via standard install—had to fork and install via GitHub and then still load in the binary manually.\n\n* **Multiprocessing and Execution Graph Dependencies**: Ensuring image generation on cuda:0, SVG conversion and cuda:1 image selection stages didn’t block each other would have been a huge speed improvement but we could not get it to run on the submission server, though it ran in notebooks, on save and even on importing the package.  \n\n## Notes on Generation Behavior\n\n* **Landscapes**: Near-perfect every time. The best modality for our pipeline.\n* **Fashion**: Challenging—details often lost in SVG conversion due to subtle features.\n* **Geometry**: Almost hopeless. Across 12+ models, even basic shapes like trapezoids only succeeded \\~10% of the time.\n\n## Alternative Submission (Not Selected)\n\nWe had another submission that scored much higher on **private LB**, but slightly worse on **public**, so we sadly didn't select it, but maybe it's still interesting for you to hear of these additional improvements:\n\n* It involved **prompt rewriting**, passing different forms to different encoders.\n* Initially failed because we sent the **same format** to both:\n\n  * CLIP prefers **comma-separated keywords**.\n  * T5 prefers **natural sentences**.\n* Once separated, prompt rewriting improved performance in niche cases (e.g., animals and food).\n\n## Final Thoughts\n\nWe learned a lot about image generation pipelines and SVG compression. The challenge pushed us to get creative with pipelines, build interpretable evaluators, and respect tight compute budgets.\n\nThanks again to the hosts and congrats to all participan",
      "votes": 14
    },
    {
      "id": 3212077,
      "postDate": "2025-05-29T09:20:49.010Z",
      "content": "<p>Solid work. Elegant solutions, especially in \"Image → SVG Conversion\".</p>\n<p>The \"abstract\" category was also really tough for me. There’s definitely potential in using LLMs to help generate those kinds of difficult abstract descriptions. Technically, I managed to mix approaches and even pack it into a working submission — and the geometric images did get higher scores and were selected. But overall, the approach didn’t quite outperform pure SD-based generation for me on the leaderboard.</p>",
      "rawMarkdown": "Solid work. Elegant solutions, especially in \"Image → SVG Conversion\".\n\nThe \"abstract\" category was also really tough for me. There’s definitely potential in using LLMs to help generate those kinds of difficult abstract descriptions. Technically, I managed to mix approaches and even pack it into a working submission — and the geometric images did get higher scores and were selected. But overall, the approach didn’t quite outperform pure SD-based generation for me on the leaderboard.",
      "votes": 1,
      "replies": [
        {
          "id": 3215398,
          "postDate": "2025-06-02T06:56:19.867Z",
          "content": "<p>Yeah we also ran a hybrid switching between Janus Pro and Flux (Janus Pro being better at abstract). But the additional compute and VRAM requirements gave us a better return when used them for our selection pipeline. </p>",
          "rawMarkdown": "Yeah we also ran a hybrid switching between Janus Pro and Flux (Janus Pro being better at abstract). But the additional compute and VRAM requirements gave us a better return when used them for our selection pipeline. ",
          "votes": 1
        }
      ]
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T09:10:45Z",
  "competition_id": 89659,
  "competition_slug": "drawing-with-llms",
  "team_id": 13404656,
  "solution_url": "/competitions/drawing-with-llms/writeups/bera-10th-place-solution-flux-1-dev-svg-optimizati"
}