Skip to content

Commit b61530e

Browse files
committed
QVAC-21921 audiogen-cpp: report per-step progress from LM and DiT
Add optional on_step hooks so the engine can surface real generation progress to its ProgressFn, driving a determinate UI progress bar instead of an indeterminate spinner. - dit_ggml: DitSampleParams.on_step(step, num_steps), fired at the start of each Euler step; returning false requests cooperative cancellation. - lm_pipeline: LmSampleParams.on_step(cur, max_tokens), fired throttled (every 8 tokens) in the Phase-2 code loop. This is the longest stage on CPU, so it drives most of the bar. Informational only (no cancel). - engine: wire both hooks to the existing ProgressFn as report("lm", ...) and report("dit", ...). No public API change: only the internal DitSampleParams/LmSampleParams gain a default-empty callback; engine.h's ProgressFn is reused as-is.
1 parent 7dc26ed commit b61530e

5 files changed

Lines changed: 25 additions & 0 deletions

File tree

audiogen-cpp/src/acestep/dit_ggml.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ bool dit_sample(DitModel * m, const DitSampleParams & p, std::vector<float> & la
709709

710710
std::vector<float> vt;
711711
for (int step = 0; step < p.num_steps; step++) {
712+
if (p.on_step && !p.on_step(step, p.num_steps)) return false;
712713
const float t_curr = p.schedule[step];
713714

714715
// splice x_t into the trailing Oc channels of the DiT input

audiogen-cpp/src/acestep/dit_ggml.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "ggml-backend.h"
1818

19+
#include <functional>
1920
#include <string>
2021
#include <vector>
2122

@@ -88,6 +89,12 @@ struct DitSampleParams {
8889
const float * schedule = nullptr; // [num_steps] descending timesteps
8990
int num_steps = 0;
9091
const int * real_enc_S = nullptr; // [N] valid encoder lengths; null = all enc_S
92+
93+
// Optional per-step progress hook, fired at the start of each Euler step
94+
// with (step, num_steps). Return false to request cancellation (the sampler
95+
// then aborts and dit_sample returns false). The diffusion loop is the bulk
96+
// of generation time, so this is the signal that drives real UI progress.
97+
std::function<bool(int step, int total)> on_step;
9198
};
9299

93100
// Writes the denoised latent [out_channels, T, N] to `latent_out`. Rebuilds the

audiogen-cpp/src/acestep/engine.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ GenerateResult Engine::generate(const GenerateParams & params, const ProgressFn
266266
// the full int64 seed (Philox, torch.randn parity), which it gets below.
267267
lp.seed = (uint32_t) seed;
268268
lp.verbose = m->opts.verbose;
269+
// Surface incremental Phase-2 progress (the longest stage) so the UI bar
270+
// advances while the LM writes audio codes, not only during the DiT.
271+
lp.on_step = [&](int cur, int total) { report("lm", cur, total); };
269272

270273
// Phase 1: fill missing metadata (bpm/keyscale/duration/timesignature)
271274
// from the caption via the FSM, so a bare caption matches the CLI.
@@ -399,6 +402,9 @@ GenerateResult Engine::generate(const GenerateParams & params, const ProgressFn
399402
sp.schedule = schedule.data();
400403
sp.num_steps = n_steps;
401404
sp.real_enc_S = &enc_S;
405+
// Surface per-step diffusion progress (the long pole) to the caller's
406+
// ProgressFn; returning false here also honours cooperative cancellation.
407+
sp.on_step = [&](int step, int total) { return report("dit", step, total); };
402408

403409
std::vector<float> latent;
404410
if (!dit_sample(m->dit, sp, latent)) throw std::runtime_error("acestep engine: DiT sample failed");

audiogen-cpp/src/acestep/lm_pipeline.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,11 @@ bool lm_generate_codes(LMModel * m,
506506
if (params.verbose && (step + 1) % 100 == 0) {
507507
fprintf(stderr, "[lm-pipeline] step %d, %zu codes\n", step + 1, codes_out.size());
508508
}
509+
// Throttled progress: every 8 tokens (each step is a full LM forward, so
510+
// this is cheap relative to the work) plus the final step.
511+
if (params.on_step && ((step & 7) == 0 || step == max_tokens - 1)) {
512+
params.on_step(step + 1, max_tokens);
513+
}
509514
}
510515

511516
if (params.verbose) {

audiogen-cpp/src/acestep/lm_pipeline.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "lm_ggml.h"
1515

1616
#include <cstdint>
17+
#include <functional>
1718
#include <random>
1819
#include <string>
1920
#include <vector>
@@ -39,6 +40,11 @@ struct LmSampleParams {
3940
uint32_t seed = 0;
4041
int max_new_tokens = 0; // 0 => derive from duration (dur*5 + 100)
4142
bool verbose = false; // gate progress/metadata/code-dump logs
43+
44+
// Optional progress hook for the Phase-2 code loop, fired periodically with
45+
// (tokens_generated, max_tokens). This is the longest stage on CPU, so it
46+
// drives the bulk of the UI progress bar. Purely informational (no cancel).
47+
std::function<void(int cur, int total)> on_step;
4248
};
4349

4450
// Temperature -> top_k -> top_p -> softmax -> multinomial. Mutates `logits`.

0 commit comments

Comments
 (0)