<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GeneLab_999</title>
    <description>The latest articles on DEV Community by GeneLab_999 (@genelab_999).</description>
    <link>https://dev.to/genelab_999</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3743545%2Fe831cbea-2547-4969-b084-e435a8e2fc05.png</url>
      <title>DEV Community: GeneLab_999</title>
      <link>https://dev.to/genelab_999</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/genelab_999"/>
    <language>en</language>
    <item>
      <title>I didn't fix the bug: contributing to a 20k-star ML repo by measuring it</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Thu, 24 Sep 2026 04:41:45 +0000</pubDate>
      <link>https://dev.to/genelab_999/i-didnt-fix-the-bug-contributing-to-a-20k-star-ml-repo-by-measuring-it-1lg7</link>
      <guid>https://dev.to/genelab_999/i-didnt-fix-the-bug-contributing-to-a-20k-star-ml-repo-by-measuring-it-1lg7</guid>
      <description>&lt;p&gt;Last week I opened an issue on &lt;a href="https://github.com/NandhaKishorM/laya" rel="noopener noreferrer"&gt;laya&lt;/a&gt;, an open-source decision model with a little over 20k stars. The issue reported that one of its checkpoints almost never picks the first-listed option on ordinal questions. About 36 hours later, three things had happened. The maintainer had documented the limitation in a release. He had asked me to run the before/after on the retrained checkpoint. And he had merged a regression check I wrote. That was four days after my first measurement.&lt;/p&gt;

&lt;p&gt;Nothing is fixed. The fix is a retrain, and the retrain hasn't happened yet. What I contributed is narrower. I think it is also the kind of thing an outsider is best placed to contribute: a measurement nobody could wave away, and a tool that says whether the fix worked.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The fastest way I've found to contribute to an ML repo you don't maintain: measure it, make the measurement impossible to explain away, and then hand the maintainer a tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The timeline, in UTC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sep 20&lt;/strong&gt; — first Japanese baseline run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 22, 05:56&lt;/strong&gt; — &lt;a href="https://github.com/NandhaKishorM/laya/issues/131" rel="noopener noreferrer"&gt;issue #131&lt;/a&gt; opened&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 22, 06:40&lt;/strong&gt; — condition F posted (position vs. label, explained below)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 22, 07:15&lt;/strong&gt; — a third party, AlKor13, traces it to the weights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 22, 10:56&lt;/strong&gt; — my labelled A/B test of his hypothesis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 22, 20:40&lt;/strong&gt; — the maintainer's decision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 23, 07:25&lt;/strong&gt; — v0.3.7 ships with the limitation in the README&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 23, 14:42&lt;/strong&gt; — &lt;a href="https://github.com/NandhaKishorM/laya/pull/259" rel="noopener noreferrer"&gt;PR #259&lt;/a&gt; opened&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sep 23, 17:48&lt;/strong&gt; — PR #259 merged&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What laya is, and why I was measuring it
&lt;/h2&gt;

&lt;p&gt;laya is a non-autoregressive "System 1" decision model. You give it some text and a set of typed questions: &lt;code&gt;choice&lt;/code&gt;, &lt;code&gt;score&lt;/code&gt; for ordinal levels, and &lt;code&gt;noul&lt;/code&gt; for yes/no. It answers all of them in one forward pass, with probabilities and no text generation. It ships several checkpoints, including an English &lt;code&gt;laya&lt;/code&gt; and a &lt;code&gt;laya-multilingual&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm building a Japanese model in the same space (&lt;a href="https://github.com/hiroki-abe-58/sokudan" rel="noopener noreferrer"&gt;sokudan&lt;/a&gt;). Before writing any training code, I wanted a baseline: how well does the existing multilingual checkpoint handle Japanese?&lt;/p&gt;

&lt;p&gt;I built 300 label-conditioned Japanese business emails. The labels were fixed first. Then a local LLM wrote an email to match them, and any email containing the label words themselves was thrown out and regenerated. Each email got three questions: department (4-way &lt;code&gt;choice&lt;/code&gt;), urgency (3-level &lt;code&gt;score&lt;/code&gt;) and whether the customer is hinting at cancelling (&lt;code&gt;bool&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The results split by question type. &lt;code&gt;choice&lt;/code&gt; worked: 0.747 accuracy against a 0.380 majority-class baseline. &lt;code&gt;score&lt;/code&gt; lost to the majority baseline (RPS 0.232 vs 0.197, lower is better). &lt;code&gt;bool&lt;/code&gt; also lost to the majority baseline (0.543 vs 0.703), with an AUROC of 0.523. That is barely better than ranking at random.&lt;/p&gt;

&lt;p&gt;One comparison I did not run is TypeSafe's Jev, the hosted API laya benchmarks itself against. Its customer agreement prohibits using the service or its outputs to develop similar products, and my project is a similar product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The number that didn't fit
&lt;/h2&gt;

&lt;p&gt;"Worse than majority" is a finding, not an explanation. The confusion matrix for &lt;code&gt;score&lt;/code&gt; was more interesting. The lowest level, "not urgent", was never predicted in all 300 emails, even though 77 emails had it as the gold label.&lt;/p&gt;

&lt;p&gt;At least three explanations fit that. The ordinal head could be degenerate. The model could be reading position rather than content. Or this particular Japanese phrase could be the problem.&lt;/p&gt;

&lt;p&gt;To separate them, I re-ran the same 300 emails under five option schemas: original order, reversed, reworded (low / medium / high), reworded and reversed, and four levels. In all five, the first-listed option was chosen 0 or 1 time out of 300.&lt;/p&gt;

&lt;p&gt;The cleanest pair was the original order against the reversed one. "Not urgent" was chosen 0 times when listed first and 250 times when listed last. The emails were the same, the words were the same, and only the slot had changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it hard to explain away
&lt;/h2&gt;

&lt;p&gt;Before reporting, I tried to list the replies a busy maintainer could reasonably give, and to answer each one with data before he had to ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Your harness is wrong."&lt;/strong&gt; I re-ran the benchmark using only the two lines from the README, &lt;code&gt;laya.load()&lt;/code&gt; and &lt;code&gt;agent.predict()&lt;/code&gt;, with no wrapper of mine in between. Then I compared the results to my saved probabilities. The maximum difference was 0.0 after the probability floor I apply, and 2.2e-16 on the raw values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"It's a Japanese problem."&lt;/strong&gt; I built 290 English emails with the same label weights, the same generator and the same rejection rules, and ran the same five conditions. The multilingual checkpoint went 0 for 290 in every one of them. English is one of its training languages, so "it can't read the input" doesn't explain this.&lt;/p&gt;

&lt;p&gt;First-listed option chosen, per condition (original / reversed / reworded / reworded reversed / four levels):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;checkpoint&lt;/th&gt;
&lt;th&gt;Japanese (n=300)&lt;/th&gt;
&lt;th&gt;English (n=290)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laya-multilingual&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0, 0, 1, 1, 0&lt;/td&gt;
&lt;td&gt;0, 0, 0, 0, 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;laya&lt;/code&gt; (English)&lt;/td&gt;
&lt;td&gt;13, 56, 8, 1, 110&lt;/td&gt;
&lt;td&gt;65, 74, 0, 5, 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4mnxwffr0u7dapzo95xo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4mnxwffr0u7dapzo95xo.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The English checkpoint picks the first slot in most conditions, on the same data through the same harness. So the task isn't the cause, and neither is the harness. It comes down to one checkpoint. I opened &lt;a href="https://github.com/NandhaKishorM/laya/issues/131" rel="noopener noreferrer"&gt;#131&lt;/a&gt; with a title that said exactly that.&lt;/p&gt;

&lt;p&gt;(A correction to myself: in the issue I summarised the English checkpoint as picking the first option "22–26% of the time". That holds for the two original orderings. It is 0 in one condition and under 2% in two others. The table above is the honest version.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Is it the position or the word?"&lt;/strong&gt; Within any single fixed ordering, "the model rejects slot 1" and "the model rejects whichever word sits in slot 1" predict the same table. Someone on X asked whether the effect survives shuffling. Twenty-two minutes later I had condition F: the option order is shuffled per item, with a fixed seed. The results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first slot was chosen 0 times out of 300.&lt;/li&gt;
&lt;li&gt;Choices by slot were [0, 149, 151].&lt;/li&gt;
&lt;li&gt;Choices by label were 75 / 93 / 132.&lt;/li&gt;
&lt;li&gt;Each label had sat in the first slot 90 / 109 / 101 times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So every label lost exactly the picks it had while it was in slot 1. Slots 2 and 3 split evenly, so this isn't a preference for the last slot either. One run was enough to separate position from label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Someone else went deeper
&lt;/h2&gt;

&lt;p&gt;What happened next was the best part, and it wasn't my work. &lt;a href="https://github.com/AlKor13" rel="noopener noreferrer"&gt;AlKor13&lt;/a&gt;, who is not a maintainer, read the raw marker logits straight off the forward pass, before temperature and softmax.&lt;/p&gt;

&lt;p&gt;On the identical code path, swapping only the checkpoint made the hole appear or disappear. Then he ran the control I wish I'd thought of: three identical options, so the inputs differ only by position. The English checkpoint came out essentially flat. The multilingual one came out sharply position-dependent. That settled it: the cause is in the weights, not the code.&lt;/p&gt;

&lt;p&gt;He went one step further. Score options are rendered with a &lt;code&gt;level N:&lt;/code&gt; prefix, and dropping that prefix made the slot-0 suppression vanish from the raw logits. But he stated the limit of his own result. Without the prefix the input is off-distribution, so the recovery might just be the learned prior getting scrambled. Settling that would take labelled data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing someone else's hypothesis, and my own
&lt;/h2&gt;

&lt;p&gt;I had the labelled data, so I ran three renderings on both benchmarks: A is the shipped &lt;code&gt;level N:&lt;/code&gt; rendering, C drops the prefix, and D uses word ordinals. My harness reproduced &lt;code&gt;agent.predict()&lt;/code&gt; to within 4.6e-5 under condition A. I compared the renderings with paired McNemar tests on identical items:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;bench&lt;/th&gt;
&lt;th&gt;change&lt;/th&gt;
&lt;th&gt;score accuracy&lt;/th&gt;
&lt;th&gt;items that flipped correctness&lt;/th&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ja&lt;/td&gt;
&lt;td&gt;A → C&lt;/td&gt;
&lt;td&gt;0.447 → 0.513&lt;/td&gt;
&lt;td&gt;56.7%&lt;/td&gt;
&lt;td&gt;0.145&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ja&lt;/td&gt;
&lt;td&gt;A → D&lt;/td&gt;
&lt;td&gt;0.447 → 0.570&lt;/td&gt;
&lt;td&gt;38.3%&lt;/td&gt;
&lt;td&gt;0.0007&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;td&gt;A → C&lt;/td&gt;
&lt;td&gt;0.266 → 0.428&lt;/td&gt;
&lt;td&gt;56.9%&lt;/td&gt;
&lt;td&gt;0.0003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;td&gt;A → D&lt;/td&gt;
&lt;td&gt;0.266 → 0.293&lt;/td&gt;
&lt;td&gt;19.3%&lt;/td&gt;
&lt;td&gt;0.350&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvuhd9qex9uqjvwjp9bbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvuhd9qex9uqjvwjp9bbo.png" alt=" " width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two of the four comparisons are significant, and they are different conditions in different languages. D wins in Japanese and C wins in English, and each is null in the other language. The claim this supports is "the shipped rendering isn't the best one for this checkpoint". It does not support "drop the prefix and it's fixed".&lt;/p&gt;

&lt;p&gt;I'll admit the accuracy column alone had me halfway to writing the second claim. The paired test is what stopped me, and I said so in the thread.&lt;/p&gt;

&lt;p&gt;The column that matters is the flip rate. Under C, 57% of items change correctness, while headline accuracy moves by 6.7 to 16.2 points. A cosmetic change to the option string nearly re-rolls the prediction. That is an instability, not a mitigation. As a control, removing the prefix makes the English checkpoint &lt;em&gt;worse&lt;/em&gt; on the English set (0.583 → 0.500). So &lt;code&gt;level N:&lt;/code&gt; isn't harmful in general. The multilingual checkpoint has learned something wrong about that specific pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The maintainer's call
&lt;/h2&gt;

&lt;p&gt;About fifteen hours after I opened the issue, the maintainer, &lt;a href="https://github.com/NandhaKishorM" rel="noopener noreferrer"&gt;NandhaKishorM&lt;/a&gt;, replied to both of us. He called the thread "a model of how to run a bug down" and made three decisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The bug is in the weights, not the code.&lt;/li&gt;
&lt;li&gt;He would not ship a new default rendering. He cited the 57% flip rate: changing the rendering would swap one instability for another.&lt;/li&gt;
&lt;li&gt;The real fix is in training. Ordinal options need the same position balancing that &lt;code&gt;choice&lt;/code&gt; options already get.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The next morning, v0.3.7 shipped with a line in the README's limits section. It says &lt;code&gt;laya-multilingual&lt;/code&gt; has a position bias on &lt;code&gt;score&lt;/code&gt; questions, that English score questions should go to the English checkpoint, and that users should validate score outputs on their own data for other languages. The issue stays open until a retrained checkpoint lands.&lt;/p&gt;

&lt;p&gt;I offered to run the same A–F and A/C/D before/after on that checkpoint. He said he'd ping me when it's ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handing over a tool
&lt;/h2&gt;

&lt;p&gt;That offer had a weak point: it depended on me. My benchmarks are CC BY 4.0, so anyone can rerun them. But the question the retrain has to answer doesn't need labels at all: did the slot prior go away? So I wrote PR &lt;a href="https://github.com/NandhaKishorM/laya/pull/259" rel="noopener noreferrer"&gt;#259&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python research/eval/presentation_checks.py &lt;span class="nt"&gt;--model&lt;/span&gt; &amp;lt;retrained checkpoint&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--subfolder&lt;/span&gt; multilingual]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses ten short English support messages that are fixed in the file, with no dataset and no labels. It runs two checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;score_slot0_identical&lt;/code&gt; is AlKor13's identical-option control turned into a gate. It measures slot 0's raw logit minus the slot mean, over K = 3, 4 and 5 identical levels, and requires the result to be at least −0.20.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;score_first_slot_permuted&lt;/code&gt; puts the three real levels in all six orders for each message, so every level sits in every slot exactly twice. A model whose answer doesn't depend on order picks the first slot in exactly 1/3 of decisions. The gate is at least 0.15.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Results on the checkpoints that ship today:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;checkpoint&lt;/th&gt;
&lt;th&gt;slot-0 logit (gate ≥ −0.20)&lt;/th&gt;
&lt;th&gt;first-slot rate (gate ≥ 0.15)&lt;/th&gt;
&lt;th&gt;verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;laya&lt;/code&gt; (English)&lt;/td&gt;
&lt;td&gt;+0.664&lt;/td&gt;
&lt;td&gt;0.217&lt;/td&gt;
&lt;td&gt;PASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laya-multilingual&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;−0.492&lt;/td&gt;
&lt;td&gt;0.017&lt;/td&gt;
&lt;td&gt;FAIL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1cpvb61088fc92i1c13d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1cpvb61088fc92i1c13d.png" alt=" " width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I fixed the threshold conditions before the real 10-message run, and I didn't move them afterwards.&lt;/strong&gt; There were two conditions. First, in every leave-one-out subset, multilingual must fail and English must pass. Second, each checkpoint's worst leave-one-out value must clear its gate by at least 0.10 logit (slot 0) or 0.05 (first-slot rate). The tightest margin turned out to be the English first-slot rate, at 0.054.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gate is one-sided on purpose.&lt;/strong&gt; With identical options, the English checkpoint isn't flat either. It leans toward early slots, and the lean grows with K. A two-sided "no position effect" gate would fail the checkpoint everyone agrees is fine. So the gate asks only the narrower question #131 is about: is slot 0 suppressed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The harness checks itself before it gives a verdict.&lt;/strong&gt; It first compares its logit path against &lt;code&gt;Agent.system_one&lt;/code&gt; on every message. On the shipped checkpoints, the maximum |Δp| was 4.98e-5, which is just the API's 4-decimal rounding. If the difference exceeds 1e-3, the script exits with code 2 and reports no verdict. Exit 0 means pass, 1 means a check failed, and 2 means the harness disagrees with the package. There are 69 offline tests using scripted logits. For example, a scripted slot-0 hole fails both checks, and an order-invariant model scores exactly 1/3.&lt;/p&gt;

&lt;p&gt;The PR also lists its own limits. Passing is not accuracy. The check covers English only, &lt;code&gt;score&lt;/code&gt; only and ten short messages. And the thresholds were set on CPU with fp32.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before opening the PR
&lt;/h2&gt;

&lt;p&gt;I spent more time reading the repo than writing the script. Tests there are plain scripts, not pytest. CI doesn't load model checkpoints. Research code lives under &lt;code&gt;research/&lt;/code&gt;. A new test has to be registered in both &lt;code&gt;ci.yml&lt;/code&gt; and &lt;code&gt;release.yml&lt;/code&gt;, and an open PR, &lt;a href="https://github.com/NandhaKishorM/laya/pull/184" rel="noopener noreferrer"&gt;#184&lt;/a&gt;, hadn't yet settled how research tests get wired in. So I didn't wire mine in. I said so in the PR and offered to do it once #184 lands. Nothing under &lt;code&gt;laya/&lt;/code&gt; changed, and I added no new dependencies.&lt;/p&gt;

&lt;p&gt;The same afternoon, another contributor, Rukafuu, had proposed a general metamorphic robustness framework in &lt;a href="https://github.com/NandhaKishorM/laya/issues/244" rel="noopener noreferrer"&gt;#244&lt;/a&gt;, and the maintainer had invited them to start with option permutation. That was their work to do. I kept my check specific to #131 and noted that it could move into their framework once it exists. Their PR, #269, has since been merged.&lt;/p&gt;

&lt;h1&gt;
  
  
  259 was merged about three hours after I opened it. The maintainer said a label-free check answering one question was "exactly what #131 needs". He also said that separating a failed check from a harness disagreement in the exit codes made it "easy to trust". That second point is the one I'm proudest of, because it's the part nobody asked for.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  On using Claude Code
&lt;/h2&gt;

&lt;p&gt;I used Claude Code throughout: for the harness, the offline tests and drafting the PR text. The commit carries a &lt;code&gt;Co-Authored-By&lt;/code&gt; line. The decisions about what to measure, what to claim, what to take back and where to stop were mine, and so are any mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell myself next time
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Measure before you report, and check your harness against the official package before you measure anything that matters.&lt;/strong&gt; "Your harness is wrong" is the cheapest possible dismissal. Rule it out first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answer the obvious objections before anyone raises them.&lt;/strong&gt; Is it the language? Run it in English. The harness? Check parity. The word? Shuffle per item. Each of those came back as one line in the thread instead of a round-trip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Take back your own overclaims, out loud.&lt;/strong&gt; McNemar turned my "the prefix is the problem" into "the rendering is unstable". The weaker claim is the one the maintainer could act on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credit precisely.&lt;/strong&gt; The most important control in this story came from AlKor13. My PR is his idea turned into a gate, and the PR says so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't take work someone else was just handed.&lt;/strong&gt; #244 was Rukafuu's. Keeping my check narrow cost nothing and avoided stepping on them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't claim the fix.&lt;/strong&gt; I found it, reported it, and merged the tool that will say whether the retrain worked. That's the whole claim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;h1&gt;
  
  
  131 is open, and the retrain is pending. When it lands, &lt;code&gt;presentation_checks.py&lt;/code&gt; gives the first answer, and I'll run the labelled A–F and A/C/D before/after on top of it.
&lt;/h1&gt;

&lt;p&gt;What I posted the day it merged:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2102969840386687112-803" src="https://platform.twitter.com/embed/Tweet.html?id=2102969840386687112"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2102969840386687112-803');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2102969840386687112&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/NandhaKishorM/laya" rel="noopener noreferrer"&gt;https://github.com/NandhaKishorM/laya&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Issue #131: &lt;a href="https://github.com/NandhaKishorM/laya/issues/131" rel="noopener noreferrer"&gt;https://github.com/NandhaKishorM/laya/issues/131&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PR #259: &lt;a href="https://github.com/NandhaKishorM/laya/pull/259" rel="noopener noreferrer"&gt;https://github.com/NandhaKishorM/laya/pull/259&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Related: &lt;a href="https://github.com/NandhaKishorM/laya/issues/171" rel="noopener noreferrer"&gt;#171&lt;/a&gt;, &lt;a href="https://github.com/NandhaKishorM/laya/issues/244" rel="noopener noreferrer"&gt;#244&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;My data and repro scripts: &lt;a href="https://github.com/hiroki-abe-58/sokudan/blob/main/docs/baseline_ja.md" rel="noopener noreferrer"&gt;baseline_ja.md&lt;/a&gt;, &lt;a href="https://github.com/hiroki-abe-58/sokudan/blob/main/docs/baseline_en.md" rel="noopener noreferrer"&gt;baseline_en.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>Claude Opus 5.5 vs GPT-6 Astra vs GPT-6 Sol: the effort knob matters more than the model</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Wed, 23 Sep 2026 11:27:37 +0000</pubDate>
      <link>https://dev.to/genelab_999/claude-opus-55-vs-gpt-6-astra-vs-gpt-6-sol-the-effort-knob-matters-more-than-the-model-55gm</link>
      <guid>https://dev.to/genelab_999/claude-opus-55-vs-gpt-6-astra-vs-gpt-6-sol-the-effort-knob-matters-more-than-the-model-55gm</guid>
      <description>&lt;p&gt;On September 22, 2026, Anthropic shipped &lt;strong&gt;Claude Opus 5.5&lt;/strong&gt; and OpenAI shipped &lt;strong&gt;GPT-6 Sol&lt;/strong&gt; on the same day. OpenAI's flagship, &lt;strong&gt;GPT-6 Astra&lt;/strong&gt;, had landed three weeks earlier.&lt;/p&gt;

&lt;p&gt;If you tried to pick one from the launch posts, you probably noticed the problem: &lt;strong&gt;nobody compared against the right opponent.&lt;/strong&gt; Anthropic's table compares Opus 5.5 with GPT-6 Astra and the &lt;em&gt;previous&lt;/em&gt; GPT-5.6 Sol. OpenAI's Sol post compares with Claude Opus 5 and Fable 5.1, not Opus 5.5. Every chart is technically true and none of them answers "which one should I call from my code today?"&lt;/p&gt;

&lt;p&gt;So I went to &lt;a href="https://artificialanalysis.ai/" rel="noopener noreferrer"&gt;Artificial Analysis&lt;/a&gt; (AA), which ran all three through the same ten evaluations at every reasoning-effort level, and did the cost math.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Raw intelligence:&lt;/strong&gt; Opus 5.5 (max) scores &lt;strong&gt;58&lt;/strong&gt; on AA's Intelligence Index. Astra (max) scores &lt;strong&gt;53&lt;/strong&gt;, Sol (max) &lt;strong&gt;48&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List price:&lt;/strong&gt; Sol is cheapest per token, Astra is 2.5x Opus 5.5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-task cost flips the ranking:&lt;/strong&gt; at max effort Opus 5.5 emits ~4x more output tokens than Astra, so Opus max ($5.98/task) costs more than Astra max ($3.26/task).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The useful finding:&lt;/strong&gt; below ~$1.30 per task, Sol and Astra trade the lead. Above ~$1.30, Opus 5.5 is on top at every budget. &lt;strong&gt;Opus 5.5 at &lt;code&gt;high&lt;/code&gt; ($1.82) outscores Astra at &lt;code&gt;max&lt;/code&gt; ($3.26).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The effort setting moves your bill more than the model choice does.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The price sheet (and its fine print)
&lt;/h2&gt;

&lt;p&gt;Per 1M tokens, standard tier, as of September 23, 2026:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT-6 Sol&lt;/th&gt;
&lt;th&gt;GPT-6 Astra&lt;/th&gt;
&lt;th&gt;Claude Opus 5.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;$50.00&lt;/td&gt;
&lt;td&gt;$20.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache read&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$12.50&lt;/td&gt;
&lt;td&gt;$5.00 (5 min) / $8.00 (1 h)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt &amp;gt; 272K input tokens&lt;/td&gt;
&lt;td&gt;2x input &amp;amp; cache, 1.5x output, &lt;strong&gt;whole request&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;same as Sol&lt;/td&gt;
&lt;td&gt;no surcharge up to 1M&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things developers tend to miss:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sol and Opus 5.5 have the same cache-read price.&lt;/strong&gt; Anthropic says cache reads make up the majority of agentic and coding costs. The more your agent re-reads a cached prefix, the less the 2x headline gap matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI's long-context surcharge applies to the entire request&lt;/strong&gt;, not just the tokens past 272K. For a cache-heavy, long-context agent, Opus 5.5 can end up &lt;em&gt;cheaper&lt;/em&gt; than Sol per request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also: tokenizers differ between vendors (Anthropic itself notes its newer tokenizer produces roughly 30% more tokens for the same text than its older one). Per-token prices are not a common currency. Compare cost per task instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Tokens per task is the hidden multiplier
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fatu9cum6kw0bnhm9l2d5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fatu9cum6kw0bnhm9l2d5.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At max effort on AA's suite, Opus 5.5 emits ~119k output tokens per task. Astra emits ~27k, Sol ~31k. That's why Astra, at 2.5x Opus's per-token price, still comes out cheaper per task at the top settings.&lt;/p&gt;

&lt;p&gt;Here's the full grid from AA (Intelligence Index score / estimated USD per task):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;effort&lt;/th&gt;
&lt;th&gt;GPT-6 Sol&lt;/th&gt;
&lt;th&gt;GPT-6 Astra&lt;/th&gt;
&lt;th&gt;Claude Opus 5.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;34 / $0.13&lt;/td&gt;
&lt;td&gt;46 / $0.82&lt;/td&gt;
&lt;td&gt;42 / $0.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;40 / $0.25&lt;/td&gt;
&lt;td&gt;50 / $1.54&lt;/td&gt;
&lt;td&gt;51 / $1.34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;43 / $0.37&lt;/td&gt;
&lt;td&gt;51 / $1.73&lt;/td&gt;
&lt;td&gt;54 / $1.82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;44 / $0.53&lt;/td&gt;
&lt;td&gt;52 / $2.31&lt;/td&gt;
&lt;td&gt;56 / $3.46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;48 / $1.06&lt;/td&gt;
&lt;td&gt;53 / $3.26&lt;/td&gt;
&lt;td&gt;58 / $5.98&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that Opus 5.5 is &lt;em&gt;cheaper&lt;/em&gt; than Astra at low and medium, roughly equal at high, and more expensive at xhigh and max.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Buy intelligence by the dollar
&lt;/h2&gt;

&lt;p&gt;The question I actually care about: &lt;strong&gt;for a given per-task budget, which (model, effort) pair gives the highest score?&lt;/strong&gt; That's a tiny script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Artificial Analysis Intelligence Index v4.3.2 (Sept 22, 2026): (score, est. USD per task)
&lt;/span&gt;&lt;span class="n"&gt;AA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.37&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xhigh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.53&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.06&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.82&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.54&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.73&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xhigh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.31&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.26&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.34&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.82&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xhigh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.46&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.98&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;best_under&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;budget_usd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Highest-scoring (model, effort) whose estimated cost fits the per-task budget.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;affordable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;AA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;budget_usd&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;affordable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;neg_cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;affordable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ties go to the cheaper config
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;neg_cost&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.00&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;best_under&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$0.25 -&amp;gt; (('gpt-6-sol', 'medium'), 40, 0.25)
$0.60 -&amp;gt; (('gpt-6-sol', 'xhigh'), 44, 0.53)
$0.90 -&amp;gt; (('gpt-6-astra', 'low'), 46, 0.82)
$1.10 -&amp;gt; (('gpt-6-sol', 'max'), 48, 1.06)
$1.40 -&amp;gt; (('claude-opus-5-5', 'medium'), 51, 1.34)
$2.00 -&amp;gt; (('claude-opus-5-5', 'high'), 54, 1.82)
$4.00 -&amp;gt; (('claude-opus-5-5', 'xhigh'), 56, 3.46)
$6.00 -&amp;gt; (('claude-opus-5-5', 'max'), 58, 5.98)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plotted as "best score you can buy at each budget":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fadp0adgyo6jcwex9fta1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fadp0adgyo6jcwex9fta1.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Under ~$1.30/task:&lt;/strong&gt; Sol owns most of the range. Astra &lt;code&gt;low&lt;/code&gt; wins a narrow band around $0.82–$1.05.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over ~$1.30/task:&lt;/strong&gt; Opus 5.5 leads everywhere (it ties Astra once, briefly, at score 51).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sol tops out at 48 and Astra at 53.&lt;/strong&gt; Past those points, paying more buys nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At 10,000 tasks a month, this stops being academic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqaelx3b3mdgmw0eczdy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqaelx3b3mdgmw0eczdy2.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Opus 5.5 &lt;code&gt;high&lt;/code&gt; scores one point above Astra &lt;code&gt;max&lt;/code&gt; and costs &lt;strong&gt;$14,400/month less&lt;/strong&gt; in this illustration. Also note the gap between Opus 5.5 &lt;code&gt;medium&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt;: about 4.5x the cost for 7 more points.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Benchmarks have referees
&lt;/h2&gt;

&lt;p&gt;Anthropic's launch table shows Opus 5.5 at 66.4% on Terminal-Bench 4.0 vs Astra at 57.9%. The footnotes matter: Opus ran at &lt;code&gt;xhigh&lt;/code&gt; in Anthropic's setup, and Astra's number is OpenAI's own figure at &lt;code&gt;high&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When AA ran both in the same harness:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju3ny3j7da2ba7vnfabk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju3ny3j7da2ba7vnfabk.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;59.6% vs 59.6%.&lt;/strong&gt; A tie. This is the same lesson as Astra's ARC-AGI-3 score, which ARC Prize reported as 99.9% with a provider-specific harness and 62.7% with the standard one. Vendor tables are drawn under each vendor's best conditions. Read the footnotes, and prefer third-party runs that hold the harness constant.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Where each model actually wins
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fge5bgn1zwzeucbdtr82u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fge5bgn1zwzeucbdtr82u.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From AA at max effort:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT-6 Sol&lt;/th&gt;
&lt;th&gt;GPT-6 Astra&lt;/th&gt;
&lt;th&gt;Claude Opus 5.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Terminal-Bench 4.0&lt;/td&gt;
&lt;td&gt;43.9%&lt;/td&gt;
&lt;td&gt;59.6%&lt;/td&gt;
&lt;td&gt;59.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AutomationBench-AA&lt;/td&gt;
&lt;td&gt;61.6%&lt;/td&gt;
&lt;td&gt;69%&lt;/td&gt;
&lt;td&gt;69.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GDP.pdf (professional documents)&lt;/td&gt;
&lt;td&gt;24.8%&lt;/td&gt;
&lt;td&gt;31%&lt;/td&gt;
&lt;td&gt;26.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hallucination rate (lower is better)&lt;/td&gt;
&lt;td&gt;60.1%&lt;/td&gt;
&lt;td&gt;51%&lt;/td&gt;
&lt;td&gt;58.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GDPval-AA (44 occupations, Elo)&lt;/td&gt;
&lt;td&gt;1487&lt;/td&gt;
&lt;td&gt;1542&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1846&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opus 5.5&lt;/strong&gt; is far ahead on knowledge work (GDPval-AA is a ~300 Elo lead over Astra). AA's industry sub-indexes agree: finance, legal, and economics all favor Opus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Astra&lt;/strong&gt; leads on document reasoning and hallucinates least. In the vendors' own tables it also leads on Terminal-Bench Science (64.6% vs 58.7%, per Anthropic's table).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Astra has several claims Opus 5.5 simply hasn't been measured on&lt;/strong&gt;: FrontierMath Tier 4 (97.6%), ScreenSpot-Pro (92.7%), MRCR v2 at 512K–1M (96.3%), ExploitBench (100%). No number means no verdict either way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sol&lt;/strong&gt; is the fast, cheap one. It isn't built to win this table.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Latency
&lt;/h2&gt;

&lt;p&gt;AA, all at &lt;code&gt;medium&lt;/code&gt; effort:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT-6 Sol&lt;/th&gt;
&lt;th&gt;GPT-6 Astra&lt;/th&gt;
&lt;th&gt;Claude Opus 5.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time to first answer token&lt;/td&gt;
&lt;td&gt;~2.0 s&lt;/td&gt;
&lt;td&gt;~6.2 s&lt;/td&gt;
&lt;td&gt;~24.4 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output speed&lt;/td&gt;
&lt;td&gt;~114 tok/s&lt;/td&gt;
&lt;td&gt;~48 tok/s&lt;/td&gt;
&lt;td&gt;~75 tok/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per task&lt;/td&gt;
&lt;td&gt;~60 s&lt;/td&gt;
&lt;td&gt;~198 s&lt;/td&gt;
&lt;td&gt;~206 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a user-facing chat UI, Sol at &lt;code&gt;medium&lt;/code&gt; is in a different league. Crank Astra to &lt;code&gt;max&lt;/code&gt; and you're waiting over five minutes for the first answer token.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Integration gotchas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opus 5.5 can't run with thinking disabled.&lt;/strong&gt; Effort is your only depth control. Sol offers a &lt;code&gt;none&lt;/code&gt; reasoning setting (though AA found Sol's non-reasoning mode scored lower &lt;em&gt;and&lt;/em&gt; cost more per task than &lt;code&gt;low&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 5.5 routes some requests to other models.&lt;/strong&gt; When its safeguards trigger, most cybersecurity tasks are handled by Claude Opus 4.8. AA's numbers were measured with this default fallback on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Astra is rated "Critical" for cyber capability&lt;/strong&gt; under OpenAI's Preparedness Framework. It currently refuses advanced tasks like proof-of-concept exploits, and OpenAI's misalignment monitoring can stop a task outright in the API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mind the 272K line on OpenAI models.&lt;/strong&gt; A prompt at 280K tokens is billed very differently from one at 270K.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. A routing recipe you can steal
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Default to Opus 5.5 &lt;code&gt;medium&lt;/code&gt;&lt;/strong&gt; for knowledge work and hard agent tasks. It beats Sol's best score and matches Astra &lt;code&gt;high&lt;/code&gt;, for less.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalate to Opus 5.5 &lt;code&gt;high&lt;/code&gt;&lt;/strong&gt; only when a task fails your acceptance check, rather than starting at &lt;code&gt;max&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send high-volume, well-specified work to Sol&lt;/strong&gt; (classification, extraction, first-line support), especially if latency matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Astra in the pool&lt;/strong&gt; for document-heavy reasoning, low-hallucination requirements, science and GUI-heavy work, and verify on your own tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then measure the only metric that matters, &lt;strong&gt;cost per shipped output&lt;/strong&gt;, including human fix time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;cost_per_attempt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;  &lt;span class="c1"&gt;# USD, measured on YOUR tasks
&lt;/span&gt;    &lt;span class="n"&gt;accept_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;       &lt;span class="c1"&gt;# share of outputs you actually ship
&lt;/span&gt;    &lt;span class="n"&gt;fix_minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;       &lt;span class="c1"&gt;# human repair time per shipped output
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cost_per_accepted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hourly_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;model_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cost_per_attempt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept_rate&lt;/span&gt;
    &lt;span class="n"&gt;human_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fix_minutes&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hourly_rate&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;human_cost&lt;/span&gt;

&lt;span class="c1"&gt;# Hypothetical numbers, just to show the shape of the math
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cheap config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost_per_attempt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accept_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fix_minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pricier config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost_per_attempt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accept_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fix_minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cost_per_accepted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; per shipped output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   cheap config: $12.42 per shipped output
 pricier config: $5.58 per shipped output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With any realistic hourly rate, human review time dominates the model bill. That is exactly why the "cheapest model" and the "cheapest workflow" are often different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AA's tasks are not your tasks. Treat the scores as a map, not a forecast.&lt;/li&gt;
&lt;li&gt;Costs are AA's estimates, including typical cache-hit rates.&lt;/li&gt;
&lt;li&gt;A few per-benchmark values above are rounded integers as AA published them.&lt;/li&gt;
&lt;li&gt;AA re-based its index since Astra launched (v4.1.1 → v4.3.2). Scores from different versions aren't comparable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic, &lt;a href="https://www.anthropic.com/claude-opus-5-5" rel="noopener noreferrer"&gt;Introducing Claude Opus 5.5&lt;/a&gt; and &lt;a href="https://platform.claude.com/docs/en/about-claude/pricing" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;OpenAI, &lt;a href="https://openai.com/index/introducing-gpt-6-sol-and-luna/" rel="noopener noreferrer"&gt;Introducing GPT-6 Sol and Luna&lt;/a&gt;, &lt;a href="https://openai.com/index/gpt-6-astra/" rel="noopener noreferrer"&gt;GPT-6 Astra&lt;/a&gt;, &lt;a href="https://developers.openai.com/api/docs/models/gpt-6-sol" rel="noopener noreferrer"&gt;GPT-6 Sol model page&lt;/a&gt;, &lt;a href="https://developers.openai.com/api/docs/models/gpt-6-astra" rel="noopener noreferrer"&gt;GPT-6 Astra model page&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Artificial Analysis, &lt;a href="https://artificialanalysis.ai/models/releases/comparisons/claude-opus-5-5-vs-gpt-6-astra" rel="noopener noreferrer"&gt;Opus 5.5 vs Astra&lt;/a&gt;, &lt;a href="https://artificialanalysis.ai/models/releases/comparisons/gpt-6-sol-vs-claude-opus-5-5" rel="noopener noreferrer"&gt;Sol vs Opus 5.5&lt;/a&gt;, &lt;a href="https://artificialanalysis.ai/articles/benchmarking-gpt-6-astra" rel="noopener noreferrer"&gt;Benchmarking GPT-6 Astra&lt;/a&gt;, &lt;a href="https://artificialanalysis.ai/articles/claude-opus-5-5" rel="noopener noreferrer"&gt;Opus 5.5 article&lt;/a&gt;, &lt;a href="https://artificialanalysis.ai/articles/gpt-6-sol-and-luna-push-the-cost-efficiency-frontier" rel="noopener noreferrer"&gt;Sol and Luna article&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I researched and drafted this with help from Claude, which makes Anthropic a party to this comparison. Every figure comes from Artificial Analysis or the vendors' own pages, linked above.&lt;/em&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Qiita (Japanese): &lt;a href="https://qiita.com/GeneLab_999" rel="noopener noreferrer"&gt;https://qiita.com/GeneLab_999&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Zenn (Japanese): &lt;a href="https://zenn.dev/genelab_999" rel="noopener noreferrer"&gt;https://zenn.dev/genelab_999&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;YouTube: &lt;a href="https://www.youtube.com/@geneLab_999" rel="noopener noreferrer"&gt;https://www.youtube.com/@geneLab_999&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;X: &lt;a href="https://x.com/geneLab_999" rel="noopener noreferrer"&gt;https://x.com/geneLab_999&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>openai</category>
      <category>claude</category>
    </item>
    <item>
      <title>I built a Jev-style decision model for Japanese in two days. Claude Code A/B-tested my architecture and killed it.</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Tue, 22 Sep 2026 06:35:24 +0000</pubDate>
      <link>https://dev.to/genelab_999/i-built-a-jev-style-decision-model-for-japanese-in-two-days-claude-code-ab-tested-my-architecture-4bi5</link>
      <guid>https://dev.to/genelab_999/i-built-a-jev-style-decision-model-for-japanese-in-two-days-claude-code-ab-tested-my-architecture-4bi5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeSafe's Jev introduced "System One" models: no text generation, you send a state and typed questions, you get typed answers with calibrated probabilities in one forward pass. Open reproductions followed within weeks. The most complete one is Laya (ModernBERT-large, 421M).&lt;/li&gt;
&lt;li&gt;I benchmarked &lt;code&gt;laya-multilingual&lt;/code&gt; on 300 Japanese business emails. &lt;code&gt;choice&lt;/code&gt; works. &lt;code&gt;score&lt;/code&gt; (ordinal) and &lt;code&gt;bool&lt;/code&gt; are below the majority-class baseline.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;score&lt;/code&gt; failure is a positional bias: &lt;strong&gt;the first-listed option is chosen 0 to 1 times out of 300, under five different orderings and wordings.&lt;/strong&gt; It reproduces in English (0/290). The English &lt;code&gt;laya&lt;/code&gt; checkpoint does not have it. Filed as &lt;a href="https://github.com/NandhaKishorM/laya/issues/131" rel="noopener noreferrer"&gt;NandhaKishorM/laya#131&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I built a Japanese one, &lt;code&gt;sokudan-ja-310m&lt;/code&gt;, on ModernBERT-Ja. On the same 300 items with unseen schemas it beats laya-multilingual on all three primitives, three seeds. Model, code, benchmark and training-data recipe are public.&lt;/li&gt;
&lt;li&gt;Day 1 produced a model that ignored the input text. Day 2 fixed the data and it still failed. The actual cause was my architecture. Claude Code, which I had handed the spec to, ran the A/B that proved it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Model: &lt;a href="https://huggingface.co/GeneLab/sokudan-ja-310m" rel="noopener noreferrer"&gt;https://huggingface.co/GeneLab/sokudan-ja-310m&lt;/a&gt;&lt;br&gt;
Code: &lt;a href="https://github.com/hiroki-abe-58/sokudan" rel="noopener noreferrer"&gt;https://github.com/hiroki-abe-58/sokudan&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a System One model is
&lt;/h2&gt;

&lt;p&gt;If you have ever asked an LLM "which department should handle this ticket, answer with one word" and then written a regex to parse the reply, you know the problem. You are using a text generator as a classifier and paying for it in latency, cost and parse failures.&lt;/p&gt;

&lt;p&gt;A System One model skips the generation. Three question types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;asks&lt;/th&gt;
&lt;th&gt;returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;choice&lt;/td&gt;
&lt;td&gt;pick one of N options&lt;/td&gt;
&lt;td&gt;choice, per-option probabilities, confidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;score&lt;/td&gt;
&lt;td&gt;rate on an ordinal rubric&lt;/td&gt;
&lt;td&gt;score, distribution, confidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bool (Jev calls it noul)&lt;/td&gt;
&lt;td&gt;is this statement true&lt;/td&gt;
&lt;td&gt;P(true)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Multiple questions go in one request and are evaluated against the same state independently. Laya implements this as an encoder with one &lt;code&gt;[MASK]&lt;/code&gt; token per option; the hidden state at each mask is scored and softmaxed within the question. Because the answer space is defined at request time, new schemas need no retraining. On an RTX 5090 it runs at 22 ms per item.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benchmark
&lt;/h2&gt;

&lt;p&gt;I generated 300 Japanese business emails with a local LLM (Qwen3 30B-A3B), &lt;strong&gt;label-conditioned&lt;/strong&gt;: the prompt says "write a slightly irritated billing inquiry that hints at cancellation", so the generation conditions are the gold labels. No annotation. Three questions per document: 4-way department routing (&lt;code&gt;choice&lt;/code&gt;), 3-level urgency (&lt;code&gt;score&lt;/code&gt;), "hints at churn" (&lt;code&gt;bool&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Baselines, all on the same 300 items with the same scoring code: &lt;code&gt;laya-multilingual&lt;/code&gt;, &lt;code&gt;laya&lt;/code&gt; (English checkpoint fed Japanese), majority class, random, and the generating LLM itself as a classifier (an upper bound, not a fair comparison, since it wrote the data).&lt;/p&gt;

&lt;p&gt;I did not benchmark Jev itself. TypeSafe's Master Customer Agreement (2.3(b)) prohibits using the service or its output to develop a similar product, and this is one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results for laya-multilingual
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;choice acc&lt;/th&gt;
&lt;th&gt;score RPS (lower is better)&lt;/th&gt;
&lt;th&gt;score acc&lt;/th&gt;
&lt;th&gt;bool acc&lt;/th&gt;
&lt;th&gt;bool AUROC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;laya-multilingual&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.747&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.232&lt;/td&gt;
&lt;td&gt;0.443&lt;/td&gt;
&lt;td&gt;0.543&lt;/td&gt;
&lt;td&gt;0.523&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;majority class&lt;/td&gt;
&lt;td&gt;0.380&lt;/td&gt;
&lt;td&gt;0.197&lt;/td&gt;
&lt;td&gt;0.460&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.703&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;random&lt;/td&gt;
&lt;td&gt;0.253&lt;/td&gt;
&lt;td&gt;0.201&lt;/td&gt;
&lt;td&gt;0.403&lt;/td&gt;
&lt;td&gt;0.513&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;choice&lt;/code&gt; is fine: twice the majority baseline, three times random. If you need multi-class routing in Japanese, this checkpoint works today.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;score&lt;/code&gt; is worse than always predicting the majority level. The confusion matrix explains why:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;gold \ predicted&lt;/th&gt;
&lt;th&gt;not urgent&lt;/th&gt;
&lt;th&gt;soon&lt;/th&gt;
&lt;th&gt;work is blocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;not urgent (77)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;soon (138)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;work is blocked (85)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The lowest level is never predicted. My first guesses were "weak on Japanese negation" or "ordinal training is broken". Five more conditions ruled both out:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;condition&lt;/th&gt;
&lt;th&gt;options (in listed order)&lt;/th&gt;
&lt;th&gt;first option chosen&lt;/th&gt;
&lt;th&gt;argmax counts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A original&lt;/td&gt;
&lt;td&gt;not urgent / soon / blocked&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0&lt;/strong&gt; / 300&lt;/td&gt;
&lt;td&gt;[0, 167, 133]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B reversed&lt;/td&gt;
&lt;td&gt;blocked / soon / not urgent&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0&lt;/strong&gt; / 300&lt;/td&gt;
&lt;td&gt;[0, 50, 250]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C relabeled&lt;/td&gt;
&lt;td&gt;low / mid / high&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1&lt;/strong&gt; / 300&lt;/td&gt;
&lt;td&gt;[1, 291, 8]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D relabeled, reversed&lt;/td&gt;
&lt;td&gt;high / mid / low&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1&lt;/strong&gt; / 300&lt;/td&gt;
&lt;td&gt;[1, 0, 299]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E four levels&lt;/td&gt;
&lt;td&gt;not at all / not urgent / soon / blocked&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0&lt;/strong&gt; / 300&lt;/td&gt;
&lt;td&gt;[0, 78, 37, 185]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Compare B and D. The last-listed option means "not urgent" in one and "high" in the other. Both attract most of the mass (250 and 299). The model is answering by slot, not by label.&lt;/p&gt;

&lt;p&gt;Then I ran the same five conditions on 290 English emails, because English is a training language for this checkpoint and "it can't read the input" should not apply:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;model&lt;/th&gt;
&lt;th&gt;Japanese (n=300)&lt;/th&gt;
&lt;th&gt;English (n=290)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;laya-multilingual&lt;/td&gt;
&lt;td&gt;0, 0, 1, 1, 0&lt;/td&gt;
&lt;td&gt;0, 0, 0, 0, 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;laya (English checkpoint)&lt;/td&gt;
&lt;td&gt;13, 56, 8, 1, 110&lt;/td&gt;
&lt;td&gt;65, 74, 0, 5, 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Still zero. In English, laya-multilingual also gets &lt;code&gt;score&lt;/code&gt; RPS 0.340 (random is 0.197) and &lt;code&gt;bool&lt;/code&gt; AUROC 0.355, which is below 0.5, meaning the ranking is inverted. The English checkpoint picks the first option 22 to 26 percent of the time under the same conditions. This is not a language gap; it is something specific to the multilingual checkpoint.&lt;/p&gt;

&lt;p&gt;Practical consequence: ordinal rubrics almost always list the lowest level first. On this checkpoint, &lt;code&gt;score&lt;/code&gt; will almost never return the lowest level regardless of input.&lt;/p&gt;

&lt;p&gt;I verified my harness against the official &lt;code&gt;laya&lt;/code&gt; package with &lt;code&gt;laya.load()&lt;/code&gt; / &lt;code&gt;agent.predict()&lt;/code&gt; straight from the README; probabilities match to float precision. Repro: &lt;a href="https://github.com/hiroki-abe-58/sokudan/blob/main/docs/baseline_en.md" rel="noopener noreferrer"&gt;docs/baseline_en.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Temperature scaling, for the record, fixes ECE (0.148 to 0.087) and changes no argmax at all. As expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I built one
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sokudan-ja-310m&lt;/code&gt;: &lt;code&gt;sbintuitions/modernbert-ja-310m&lt;/code&gt; backbone (MIT), full fine-tune, one &lt;code&gt;&amp;lt;mask&amp;gt;&lt;/code&gt; per option, softmax within the question. Two design choices worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;score&lt;/code&gt; is not a multi-class softmax. It uses a cumulative-link parameterization that keeps the CDF monotone for any number of levels K, decided at request time: each level's marker contributes a non-negative increment via softplus, and P(y &amp;gt; k) is a sigmoid over the running sum. K=2 and K=7 share the same head.&lt;/li&gt;
&lt;li&gt;All training data is gold-labeled synthetic data from the same label-conditioned generation. No Laya or Jev outputs anywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Results on the same 300 items, three seeds, mean ± SD. The benchmark's three schemas were never in training:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;choice acc&lt;/th&gt;
&lt;th&gt;score RPS&lt;/th&gt;
&lt;th&gt;score acc&lt;/th&gt;
&lt;th&gt;bool acc&lt;/th&gt;
&lt;th&gt;bool AUROC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;sokudan-ja-310m&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.847 ± 0.009&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.090 ± 0.023&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.763 ± 0.088&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.788 ± 0.010&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.789 ± 0.043&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;laya-multilingual&lt;/td&gt;
&lt;td&gt;0.747&lt;/td&gt;
&lt;td&gt;0.232&lt;/td&gt;
&lt;td&gt;0.443&lt;/td&gt;
&lt;td&gt;0.543&lt;/td&gt;
&lt;td&gt;0.523&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;majority class&lt;/td&gt;
&lt;td&gt;0.380&lt;/td&gt;
&lt;td&gt;0.197&lt;/td&gt;
&lt;td&gt;0.460&lt;/td&gt;
&lt;td&gt;0.703&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Seed variance on &lt;code&gt;score&lt;/code&gt; accuracy is large (0.663 / 0.800 / 0.827). The distributed weights are seed 0, which is the worst of the three on that metric and the best on bool AUROC. Seed 0 was designated before any of the three finished training. Seeds 1 and 2 are revisions in the same repo.&lt;/p&gt;

&lt;p&gt;Under the five position-bias conditions, sokudan picks the first option 45 to 98 times out of 300 (i.e. normally), across all seeds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I actually want to write about
&lt;/h2&gt;

&lt;p&gt;Day 1 ended with a model whose &lt;code&gt;bool&lt;/code&gt; AUROC on the benchmark was 0.513. Diagnostics showed something worse than "weak": &lt;strong&gt;replacing the input text with an empty string improved bool accuracy&lt;/strong&gt; (0.623 to 0.703). The model was reading the question and emitting a prior. My training data's bool questions were all mechanical derivations ("does this document belong to category X", "is urgency at least level k") and none required reading for intent. "Hints at churn" is an intent question. You cannot transfer a skill you never trained.&lt;/p&gt;

&lt;p&gt;Day 2 morning: Claude Code and I redesigned the data. Twenty-four attributes baked into the generation prompt as conditions, split into three tiers: surface (mentions a deadline), explicit attitude (states dissatisfaction), implicit intent (implies it is about to decline). Five attributes held out entirely so we had an unseen-schema validation set that was not the benchmark. Claude Code caught two things in the verification pass that I would not have: implicit-intent attributes imply each other, so independent 50/50 sampling creates false labels that are actually true; and discarding verifier disagreements removes hard cases asymmetrically, teaching "always yes". Both fixed.&lt;/p&gt;

&lt;p&gt;Day 2 afternoon: trained on the new data. Held-out bool AUROC 0.509. Every held-out attribute at chance, including "ends with a question mark". And &lt;code&gt;choice&lt;/code&gt; and &lt;code&gt;score&lt;/code&gt; were worse than Day 1 despite 2.6 times the data.&lt;/p&gt;

&lt;p&gt;Here is the diagnostic that mattered. On attributes the model &lt;em&gt;had&lt;/em&gt; trained on, evaluated on unseen documents, only 4 of 14 were above 0.7, and the top two were "contains numbers" and "mentions a deadline". Lexical. Every attitude and intent attribute sat at 0.5 even though the model had seen thousands of examples of each. Before asking why it did not transfer, we had to ask why it had not learned.&lt;/p&gt;

&lt;p&gt;My architecture encoded the state and the question separately and merged them in a two-layer cross-attention head. The selling point was that the state is encoded once per request and broadcast to all questions, so latency does not grow with question count. I had rejected Laya's joint layout (question and state in one sequence) on the grounds that ModernBERT has global attention only every third layer and a 128-token local window, so a question block placed far from the state could not see it.&lt;/p&gt;

&lt;p&gt;Claude Code proposed the A/B and ran it: same data, same mix, same epochs, same learning rate, the only change being joint encoding with no cross-attention head.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;cross-attention (mine)&lt;/th&gt;
&lt;th&gt;joint (Laya's layout)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;held-out bool AUROC, unseen schema&lt;/td&gt;
&lt;td&gt;0.506&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.872&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;implicit-intent tier&lt;/td&gt;
&lt;td&gt;0.486&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.786&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;explicit-attitude tier&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.995&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trained attributes on unseen docs&lt;/td&gt;
&lt;td&gt;4 of 14 above 0.7&lt;/td&gt;
&lt;td&gt;14 of 14 between 0.96 and 1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;seconds per epoch&lt;/td&gt;
&lt;td&gt;464&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;330&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ablating the state (empty or shuffled) drops joint to 0.485 / 0.504. It is reading the text.&lt;/p&gt;

&lt;p&gt;My local-attention argument was correct and irrelevant. The mean sequence length in this data is 160 tokens. The "question block at position 3000" I was worried about never occurs. Meanwhile, the only held-out attribute joint failed was "ends with a question mark" (0.688), which is a positional question and exactly where a 128-token window hurts. The concern was real; I had aimed it at the wrong place.&lt;/p&gt;

&lt;p&gt;I retracted the design, the latency claim, and the paragraph in the architecture doc that explained why joint would not work. v0.1 ships joint. Claude Code wrote the retraction section with the A/B numbers and a note on where the original argument's premise failed.&lt;/p&gt;

&lt;p&gt;Two things I put in the spec that earned their place: &lt;strong&gt;never fabricate a number, write TBD&lt;/strong&gt; (no estimate ever leaked into a doc), and &lt;strong&gt;stop at the gate&lt;/strong&gt; (three sub-majority checkpoints were stopped before publication). One thing I did not put in the spec: permission to refute the spec's author. It did that on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On the benchmark, bool under-predicts true (mean P(true) 0.125 vs a gold rate of 0.297). AUROC 0.789, so the ranking works; set your threshold to your prior. Temperature does not shift this.&lt;/li&gt;
&lt;li&gt;Calibration helps choice and bool ECE and hurts score RPS (0.090 to 0.149). Default is uncalibrated; &lt;code&gt;temperatures.json&lt;/code&gt; is included; refit on your own validation set.&lt;/li&gt;
&lt;li&gt;Long inputs: held-out bool AUROC drops from 0.904 on short documents to 0.730 at 400 to 800 tokens. Local attention.&lt;/li&gt;
&lt;li&gt;Latency scales with question count under joint encoding. &lt;code&gt;usage.backbone_passes&lt;/code&gt; in the response tells you how many.&lt;/li&gt;
&lt;li&gt;Single benchmark, 300 items, all synthetic from one LLM. Real-data validation is next.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Model: &lt;a href="https://huggingface.co/GeneLab/sokudan-ja-310m" rel="noopener noreferrer"&gt;https://huggingface.co/GeneLab/sokudan-ja-310m&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code, bench_ja, bench_en, ablations, retracted design: &lt;a href="https://github.com/hiroki-abe-58/sokudan" rel="noopener noreferrer"&gt;https://github.com/hiroki-abe-58/sokudan&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laya issue: &lt;a href="https://github.com/NandhaKishorM/laya/issues/131" rel="noopener noreferrer"&gt;https://github.com/NandhaKishorM/laya/issues/131&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TypeSafe docs: &lt;a href="https://docs.typesafe.ai" rel="noopener noreferrer"&gt;https://docs.typesafe.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laya: &lt;a href="https://huggingface.co/convaiinnovations/laya" rel="noopener noreferrer"&gt;https://huggingface.co/convaiinnovations/laya&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ModernBERT-Ja: &lt;a href="https://huggingface.co/sbintuitions/modernbert-ja-310m" rel="noopener noreferrer"&gt;https://huggingface.co/sbintuitions/modernbert-ja-310m&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>nlp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🛠️ I Built a One-Click ComfyUI Setup for RTX 5090 on Windows — No WSL2, No Docker</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Mon, 02 Mar 2026 15:18:28 +0000</pubDate>
      <link>https://dev.to/genelab_999/i-built-a-one-click-comfyui-setup-for-rtx-5090-on-windows-no-wsl2-no-docker-4n1i</link>
      <guid>https://dev.to/genelab_999/i-built-a-one-click-comfyui-setup-for-rtx-5090-on-windows-no-wsl2-no-docker-4n1i</guid>
      <description>&lt;p&gt;I bought an RTX 5090. 32GB VRAM. The most powerful consumer GPU on the planet.&lt;/p&gt;

&lt;p&gt;Then I tried to run ComfyUI on Windows. It broke immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RuntimeError: sm_120 is not compatible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Three days later, I had a fully working solution. I packaged it and open-sourced it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell" rel="noopener noreferrer"&gt;ComfyUI-Win-Blackwell&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the whole story.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why RTX 50-series Breaks Everything
&lt;/h2&gt;

&lt;p&gt;NVIDIA's Blackwell architecture (RTX 5090/5080/5070) uses a new compute capability code called &lt;code&gt;sm_120&lt;/code&gt;. The problem? PyTorch's stable release doesn't include kernels for it.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pip install torch&lt;/code&gt; → &lt;strong&gt;doesn't work on Blackwell&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You need PyTorch nightly with CUDA 13.0 (cu130)&lt;/li&gt;
&lt;li&gt;But then &lt;strong&gt;xformers&lt;/strong&gt; (the standard ComfyUI speed boost) forces PyTorch back to stable&lt;/li&gt;
&lt;li&gt;And custom nodes silently pull stable PyTorch through their dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a dependency trap. Every fix creates a new problem.&lt;/p&gt;


&lt;h2&gt;
  
  
  The 5 Rules I Discovered
&lt;/h2&gt;

&lt;p&gt;After 3 days of trial and error, I distilled everything into 5 rules. Break any one of them and your environment dies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: Use PyTorch nightly cu130&lt;/strong&gt; — stable doesn't have sm_120 kernels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 2: Never install xformers&lt;/strong&gt; — it force-downgrades PyTorch to stable. This is the trap that got me twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 3: Strip &lt;code&gt;torch&lt;/code&gt; from every requirements.txt&lt;/strong&gt; — custom nodes list torch as a dependency, and pip will happily replace your nightly build with stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 4: Verify PyTorch after every custom node install&lt;/strong&gt; — run &lt;code&gt;python -c "import torch; print(torch.__version__)"&lt;/code&gt; and check that it still says &lt;code&gt;cu130&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 5: Clear proxy environment variables&lt;/strong&gt; — system proxies block pip and git silently on Windows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Pro Tip:&lt;/strong&gt; Rule 2 was the hardest to figure out. xformers installs &lt;em&gt;successfully&lt;/em&gt;, ComfyUI &lt;em&gt;starts&lt;/em&gt; fine, and then crashes mid-inference with &lt;code&gt;sm_120 is not compatible&lt;/code&gt;. You don't even realize PyTorch was downgraded until you check the version.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I automated all 5 rules into a one-click setup:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ComfyUI-Win-Blackwell
&lt;span class="c"&gt;# Double-click setup.bat — done in ~20 minutes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What &lt;code&gt;setup.bat&lt;/code&gt; handles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.13 environment&lt;/li&gt;
&lt;li&gt;PyTorch nightly cu130 (not stable, not cu128)&lt;/li&gt;
&lt;li&gt;triton-windows + torch.compile (replaces xformers)&lt;/li&gt;
&lt;li&gt;ComfyUI core + custom dependencies (with torch stripped out)&lt;/li&gt;
&lt;li&gt;28 verified custom nodes&lt;/li&gt;
&lt;li&gt;Post-install verification that cu130 is still intact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also built companion tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;verify_env.py&lt;/code&gt; — Blackwell-specific environment checker (sm_120, cu130, Triton, torch.compile)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fix_windows_compat.py&lt;/code&gt; — Converts Linux workflow JSON paths to Windows format, replaces SageAttention with SDPA&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update.bat&lt;/code&gt; — Updates everything while preserving Blackwell compatibility&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  What I Verified
&lt;/h2&gt;

&lt;p&gt;I tested 28 custom nodes one by one. Install → check PyTorch version → run test → record result. That was the most tedious part.&lt;/p&gt;

&lt;p&gt;I also tested 5 Image-to-Video pipelines on 32GB VRAM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HunyuanVideo 1.5 I2V&lt;/strong&gt; (8.3B params, ~16GB) — Smooth. My top recommendation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kandinsky 5.0 Lite I2V&lt;/strong&gt; (2B, ~4GB) — Very smooth. Great for quick tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LTX-2 I2V&lt;/strong&gt; (19B, ~25GB) — Works in FP8. Tight but fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LongCat-Video TI2V&lt;/strong&gt; (13.6B, ~14.5GB) — Works with adjustments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kandinsky 5.0 Pro I2V&lt;/strong&gt; (19B, ~40GB) — Needs CPU offload. Slow.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Why Not Just Use WSL2 or Docker?
&lt;/h2&gt;

&lt;p&gt;The short answer: performance.&lt;/p&gt;

&lt;p&gt;Loading safetensors through WSL2's NTFS translation layer is noticeably slower. Docker has the same issue plus additional setup complexity. For a tool like ComfyUI where you're iterating on workflows and loading large models frequently, native Windows file I/O makes a real difference.&lt;/p&gt;

&lt;p&gt;Also, most AI artists using ComfyUI on Windows aren't Docker experts. A &lt;code&gt;.bat&lt;/code&gt; file they can double-click is the right UX.&lt;/p&gt;


&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;If you have an RTX 5090/5080/5070 and want to run ComfyUI on Windows without WSL2 or Docker, give it a try:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell" rel="noopener noreferrer"&gt;github.com/hiroki-abe-58/ComfyUI-Win-Blackwell&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hiroki-abe-58" rel="noopener noreferrer"&gt;
        hiroki-abe-58
      &lt;/a&gt; / &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell" rel="noopener noreferrer"&gt;
        ComfyUI-Win-Blackwell
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ComfyUI for GeForce RTX 50-Series (Blackwell)&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The first fully documented, Windows-native ComfyUI setup for NVIDIA GeForce RTX 5090/5080/5070 (Blackwell architecture, sm_120) with CUDA 13.0.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Other languages:&lt;/strong&gt; &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell/README_ja.md" rel="noopener noreferrer"&gt;日本語&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell/README_zh.md" rel="noopener noreferrer"&gt;中文&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell/README_ko.md" rel="noopener noreferrer"&gt;한국어&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What Makes This Special&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;RTX 50-series GPUs (Blackwell, Compute Capability sm_120) are &lt;strong&gt;not supported by PyTorch stable releases&lt;/strong&gt; as of early 2026. Running ComfyUI on these GPUs requires specific versions and workarounds that are not documented anywhere else in a single, reproducible package.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Technical Highlights&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Feature&lt;/th&gt;

&lt;th&gt;Details&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;GPU Architecture&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;NVIDIA Blackwell (sm_120) -- RTX 5090 / 5080 / 5070&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;CUDA Version&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;13.0 (cu130) -- the latest CUDA runtime&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;Nightly cu130 build (not stable, not cu128)&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;3.13 (latest)&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Triton&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;triton-windows fork (official Triton is Linux-only)&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;xformers&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;Deliberately excluded (causes PyTorch downgrade)&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Custom Nodes&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;28 verified nodes including video &amp;amp; music generation&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Platform&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;Windows Native (no WSL2, no Docker required)&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Why This Is Unique&lt;/h3&gt;

&lt;/div&gt;


&lt;ol&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Blackwell + Windows Native +&lt;/strong&gt;…&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/hiroki-abe-58/ComfyUI-Win-Blackwell" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;MIT licensed. Stars and PRs welcome — especially if you verify additional custom nodes on Blackwell hardware.&lt;/p&gt;

&lt;p&gt;Have you tried running AI tools on RTX 50-series? What was your experience? Let me know in the comments! 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this helpful, consider following me for more AI + GPU content!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;📝 Japanese version: &lt;a href="https://qiita.com/GeneLab_999" rel="noopener noreferrer"&gt;Qiita&lt;/a&gt; / &lt;a href="https://zenn.dev/rick_lyric" rel="noopener noreferrer"&gt;Zenn&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;🐦 Follow me on X: &lt;a href="https://x.com/geneLab_999" rel="noopener noreferrer"&gt;@geneLab_999&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;💻 GitHub: &lt;a href="https://github.com/hiroki-abe-58" rel="noopener noreferrer"&gt;hiroki-abe-58&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>comfyui</category>
      <category>ai</category>
      <category>showdev</category>
      <category>python</category>
    </item>
    <item>
      <title>How I Run 6 AI Services Simultaneously on RTX 5090 + WSL2 + Docker (And You Can Too)</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Sat, 21 Feb 2026 22:53:44 +0000</pubDate>
      <link>https://dev.to/genelab_999/how-i-run-6-ai-services-simultaneously-on-rtx-5090-wsl2-docker-and-you-can-too-539a</link>
      <guid>https://dev.to/genelab_999/how-i-run-6-ai-services-simultaneously-on-rtx-5090-wsl2-docker-and-you-can-too-539a</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi3gqfdvscvd8l33emrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi3gqfdvscvd8l33emrs.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a multi-service local AI stack (image gen, video gen, voice synthesis, voice cloning) running on RTX 5090 via WSL2 Docker. The key breakthrough was solving the GPU driver passthrough layer that nobody documented. Here's the architecture, the critical &lt;code&gt;gpu-run&lt;/code&gt; function, and everything I learned the hard way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Nobody Solved
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pxxeronj3qvsolju6yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pxxeronj3qvsolju6yb.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In August 2025, I bought an RTX 5090. Blackwell architecture. 32GB GDDR7. Compute capability &lt;code&gt;sm_120&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And nobody could make it work with WSL2 + Docker + PyTorch.&lt;/p&gt;

&lt;p&gt;The issue wasn't any single component. &lt;code&gt;nvidia-smi&lt;/code&gt; worked fine in containers. &lt;code&gt;libcuda.so.1&lt;/code&gt; loaded correctly. But PyTorch kept returning &lt;code&gt;torch.cuda.is_available() = False&lt;/code&gt; with a cryptic &lt;code&gt;Error 500: named symbol not found&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I spent roughly 40 hours debugging. Here's what I found, and how I turned it into a production multi-service AI environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Root Cause
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbrbuumujv100b3qcazv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbrbuumujv100b3qcazv.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The failure point was in the &lt;strong&gt;interaction layer&lt;/strong&gt; between WSL2's driver mounting and Docker's GPU runtime.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;--gpus all&lt;/code&gt; in a Docker container on WSL2, the NVIDIA Container Toolkit mounts &lt;code&gt;/usr/lib/wsl/lib&lt;/code&gt; into the container. This directory contains &lt;code&gt;libcuda.so.1&lt;/code&gt; and friends. For most GPUs, this is enough.&lt;/p&gt;

&lt;p&gt;For the RTX 5090, it's not.&lt;/p&gt;

&lt;p&gt;The actual driver binaries live in a &lt;strong&gt;separate directory&lt;/strong&gt;: &lt;code&gt;/usr/lib/wsl/drivers/nvmdi.inf_amd64_&amp;lt;hash&amp;gt;&lt;/code&gt;. This directory contains the real &lt;code&gt;libcuda.so.1.1&lt;/code&gt;, &lt;code&gt;libnvdxgdmal.so.1&lt;/code&gt;, &lt;code&gt;libnvidia-ptxjitcompiler.so.1&lt;/code&gt;, and other dependencies that the PyTorch CUDA runtime needs to initialize the Blackwell architecture.&lt;/p&gt;

&lt;p&gt;Without mounting this directory AND setting &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; to include it, PyTorch's CUDA initialization hits a dead end -- it finds &lt;code&gt;libcuda.so.1&lt;/code&gt; but can't resolve the sm_120-specific symbols.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: &lt;code&gt;gpu-run&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here's the function that makes everything work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpu-run &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;D BN
  &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /usr/lib/wsl/drivers/nvmdi.inf_amd64_&lt;span class="k"&gt;*&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="nv"&gt;BN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$D&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Using driver path: &lt;/span&gt;&lt;span class="nv"&gt;$D&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--gpus&lt;/span&gt; all &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /usr/lib/wsl/lib:/usr/lib/wsl/lib:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$D&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:/usr/lib/wsl/drivers/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/wsl/lib:/usr/lib/wsl/drivers/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Finds the driver directory dynamically&lt;/strong&gt; -- the hash suffix changes with driver updates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mounts both WSL lib paths&lt;/strong&gt; -- the standard &lt;code&gt;/usr/lib/wsl/lib&lt;/code&gt; AND the driver-specific directory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sets &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;&lt;/strong&gt; to prioritize these paths for symbol resolution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Verification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;gpu-run.sh
gpu-run torch-wsl-cu128 python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"
import torch
print('PyTorch:', torch.__version__)
print('CUDA available:', torch.cuda.is_available())
print('GPU:', torch.cuda.get_device_name(0))
print('VRAM:', torch.cuda.get_device_properties(0).total_mem // 1024**3, 'GB')
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using driver path: /usr/lib/wsl/drivers/nvmdi.inf_amd64_fb80e95fa979ce23
PyTorch: 2.9.0.dev20250812+cu128
CUDA available: True
GPU: NVIDIA GeForce RTX 5090
VRAM: 32 GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Dockerfile Template
&lt;/h2&gt;

&lt;p&gt;Every AI service in my stack uses a variation of this base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nvidia/cuda:12.8.0-devel-ubuntu22.04&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; TZ=Asia/Tokyo&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DEBIAN_FRONTEND=noninteractive&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PYTHONUNBUFFERED=1&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; CUDA_HOME=/usr/local/cuda&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-snf&lt;/span&gt; /usr/share/zoneinfo/&lt;span class="nv"&gt;$TZ&lt;/span&gt; /etc/localtime &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$TZ&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/timezone

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    python3 python3-pip python3-dev git ffmpeg ca-certificates &lt;span class="se"&gt;\
&lt;/span&gt;    build-essential cmake ninja-build libsndfile1 &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nv"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.26.4

&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;--pre&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    torch torchvision torchaudio &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/nightly/cu128

&lt;span class="k"&gt;RUN &lt;/span&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import torch; print('PyTorch:', torch.__version__); assert 'cu128' in torch.__version__"&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nvidia/cuda:12.8.0-devel-ubuntu22.04&lt;/code&gt;&lt;/strong&gt; -- CUDA 12.8 is the minimum for sm_120. Using &lt;code&gt;devel&lt;/code&gt; (not &lt;code&gt;runtime&lt;/code&gt;) because some AI frameworks compile CUDA extensions at build time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyTorch nightly cu128&lt;/strong&gt; -- as of early 2026, stable PyTorch still has incomplete Blackwell support. Nightly cu128 is non-negotiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;numpy pinned to 1.26.4&lt;/strong&gt; -- numpy 2.x breaks several AI frameworks that haven't updated their C extensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install torch LAST&lt;/strong&gt; -- many &lt;code&gt;requirements.txt&lt;/code&gt; files include torch. If you install dependencies first, they'll pull in a stable torch that doesn't support sm_120. Always install your carefully selected torch version as the final step.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Docker Compose Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugigk21n3lqhq2cywzsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugigk21n3lqhq2cywzsj.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how six AI services coexist in a single &lt;code&gt;compose.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;comfyui&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./apps/comfyui&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;comfyui:wsl-cu12&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comfyui"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/wsl/drivers/${WSL_DRV_BN}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,max_split_size_mb:512&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CUDA_VISIBLE_DEVICES=0&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/usr/lib/wsl/lib:/usr/lib/wsl/lib:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${WSL_DRV_DIR}:/usr/lib/wsl/drivers/${WSL_DRV_BN}:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data/comfyui-models:/app/models&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./shared/models:/shared/models:ro&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8188:8188"&lt;/span&gt;
    &lt;span class="na"&gt;ipc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host&lt;/span&gt;
    &lt;span class="na"&gt;ulimits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
      &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;67108864&lt;/span&gt;

  &lt;span class="na"&gt;sbv2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./apps/sbv2&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sbv2:wsl-cu12&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sbv2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LD_LIBRARY_PATH=/usr/lib/wsl/lib:/usr/lib/wsl/drivers/${WSL_DRV_BN}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,max_split_size_mb:512&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/usr/lib/wsl/lib:/usr/lib/wsl/lib:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${WSL_DRV_DIR}:/usr/lib/wsl/drivers/${WSL_DRV_BN}:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data/sbv2-models:/opt/models&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;ipc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host&lt;/span&gt;
    &lt;span class="na"&gt;ulimits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
      &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;67108864&lt;/span&gt;

  &lt;span class="na"&gt;cosyvoice&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cosyvoice"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7865:7865"&lt;/span&gt;

  &lt;span class="na"&gt;rvc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rvc"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7866:7866"&lt;/span&gt;

  &lt;span class="na"&gt;framepack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;framepack"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7862:7862"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Each service follows the same WSL driver mount pattern -- I've abbreviated the later ones for readability.)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file is auto-generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;WSL_DRV_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /usr/lib/wsl/drivers/nvmdi.inf_amd64_&lt;span class="k"&gt;*&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;WSL_DRV_BN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WSL_DRV_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
WSL_DRV_DIR=&lt;/span&gt;&lt;span class="nv"&gt;$WSL_DRV_DIR&lt;/span&gt;&lt;span class="sh"&gt;
WSL_DRV_BN=&lt;/span&gt;&lt;span class="nv"&gt;$WSL_DRV_BN&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Design Decisions That Saved My Sanity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Docker Profiles for Resource Isolation
&lt;/h3&gt;

&lt;p&gt;With 32GB VRAM, you can't run everything simultaneously. Video generation alone can eat 24GB. Docker profiles let me spin up exactly what I need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;--profile&lt;/span&gt; comfyui up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker compose &lt;span class="nt"&gt;--profile&lt;/span&gt; sbv2 &lt;span class="nt"&gt;--profile&lt;/span&gt; cosyvoice up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker compose &lt;span class="nt"&gt;--profile&lt;/span&gt; all up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Shared Model Directory
&lt;/h3&gt;

&lt;p&gt;AI models are enormous. Flux checkpoints, HunyuanVideo weights, voice models -- easily 200GB+. Instead of duplicating them per container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/ai-workspace-correct/
  shared/
    models/           # Cross-service shared models
    hf_cache/         # HuggingFace cache (persistent)
  data/
    comfyui-models/   # Service-specific models
    sbv2-models/
    cosyvoice-models/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each service mounts &lt;code&gt;shared/models&lt;/code&gt; read-only. Service-specific models go in their own &lt;code&gt;data/&lt;/code&gt; directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Port Allocation Strategy
&lt;/h3&gt;

&lt;p&gt;I carved out port ranges by domain:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Services&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5000-5009&lt;/td&gt;
&lt;td&gt;Voice synthesis&lt;/td&gt;
&lt;td&gt;Style-BERT-VITS2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7860-7869&lt;/td&gt;
&lt;td&gt;Voice/Video AI&lt;/td&gt;
&lt;td&gt;FramePack, CosyVoice, RVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8180-8189&lt;/td&gt;
&lt;td&gt;Image AI&lt;/td&gt;
&lt;td&gt;ComfyUI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This avoids collisions and makes firewall rules predictable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The torchaudio Trap
&lt;/h3&gt;

&lt;p&gt;This one cost me hours. Several voice synthesis frameworks use &lt;code&gt;torchaudio.info()&lt;/code&gt; and &lt;code&gt;torchaudio.load()&lt;/code&gt;. The nightly cu128 build of torchaudio has breaking API changes. The fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;

&lt;span class="n"&gt;sample_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wav_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;samplerate&lt;/span&gt;
&lt;span class="n"&gt;audio_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wav_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I patch these at Docker build time with &lt;code&gt;sed&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/import torchaudio/import torchaudio\nimport soundfile as sf/'&lt;/span&gt; /opt/app/webui.py &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/torchaudio.info(prompt_wav).sample_rate/sf.info(prompt_wav).samplerate/g'&lt;/span&gt; /opt/app/webui.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Lessons Learned (The Hard Way)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewd146y03lfz0thx71y1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewd146y03lfz0thx71y1.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Never let &lt;code&gt;requirements.txt&lt;/code&gt; install torch.&lt;/strong&gt;&lt;br&gt;
Strip &lt;code&gt;torch&lt;/code&gt;, &lt;code&gt;torchvision&lt;/code&gt;, &lt;code&gt;torchaudio&lt;/code&gt; from every &lt;code&gt;requirements.txt&lt;/code&gt; before installing. Then install your nightly cu128 build as the final step. If you don't, pip will happily overwrite your working torch with a stable version that can't see your GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Driver updates break the hash.&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;nvmdi.inf_amd64_&amp;lt;hash&amp;gt;&lt;/code&gt; directory changes when you update NVIDIA drivers. The &lt;code&gt;gpu-run&lt;/code&gt; function handles this with dynamic lookup. But if you hardcode the path anywhere, you'll have a bad time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;ipc: host&lt;/code&gt; is non-negotiable for AI workloads.&lt;/strong&gt;&lt;br&gt;
Without it, PyTorch's shared memory operations fail silently or with cryptic errors. Always set it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
This environment variable enables PyTorch's memory-efficient allocation strategy. Without it on 32GB VRAM, you'll hit fragmentation issues on large models that shouldn't theoretically run out of memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Document everything as if you'll have amnesia tomorrow.&lt;/strong&gt;&lt;br&gt;
I wrote my setup docs with the goal of "restore everything from scratch in 30 minutes." That document has saved me three times already.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Stack (February 2026)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ComfyUI&lt;/td&gt;
&lt;td&gt;Image generation (Flux, SDXL)&lt;/td&gt;
&lt;td&gt;8188&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Style-BERT-VITS2&lt;/td&gt;
&lt;td&gt;Japanese TTS voice synthesis&lt;/td&gt;
&lt;td&gt;5000&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CosyVoice&lt;/td&gt;
&lt;td&gt;Multi-speaker voice synthesis&lt;/td&gt;
&lt;td&gt;7865&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RVC&lt;/td&gt;
&lt;td&gt;Real-time voice conversion&lt;/td&gt;
&lt;td&gt;7866&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FramePack&lt;/td&gt;
&lt;td&gt;Video generation (HunyuanVideo)&lt;/td&gt;
&lt;td&gt;7862&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All running on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPU&lt;/strong&gt;: RTX 5090 32GB GDDR7&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU&lt;/strong&gt;: Intel Core Ultra 9 285K&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM&lt;/strong&gt;: 64GB DDR5&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS&lt;/strong&gt;: Windows 11 Pro + WSL2 Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container runtime&lt;/strong&gt;: Docker with NVIDIA Container Toolkit&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Is This Still Unique?
&lt;/h2&gt;

&lt;p&gt;As of February 2026, there are published examples of single-service RTX 5090 + Docker setups (vLLM, ComfyUI, basic PyTorch). What I haven't found elsewhere is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;multi-service Docker Compose stack&lt;/strong&gt; orchestrating 5+ AI services on Blackwell&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;specific WSL2 driver mount solution&lt;/strong&gt; documented with the &lt;code&gt;nvmdi.inf_amd64_*&lt;/code&gt; path&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;systematic approach to dependency isolation&lt;/strong&gt; across services sharing one GPU&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-grade patterns&lt;/strong&gt; for model sharing, port management, and environment recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've done something similar, I'd genuinely love to hear about it. Drop a comment or reach out.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with ~40 hours of debugging, 200+ GB of model files, and an unreasonable amount of stubbornness. Based in Tokyo.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#rtx5090&lt;/code&gt; &lt;code&gt;#docker&lt;/code&gt; &lt;code&gt;#wsl2&lt;/code&gt; &lt;code&gt;#pytorch&lt;/code&gt; &lt;code&gt;#cuda&lt;/code&gt; &lt;code&gt;#blackwell&lt;/code&gt; &lt;code&gt;#ai&lt;/code&gt; &lt;code&gt;#selfhosted&lt;/code&gt;&lt;/p&gt;

</description>
      <category>cuda</category>
      <category>linux</category>
      <category>showdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built a Voice Cloning GUI That Supports 10 Languages — Here's What I Learned Wrestling with CUDA on Windows published</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Sat, 21 Feb 2026 22:05:52 +0000</pubDate>
      <link>https://dev.to/genelab_999/i-built-a-voice-cloning-gui-that-supports-10-languages-heres-what-i-learned-wrestling-with-cuda-30gp</link>
      <guid>https://dev.to/genelab_999/i-built-a-voice-cloning-gui-that-supports-10-languages-heres-what-i-learned-wrestling-with-cuda-30gp</guid>
      <description>&lt;p&gt;Have you ever recorded yourself speaking and thought, &lt;em&gt;"I wish I could just type what I want to say and have my own voice read it back"&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;That's exactly the rabbit hole I fell down when Alibaba dropped &lt;a href="https://github.com/QwenLM/Qwen3-TTS" rel="noopener noreferrer"&gt;Qwen3-TTS&lt;/a&gt; — an open-source TTS model that can clone any voice from just &lt;strong&gt;3 seconds of audio&lt;/strong&gt;. Ten languages. 97ms latency. Apache 2.0 license. On paper, it was everything I'd ever wanted.&lt;/p&gt;

&lt;p&gt;In practice? It assumed Linux. FlashAttention 2 (recommended) doesn't run on Windows. And voice cloning required you to &lt;em&gt;manually transcribe&lt;/em&gt; your reference audio — which kind of defeats the purpose of a "quick clone" workflow.&lt;/p&gt;

&lt;p&gt;So I did what any developer would do: I forked it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hiroki-abe-58" rel="noopener noreferrer"&gt;
        hiroki-abe-58
      &lt;/a&gt; / &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;
        Qwen3-TTS-JP
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Japanese GUI + Whisper auto-transcription for Qwen3-TTS. RTX 5090 tested.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Qwen3-TTS-JP&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;English&lt;/strong&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ja.md" rel="noopener noreferrer"&gt;日本語&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_zh.md" rel="noopener noreferrer"&gt;中文&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ko.md" rel="noopener noreferrer"&gt;한국어&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ru.md" rel="noopener noreferrer"&gt;Русский&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_es.md" rel="noopener noreferrer"&gt;Español&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_it.md" rel="noopener noreferrer"&gt;Italiano&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_de.md" rel="noopener noreferrer"&gt;Deutsch&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_fr.md" rel="noopener noreferrer"&gt;Français&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_pt.md" rel="noopener noreferrer"&gt;Português&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;Windows-native&lt;/strong&gt; fork of Qwen3-TTS with a modern, multilingual Web UI.&lt;/p&gt;
&lt;p&gt;The original Qwen3-TTS was developed primarily for Linux environments, and FlashAttention 2 is recommended. However, FlashAttention 2 does not work on Windows. This fork enables &lt;strong&gt;direct execution on Windows without WSL2 or Docker&lt;/strong&gt;, provides a &lt;strong&gt;modern Web UI supporting 10 languages&lt;/strong&gt;, and adds automatic transcription via Whisper.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mac (Apple Silicon) users:&lt;/strong&gt; For the best experience on Mac, please use &lt;strong&gt;&lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-Mac-GeneLab" rel="noopener noreferrer"&gt;Qwen3-TTS-Mac-GeneLab&lt;/a&gt;&lt;/strong&gt; -- fully optimized for Apple Silicon with MLX + PyTorch dual engine, 8bit/4bit quantization, and 10-language Web UI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Custom Voice -- Speech synthesis with preset speakers&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/CustomVoice.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FCustomVoice.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Voice Design -- Describe voice characteristics to synthesize&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/VoiceDesign.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FVoiceDesign.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Voice Clone -- Clone voice from reference audio&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/VoiceClone.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FVoiceClone.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Settings -- GPU / VRAM / Model information&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/Settings.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FSettings.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Related Projects&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Platform&lt;/th&gt;

&lt;th&gt;Repository&lt;/th&gt;

&lt;th&gt;Description&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;Windows&lt;/td&gt;

&lt;td&gt;&lt;strong&gt;This&lt;/strong&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;&lt;strong&gt;Qwen3-TTS-JP&lt;/strong&gt; started as a personal fix — a Japanese-localized fork with Whisper auto-transcription bolted on. But as people started using it, I realized the same pain points existed for developers everywhere. So I expanded it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10-language Web UI&lt;/strong&gt; — Japanese, English, Chinese, Korean, German, French, Russian, Portuguese, Spanish, Italian. The UI auto-detects your browser locale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Windows support&lt;/strong&gt; — No WSL. No Docker. Just Python + CUDA.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whisper auto-transcription&lt;/strong&gt; — Upload 3 seconds of audio, Whisper handles the rest. Pick from 5 model sizes (tiny → large-v3) depending on your speed/accuracy tradeoff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RTX 5090 (Blackwell) tested&lt;/strong&gt; — I developed this on a Blackwell GPU, so sm_120 architecture is a first-class citizen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mac support&lt;/strong&gt; — Apple Silicon users get a &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-Mac-GeneLab" rel="noopener noreferrer"&gt;dedicated fork&lt;/a&gt; with MLX + PyTorch dual engine and 4bit/8bit quantization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Architecture in 30 Seconds
&lt;/h2&gt;

&lt;p&gt;Qwen3-TTS isn't your typical TTS pipeline. Instead of the usual &lt;code&gt;Text → LM → DiT → Audio&lt;/code&gt; cascade, it uses a discrete multi-codebook LM that goes straight from text to audio codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traditional:  Text → Language Model → Intermediate Repr → DiT → Audio
Qwen3-TTS:    Text → Language Model → Audio Codes → Decoder → Audio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bypasses the information bottleneck that makes most TTS systems sound robotic. The result is eerily human-sounding output — with emotion, prosody, and natural pauses all preserved.&lt;/p&gt;

&lt;p&gt;The dual-track streaming architecture means it starts generating audio from the &lt;em&gt;first character&lt;/em&gt; of input. That 97ms first-packet latency is real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting It Running (It's Actually Easy Now)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/hiroki-abe-58/Qwen3-TTS-JP.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Qwen3-TTS-JP

python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="c"&gt;# Windows&lt;/span&gt;
.venv&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate
&lt;span class="c"&gt;# Linux/Mac&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;faster-whisper

&lt;span class="c"&gt;# RTX 30/40 series&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;torch torchvision torchaudio &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cu124

&lt;span class="c"&gt;# RTX 50 series (Blackwell) — needs nightly&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--pre&lt;/span&gt; torch torchvision torchaudio &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/nightly/cu128
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch the GUI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Voice cloning mode&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; qwen_tts.cli.demo Qwen/Qwen3-TTS-12Hz-1.7B-Base &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ip&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt; 7860 &lt;span class="nt"&gt;--no-flash-attn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://127.0.0.1:7860&lt;/code&gt;. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Actually Build With This
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting for developers. This isn't just a toy — the Python API is clean enough to integrate into real projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice Cloning in 5 Lines
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qwen_tts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qwen3TTSModel&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Qwen3TTSModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qwen/Qwen3-TTS-12Hz-1.7B-Base&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bfloat16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_voice_clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is my cloned voice. It only needed 3 seconds of audio.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;English&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ref_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_voice.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# 3 seconds is enough
&lt;/span&gt;    &lt;span class="n"&gt;ref_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, testing.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# Whisper can auto-generate this
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Design a Voice From Scratch
&lt;/h3&gt;

&lt;p&gt;No reference audio needed — just describe what you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Qwen3TTSModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bfloat16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_voice_design&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome back, adventurer. Your quest awaits.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;English&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruct&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deep male voice, 45 years old, slight British accent, warm and commanding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cross-Lingual Cloning
&lt;/h3&gt;

&lt;p&gt;Clone a voice in one language, generate speech in another. The model preserves the speaker's timbre across languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_voice_clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bonjour, comment allez-vous aujourd&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hui?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;French&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ref_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;english_speaker.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ref_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hi, this is a test recording.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practical Use Cases I've Seen
&lt;/h2&gt;

&lt;p&gt;Since releasing this fork, I've seen developers use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Game dev&lt;/strong&gt; — Generating NPC dialogue dynamically instead of recording thousands of audio files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Podcasting&lt;/strong&gt; — Creating consistent intro/outro narration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt; — Multilingual audio versions of documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localization&lt;/strong&gt; — Same voice, 10 languages, zero re-recording&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototyping&lt;/strong&gt; — Testing voice UX before hiring voice actors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GPU Compatibility
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GPU&lt;/th&gt;
&lt;th&gt;VRAM&lt;/th&gt;
&lt;th&gt;Recommended Model&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090&lt;/td&gt;
&lt;td&gt;32GB&lt;/td&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;Tested &amp;amp; verified&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090&lt;/td&gt;
&lt;td&gt;24GB&lt;/td&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;Works great&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4070&lt;/td&gt;
&lt;td&gt;12GB&lt;/td&gt;
&lt;td&gt;0.6B or 1.7B (tight)&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3080&lt;/td&gt;
&lt;td&gt;10GB&lt;/td&gt;
&lt;td&gt;0.6B&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple Silicon&lt;/td&gt;
&lt;td&gt;16GB+&lt;/td&gt;
&lt;td&gt;Via Mac fork&lt;/td&gt;
&lt;td&gt;MLX optimized&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you're VRAM-constrained, the 0.6B model is surprisingly capable — and FlashAttention 2 can help on Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flash-attn &lt;span class="nt"&gt;--no-build-isolation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Things I Learned the Hard Way
&lt;/h2&gt;

&lt;p&gt;A few gotchas from building this that might save you time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows cp932 encoding hell.&lt;/strong&gt; Japanese Windows defaults to cp932 encoding, which chokes on Unicode output from the model. The fix is wrapping stdout/stderr:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextIOWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextIOWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FlashAttention 2 doesn't compile on Windows.&lt;/strong&gt; The solution is using PyTorch's built-in SDPA (Scaled Dot Product Attention) via &lt;code&gt;--no-flash-attn&lt;/code&gt;. Performance hit is minimal for single-user inference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blackwell (sm_120) needs nightly PyTorch.&lt;/strong&gt; As of early 2026, stable PyTorch doesn't support RTX 50-series. Nightly builds with cu128 work, but you'll see warnings about torchao version mismatches. They're cosmetic — ignore them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SoX is optional.&lt;/strong&gt; The model prints warnings about missing SoX, but it works fine without it. Don't waste time installing it on Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I'm currently exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vLLM integration for production-grade serving&lt;/li&gt;
&lt;li&gt;Fine-tuning workflows for custom voice models&lt;/li&gt;
&lt;li&gt;Streaming WebSocket API for real-time applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you're working on anything voice-related — games, accessibility, content creation, or just want to mess around with state-of-the-art TTS — give it a spin:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows/Linux:&lt;/strong&gt; &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;Qwen3-TTS-JP&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Mac (Apple Silicon):&lt;/strong&gt; &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-Mac-GeneLab" rel="noopener noreferrer"&gt;Qwen3-TTS-Mac-GeneLab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stars are appreciated — they help other developers find the project.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;I'm curious:&lt;/strong&gt; What would you build with 3-second voice cloning? Drop your ideas in the comments — I'd love to hear what use cases I haven't thought of yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ethical Note
&lt;/h2&gt;

&lt;p&gt;Voice cloning is powerful tech. Please use it responsibly — clone only with consent, disclose AI-generated audio, and don't use it for fraud or impersonation. The Apache 2.0 license gives you freedom, but with great power... you know the rest.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>ComfyUI-AceMusic: The First Full Implementation of ACE-Step 1.5 Features That "Weren't Yet Supported"</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Wed, 04 Feb 2026 15:06:27 +0000</pubDate>
      <link>https://dev.to/genelab_999/comfyui-acemusic-the-first-full-implementation-of-ace-step-15-features-that-werent-yet-2kje</link>
      <guid>https://dev.to/genelab_999/comfyui-acemusic-the-first-full-implementation-of-ace-step-15-features-that-werent-yet-2kje</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;On February 3rd, 2026, the official ComfyUI blog announced ACE-Step 1.5 support with a notable caveat: &lt;strong&gt;"Cover, Repaint, and other features aren't yet supported in ComfyUI."&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The next day, I released ComfyUI-AceMusic — a complete implementation of all 15 ACE-Step 1.5 features as ComfyUI nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;World-first&lt;/strong&gt;: Full Cover, Repaint, Edit, Retake, Extend support in ComfyUI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15 nodes&lt;/strong&gt; covering every ACE-Step 1.5 capability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular architecture&lt;/strong&gt; that eliminates widget ordering issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows + Python 3.13+ compatible&lt;/strong&gt; using soundfile/scipy instead of problematic torchaudio backends&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HeartMuLa interoperability&lt;/strong&gt; for hybrid AI music workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-AceMusic" rel="noopener noreferrer"&gt;github.com/hiroki-abe-58/ComfyUI-AceMusic&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Official Support Was Incomplete
&lt;/h2&gt;

&lt;p&gt;ACE-Step 1.5 is a game-changer for open-source music generation. It outperforms most commercial alternatives, runs on consumer hardware (4GB VRAM), and generates full songs in under 10 seconds on an RTX 3090.&lt;/p&gt;

&lt;p&gt;When ComfyUI announced native support, the community was excited. But there was a catch.&lt;/p&gt;

&lt;p&gt;From the &lt;a href="https://blog.comfy.org/p/ace-step-15-is-now-available-in-comfyui" rel="noopener noreferrer"&gt;official ComfyUI blog&lt;/a&gt; (February 3rd, 2026):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"ACE-Step 1.5 has a few more tricks up its sleeve. &lt;strong&gt;These aren't yet supported in ComfyUI&lt;/strong&gt;, but we have no doubt the community will figure it out."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The "tricks" they mentioned? Only the most powerful features of ACE-Step 1.5:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Official Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Transform any song into a different style&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repaint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Regenerate specific sections of audio&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Change tags/lyrics while preserving melody&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retake&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create variations of existing audio&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add new content before/after audio&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So I built them.&lt;/p&gt;




&lt;h2&gt;
  
  
  What ComfyUI-AceMusic Offers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Complete Feature Coverage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model Loader&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Downloads and caches ACE-Step 1.5 models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Settings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configure generation parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Generator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Text-to-Music generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lyrics Input&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dedicated lyrics input with section markers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caption Input&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Style/genre description input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Transform existing audio into different styles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repaint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Regenerate specific time ranges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retake&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create variations with same settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add content to beginning or end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Change tags/lyrics, preserve melody (FlowEdit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Conditioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Combine parameters into conditioning object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Generator (from Cond)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generate from conditioning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Load LoRA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Load fine-tuned adapters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Understand&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extract metadata from audio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Create Sample&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generate params from natural language&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Comparison with Existing Implementations
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;ACE-Step Version&lt;/th&gt;
&lt;th&gt;Cover&lt;/th&gt;
&lt;th&gt;Repaint&lt;/th&gt;
&lt;th&gt;Edit&lt;/th&gt;
&lt;th&gt;Retake&lt;/th&gt;
&lt;th&gt;Extend&lt;/th&gt;
&lt;th&gt;Win 3.13+&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ComfyUI Native&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Untested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;billwuhao&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Untested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ryanontheinside&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Untested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ComfyUI-AceMusic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;✅&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Technical Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Modular Architecture
&lt;/h3&gt;

&lt;p&gt;Previous implementations crammed 30+ parameters into a single node, causing widget ordering issues — a known ComfyUI quirk where input field order can cause unexpected behavior.&lt;/p&gt;

&lt;p&gt;ComfyUI-AceMusic separates concerns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Model Loader] → Model loading only
[Settings] → Generation parameters only  
[Lyrics Input] → Lyrics entry only
[Caption Input] → Style description only
[Generator] → Generation execution only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eliminates widget ordering bugs&lt;/li&gt;
&lt;li&gt;Improves workflow readability&lt;/li&gt;
&lt;li&gt;Makes nodes reusable across different workflows&lt;/li&gt;
&lt;li&gt;Follows single-responsibility principle&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cross-Platform Compatibility
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: &lt;code&gt;torchaudio&lt;/code&gt; backends can fail on Windows + Python 3.13+.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Use &lt;code&gt;soundfile&lt;/code&gt; and &lt;code&gt;scipy&lt;/code&gt; instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Problematic approach
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torchaudio&lt;/span&gt;
&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torchaudio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Fails on Windows 3.13+
&lt;/span&gt;
&lt;span class="c1"&gt;# ComfyUI-AceMusic approach
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;
&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Works everywhere
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't just a workaround — it's a more robust solution that works across all platforms without requiring specific backend configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. HeartMuLa Interoperability
&lt;/h3&gt;

&lt;p&gt;The AUDIO type in ComfyUI-AceMusic is compatible with HeartMuLa outputs, enabling hybrid workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HeartMuLa Generator] → [AceMusic Cover] → [AceMusic Extend] → [Output]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you combine the strengths of different music generation models in a single workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Via ComfyUI Manager (Recommended):&lt;/strong&gt;&lt;br&gt;
Search for "ComfyUI-AceMusic" and install.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ComfyUI/custom_nodes
git clone https://github.com/hiroki-abe-58/ComfyUI-AceMusic.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ComfyUI-AceMusic
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Install ACE-Step 1.5&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/ace-step/ACE-Step.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Models auto-download from Hugging Face on first use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Workflow (Text-to-Music)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;strong&gt;AceMusic Model Loader&lt;/strong&gt; → set device to &lt;code&gt;cuda&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;AceMusic Settings&lt;/strong&gt; → configure duration, language, etc.&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;AceMusic Lyrics Input&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   [Verse]
   Walking down the empty street
   Thinking about you and me

   [Chorus]
   We belong together
   Now and forever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add &lt;strong&gt;AceMusic Caption Input&lt;/strong&gt;: &lt;code&gt;pop, female vocal, energetic&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Connect all to &lt;strong&gt;AceMusic Generator&lt;/strong&gt; → &lt;strong&gt;Preview Audio&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Load the example workflow: &lt;code&gt;workflow/AceMusic_Lyrics_v3.json&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cover Workflow (Style Transfer)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Load Audio] ──────────────────┐
                               ↓
[Model Loader] → [Settings] → [AceMusic Cover] → [Preview Audio]
                               ↑
[Caption Input] ───────────────┘
"jazz piano trio, smooth, relaxed"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pop → Jazz arrangement&lt;/li&gt;
&lt;li&gt;Rock → Acoustic version&lt;/li&gt;
&lt;li&gt;EDM → Orchestral arrangement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Repaint Workflow (Section Regeneration)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Load Audio] ──────────────────┐
                               ↓
[Model Loader] → [Settings] → [AceMusic Repaint] → [Preview Audio]
                               ↑
[Time Range: 30-45s] ──────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix a problematic chorus&lt;/li&gt;
&lt;li&gt;Improve the intro&lt;/li&gt;
&lt;li&gt;Regenerate specific vocal sections&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Generation Speed
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;RTF (27 steps)&lt;/th&gt;
&lt;th&gt;Time for 1 min audio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090&lt;/td&gt;
&lt;td&gt;~50x&lt;/td&gt;
&lt;td&gt;~1.2s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090&lt;/td&gt;
&lt;td&gt;34.48x&lt;/td&gt;
&lt;td&gt;1.74s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A100&lt;/td&gt;
&lt;td&gt;27.27x&lt;/td&gt;
&lt;td&gt;2.20s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3090&lt;/td&gt;
&lt;td&gt;12.76x&lt;/td&gt;
&lt;td&gt;4.70s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M2 Max&lt;/td&gt;
&lt;td&gt;2.27x&lt;/td&gt;
&lt;td&gt;26.43s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  VRAM Requirements
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;VRAM&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal&lt;/td&gt;
&lt;td&gt;8GB+&lt;/td&gt;
&lt;td&gt;Full speed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU Offload&lt;/td&gt;
&lt;td&gt;~4GB&lt;/td&gt;
&lt;td&gt;Slower but works on limited VRAM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CUDA out of memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Insufficient GPU memory&lt;/td&gt;
&lt;td&gt;Enable &lt;code&gt;cpu_offload&lt;/code&gt; or reduce &lt;code&gt;duration&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ModuleNotFoundError: acestep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ACE-Step not installed&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install git+https://github.com/ace-step/ACE-Step.git&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;soundfile not found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing dependency&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install soundfile scipy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Model download failed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Network issue&lt;/td&gt;
&lt;td&gt;Check Hugging Face access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;torchaudio backend error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Windows 3.13+ issue&lt;/td&gt;
&lt;td&gt;Ensure soundfile is properly installed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Environment Check Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;ComfyUI-AceMusic Environment Checker&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# Python version
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_info&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3.10+ required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# PyTorch + CUDA
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ PyTorch: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__version__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ CUDA: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;vram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_device_properties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;total_memory&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e9&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ GPU VRAM: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vram&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; GB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CUDA not available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PyTorch not installed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ACE-Step
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;acestep&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ ACE-Step: installed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ACE-Step not installed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Audio libraries
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ soundfile: installed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;soundfile not installed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Results
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;❌ Issues found:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;issue&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ Environment OK!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;When I saw the official announcement saying "these features aren't yet supported," I knew exactly what needed to be done. The ACE-Step team built an incredible model with Cover, Repaint, Edit, and other powerful features — but without ComfyUI support, most users couldn't access them.&lt;/p&gt;

&lt;p&gt;The hardest part was the &lt;code&gt;torchaudio&lt;/code&gt; issue. On Windows with Python 3.13+, the audio backends just don't work reliably. The solution was to bypass torchaudio entirely and use soundfile/scipy for all audio I/O. It's a more robust approach that should work on any platform.&lt;/p&gt;

&lt;p&gt;The modular architecture came from frustration with existing implementations. Stuffing 30+ parameters into one node isn't just ugly — it causes real bugs. Separating concerns made the nodes more reliable and the workflows more readable.&lt;/p&gt;

&lt;p&gt;This is what open source is about. The official team sets the direction, and the community fills in the gaps. I'm proud to contribute to the music generation ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/hiroki-abe-58/ComfyUI-AceMusic" rel="noopener noreferrer"&gt;github.com/hiroki-abe-58/ComfyUI-AceMusic&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACE-Step 1.5&lt;/strong&gt;: &lt;a href="https://github.com/ace-step/ACE-Step-1.5" rel="noopener noreferrer"&gt;github.com/ace-step/ACE-Step-1.5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ComfyUI Official Blog&lt;/strong&gt;: &lt;a href="https://blog.comfy.org/p/ace-step-15-is-now-available-in-comfyui" rel="noopener noreferrer"&gt;ACE-Step 1.5 Announcement&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HeartMuLa&lt;/strong&gt; (compatible): &lt;a href="https://github.com/filliptm/ComfyUI_FL-HeartMuLa" rel="noopener noreferrer"&gt;github.com/filliptm/ComfyUI_FL-HeartMuLa&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;Apache 2.0&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you find this useful, consider starring the repo. And if you build something cool with it, I'd love to see it!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>news</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Run Qwen3-TTS on Windows with RTX 5090: Voice Cloning in 3 Seconds</title>
      <dc:creator>GeneLab_999</dc:creator>
      <pubDate>Sat, 31 Jan 2026 09:37:20 +0000</pubDate>
      <link>https://dev.to/genelab_999/run-qwen3-tts-on-windows-with-rtx-5090-voice-cloning-in-3-seconds-elc</link>
      <guid>https://dev.to/genelab_999/run-qwen3-tts-on-windows-with-rtx-5090-voice-cloning-in-3-seconds-elc</guid>
      <description>&lt;h1&gt;
  
  
  Run Qwen3-TTS on Windows with RTX 5090: The Complete Guide to Voice Cloning in 3 Seconds
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Clone any voice with just 3 seconds of audio — now with native Windows support and the latest Blackwell GPUs&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Qwen3-TTS-JP&lt;/strong&gt; is a fork of Alibaba's Qwen3-TTS that adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Native Windows support&lt;/strong&gt; (no WSL required!)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;RTX 5090 / Blackwell GPU tested&lt;/strong&gt; and optimized&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Auto-transcription&lt;/strong&gt; via Whisper integration&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Localized GUI&lt;/strong&gt; (Japanese, easy to adapt)&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hiroki-abe-58" rel="noopener noreferrer"&gt;
        hiroki-abe-58
      &lt;/a&gt; / &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;
        Qwen3-TTS-JP
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Japanese GUI + Whisper auto-transcription for Qwen3-TTS. RTX 5090 tested.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Qwen3-TTS-JP&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;English&lt;/strong&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ja.md" rel="noopener noreferrer"&gt;日本語&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_zh.md" rel="noopener noreferrer"&gt;中文&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ko.md" rel="noopener noreferrer"&gt;한국어&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_ru.md" rel="noopener noreferrer"&gt;Русский&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_es.md" rel="noopener noreferrer"&gt;Español&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_it.md" rel="noopener noreferrer"&gt;Italiano&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_de.md" rel="noopener noreferrer"&gt;Deutsch&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_fr.md" rel="noopener noreferrer"&gt;Français&lt;/a&gt; | &lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/docs/README_pt.md" rel="noopener noreferrer"&gt;Português&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;Windows-native&lt;/strong&gt; fork of Qwen3-TTS with a modern, multilingual Web UI.&lt;/p&gt;
&lt;p&gt;The original Qwen3-TTS was developed primarily for Linux environments, and FlashAttention 2 is recommended. However, FlashAttention 2 does not work on Windows. This fork enables &lt;strong&gt;direct execution on Windows without WSL2 or Docker&lt;/strong&gt;, provides a &lt;strong&gt;modern Web UI supporting 10 languages&lt;/strong&gt;, and adds automatic transcription via Whisper.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mac (Apple Silicon) users:&lt;/strong&gt; For the best experience on Mac, please use &lt;strong&gt;&lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-Mac-GeneLab" rel="noopener noreferrer"&gt;Qwen3-TTS-Mac-GeneLab&lt;/a&gt;&lt;/strong&gt; -- fully optimized for Apple Silicon with MLX + PyTorch dual engine, 8bit/4bit quantization, and 10-language Web UI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Custom Voice -- Speech synthesis with preset speakers&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/CustomVoice.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FCustomVoice.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Voice Design -- Describe voice characteristics to synthesize&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/VoiceDesign.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FVoiceDesign.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Voice Clone -- Clone voice from reference audio&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/VoiceClone.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FVoiceClone.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Settings -- GPU / VRAM / Model information&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP/assets/Settings.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fhiroki-abe-58%2FQwen3-TTS-JP%2FHEAD%2Fassets%2FSettings.png" width="90%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Related Projects&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Platform&lt;/th&gt;

&lt;th&gt;Repository&lt;/th&gt;

&lt;th&gt;Description&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;Windows&lt;/td&gt;

&lt;td&gt;&lt;strong&gt;This&lt;/strong&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





&lt;h2&gt;
  
  
  The Problem: Getting Qwen3-TTS Running on Windows
&lt;/h2&gt;

&lt;p&gt;When Alibaba released Qwen3-TTS in January 2026, the AI community was amazed: &lt;strong&gt;3 seconds of reference audio is all you need to clone a voice&lt;/strong&gt;. Ten languages supported, 97ms latency, emotion control — impressive specs on paper.&lt;/p&gt;

&lt;p&gt;But there was a catch.&lt;/p&gt;

&lt;p&gt;The official repo assumed Linux. CUDA setup was finicky. And if you wanted to use the voice cloning feature, you had to &lt;strong&gt;manually transcribe your reference audio&lt;/strong&gt; — defeating the purpose of a quick workflow.&lt;/p&gt;

&lt;p&gt;I'd just upgraded to an RTX 5090 (Blackwell architecture), eager to push local AI to its limits. After days of wrestling with environments, I got it working and decided to package the solution for everyone else.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes This Fork Different?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Native Windows Support
&lt;/h3&gt;

&lt;p&gt;No WSL. No Docker (though it's optional). Just Python, CUDA, and you're good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repo&lt;/span&gt;
git clone https://github.com/hiroki-abe-58/Qwen3-TTS-JP.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Qwen3-TTS-JP

&lt;span class="c"&gt;# Create virtual environment&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
.venv&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate

&lt;span class="c"&gt;# Install&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;faster-whisper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Works on Windows 10/11 with any CUDA-capable GPU (RTX 30/40/50 series).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. RTX 5090 (Blackwell) Tested
&lt;/h3&gt;

&lt;p&gt;This fork was developed and tested on an RTX 5090. The latest CUDA 12.x with Blackwell architecture can be tricky — many AI repos break on it. This one doesn't.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GPU&lt;/th&gt;
&lt;th&gt;VRAM&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090&lt;/td&gt;
&lt;td&gt;32GB&lt;/td&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;✅ Works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090&lt;/td&gt;
&lt;td&gt;24GB&lt;/td&gt;
&lt;td&gt;1.7B&lt;/td&gt;
&lt;td&gt;✅ Works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3080&lt;/td&gt;
&lt;td&gt;10GB&lt;/td&gt;
&lt;td&gt;0.6B&lt;/td&gt;
&lt;td&gt;✅ Works&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Whisper Auto-Transcription
&lt;/h3&gt;

&lt;p&gt;The original Qwen3-TTS requires you to provide the transcript of your reference audio. This fork integrates &lt;strong&gt;faster-whisper&lt;/strong&gt; to do it automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload 3 seconds of audio&lt;/li&gt;
&lt;li&gt;Whisper transcribes it&lt;/li&gt;
&lt;li&gt;Qwen3-TTS clones the voice&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No manual typing. Choose from 5 Whisper models:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Params&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tiny&lt;/td&gt;
&lt;td&gt;39M&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;small&lt;/td&gt;
&lt;td&gt;244M&lt;/td&gt;
&lt;td&gt;⚡⚡⚡&lt;/td&gt;
&lt;td&gt;★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;large-v3&lt;/td&gt;
&lt;td&gt;1.5B&lt;/td&gt;
&lt;td&gt;⚡&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Launch the GUI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; qwen_tts.demo Qwen/Qwen3-TTS-12Hz-1.7B-Base &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ip&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;soundfile&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qwen_tts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qwen3TTSModel&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Qwen3TTSModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qwen/Qwen3-TTS-12Hz-1.7B-Base&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bfloat16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Clone a voice with 3-second reference
&lt;/span&gt;&lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_voice_clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is my cloned voice speaking!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;English&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ref_audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reference.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ref_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, this is a test.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wavs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Content Creators
&lt;/h3&gt;

&lt;p&gt;Clone your own voice for consistent narration across videos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Developers
&lt;/h3&gt;

&lt;p&gt;Create character voices without expensive voice actors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_voice_design&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hero, your quest awaits!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;English&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruct&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deep male voice, 40 years old, British accent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Podcasters
&lt;/h3&gt;

&lt;p&gt;Quick voice-over generation for intros and outros.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported Languages
&lt;/h2&gt;

&lt;p&gt;🇨🇳 Chinese | 🇺🇸 English | 🇯🇵 Japanese | 🇰🇷 Korean | 🇩🇪 German | 🇫🇷 French | 🇷🇺 Russian | 🇧🇷 Portuguese | 🇪🇸 Spanish | 🇮🇹 Italian&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CUDA out of memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use 0.6B model or add FlashAttention 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;faster-whisper not found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install faster-whisper&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Ethical Note
&lt;/h2&gt;

&lt;p&gt;Voice cloning is powerful. Please:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only clone voices &lt;strong&gt;with consent&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Don't use for fraud or misinformation&lt;/li&gt;
&lt;li&gt;Disclose AI-generated audio&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hiroki-abe-58/Qwen3-TTS-JP" rel="noopener noreferrer"&gt;This Fork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/QwenLM/Qwen3-TTS" rel="noopener noreferrer"&gt;Original Qwen3-TTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2601.15621" rel="noopener noreferrer"&gt;Paper&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If this helped, please ⭐ the repo!&lt;/p&gt;

&lt;p&gt;Questions? Drop a comment below! 👇&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
  </channel>
</rss>
