1- From 861fb06531e770fcea65e86296f80eba830dac30 Mon Sep 17 00:00:00 2001
2- From: Codex <codex@local>
3- Date: Mon, 10 Aug 2026 23:05:53 +0000
4- Subject: [PATCH 2/2] tts-patch
5-
6- ---
7- tools/mtmd/mtmd-helper-gen.cpp | 118 +++++++++---
8- tools/mtmd/mtmd-helper.h | 47 ++++-
9- tools/server/server-context.cpp | 322 +++++++++++++++++++++++++++++++-
10- tools/server/server-context.h | 3 +
11- tools/server/server-task.cpp | 11 ++
12- tools/server/server-task.h | 16 ++
13- 6 files changed, 481 insertions(+), 36 deletions(-)
14-
151diff --git a/tools/mtmd/mtmd-helper-gen.cpp b/tools/mtmd/mtmd-helper-gen.cpp
16- index 85671d1..66ccf0a 100644
2+ index 1c58d3ae1..196cbd433 100644
173--- a/tools/mtmd/mtmd-helper-gen.cpp
184+++ b/tools/mtmd/mtmd-helper-gen.cpp
19- @@ -48 ,29 +48 ,38 @@ static llama_token find_special_token(const llama_vocab * vocab, const std::stri
5+ @@ -50 ,29 +50 ,38 @@ static llama_token find_special_token(const llama_vocab * vocab, const std::stri
206 return LLAMA_TOKEN_NULL;
217 }
228
@@ -73,16 +59,16 @@ index 85671d1..66ccf0a 100644
7359 return true;
7460 }
7561
76- @@ -89 ,6 +98 ,8 @@ public:
77- // those read what they need from h_state_in instead
78- virtual int32_t step_gen(llama_token sampled, const float * h_state_in, const float ** h_state_out) = 0;
62+ @@ -92 ,6 +101 ,8 @@ public:
63+ // set out_stop on end-of-speech, h_state_out must be null if no frame is generated
64+ virtual int32_t step_gen(llama_token sampled, const float * h_state_in, const float ** h_state_out, bool * out_stop ) = 0;
7965 virtual int32_t get_output(int32_t * out_sample_rate, const char ** out_data, size_t * out_data_len, int64_t * out_n_samples) = 0;
8066+ // forces any buffered codes through code2wav now, regardless of window_frames
81- + virtual int32_t flush() = 0;
67+ + virtual int32_t flush() { return 0; }
8268
8369 protected:
8470 llama_context * lctx;
85- @@ -118 ,6 +129 ,9 @@ public:
71+ @@ -121 ,6 +132 ,9 @@ public:
8672 prompt_batch.reset();
8773 n_prompt = 0;
8874 prompt_pos = 0;
@@ -92,15 +78,15 @@ index 85671d1..66ccf0a 100644
9278 }
9379
9480 int32_t set_input(const mtmd_helper_gen_audio_inp * inp) override {
95- @@ -203 ,6 +217 ,7 @@ public:
96- top_k = inp->top_k > 0 ? inp->top_k : 50 ;
97- top_p = inp->top_p > 0 ? inp->top_p : 1.0f ;
81+ @@ -208 ,6 +222 ,7 @@ public:
82+ top_p = inp->top_p > 0 ? inp->top_p : def.top_p ;
83+ seed = inp->seed ;
9884 out_type = inp->out_type;
9985+ stream = inp->stream;
10086
10187 // the prompt above holds the whole text stream up to tts_eos, so every generated
10288 // frame adds tts_pad on top of the codes embedding
103- @@ -284 ,31 +299 ,60 @@ public:
89+ @@ -302 ,31 +317 ,60 @@ public:
10490 }
10591
10692 int32_t get_output(int32_t * out_sample_rate, const char ** out_data, size_t * out_data_len, int64_t * out_n_samples) override {
@@ -170,7 +156,7 @@ index 85671d1..66ccf0a 100644
170156 private:
171157 bool ensure_cache() {
172158 if (specials_ok) {
173- @@ -352 ,7 +396 ,7 @@ private:
159+ @@ -370 ,7 +414 ,7 @@ private:
174160 LOG_ERR("mtmd_helper_gen_audio: mmproj has no speaker/audio encoder\n");
175161 return false;
176162 }
@@ -179,7 +165,7 @@ index 85671d1..66ccf0a 100644
179165 mtmd_input_text text{ marker.c_str(), marker.size(), false, true };
180166 mtmd_input_chunks * chunks = mtmd_input_chunks_init();
181167 const mtmd_bitmap * bptr = bitmap;
182- @@ -436 ,6 +480 ,9 @@ private:
168+ @@ -456 ,6 +500 ,9 @@ private:
183169 std::vector<float> h_state_buf;
184170 mtmd_helper_gen_audio_outtype out_type = MTMD_HELPER_GEN_AUDIO_OUTTYPE_WAV;
185171 std::vector<char> out_buf;
@@ -188,8 +174,8 @@ index 85671d1..66ccf0a 100644
188174+ bool wav_header_sent = false;
189175 };
190176
191- static std::unique_ptr<mtmd_gen_audio_pipeline> make_pipeline(llama_context * lctx, mtmd_context * mctx) {
192- @@ -467 ,6 +514 ,14 @@ void mtmd_helper_gen_audio_reset(mtmd_helper_gen_audio * ctx) {
177+ // settings that only live in the reference's per-pack yaml, not in the checkpoint
178+ @@ -1024 ,6 +1071 ,14 @@ void mtmd_helper_gen_audio_reset(mtmd_helper_gen_audio * ctx) {
193179 }
194180 }
195181
@@ -204,7 +190,7 @@ index 85671d1..66ccf0a 100644
204190 int32_t mtmd_helper_gen_audio_set_input(mtmd_helper_gen_audio * ctx, const mtmd_helper_gen_audio_inp * inp) {
205191 if (!ctx->pipeline) {
206192 LOG_ERR("mtmd_helper_gen_audio: unsupported or missing gen-audio pipeline\n");
207- @@ -497 ,3 +552 ,10 @@ int32_t mtmd_helper_gen_audio_get_output(mtmd_helper_gen_audio * ctx, int32_t *
193+ @@ -1060 ,3 +1115 ,10 @@ int32_t mtmd_helper_gen_audio_get_output(mtmd_helper_gen_audio * ctx, int32_t *
208194 }
209195 return ctx->pipeline->get_output(out_sample_rate, out_data, out_data_len, out_n_samples);
210196 }
@@ -216,7 +202,7 @@ index 85671d1..66ccf0a 100644
216202+ return ctx->pipeline->flush();
217203+ }
218204diff --git a/tools/mtmd/mtmd-helper.h b/tools/mtmd/mtmd-helper.h
219- index 7e5cf9b..1f3ec01 100644
205+ index 832f7171a..3eaa01aab 100644
220206--- a/tools/mtmd/mtmd-helper.h
221207+++ b/tools/mtmd/mtmd-helper.h
222208@@ -175,6 +175,7 @@ enum mtmd_helper_gen_audio_outtype {
@@ -227,7 +213,7 @@ index 7e5cf9b..1f3ec01 100644
227213 llama_seq_id seq_id;
228214
229215 const char * prompt;
230- @@ -189 ,6 +190 ,8 @@ struct mtmd_helper_gen_audio_inp {
216+ @@ -190 ,6 +191 ,8 @@ struct mtmd_helper_gen_audio_inp {
231217 enum mtmd_helper_gen_audio_outtype out_type;
232218 };
233219
@@ -236,7 +222,7 @@ index 7e5cf9b..1f3ec01 100644
236222 MTMD_API mtmd_helper_gen_audio * mtmd_helper_gen_audio_init(
237223 struct llama_context * lctx,
238224 struct mtmd_context * mctx);
239- @@ -217 ,6 +220 ,8 @@ MTMD_API int32_t mtmd_helper_gen_audio_step_gen(
225+ @@ -221 ,6 +224 ,8 @@ MTMD_API int32_t mtmd_helper_gen_audio_step_gen(
240226
241227 // out_data valid until next get_output() or reset() call
242228 // out_n_samples (optional, can be NULL) receives the number of generated PCM samples
@@ -245,7 +231,7 @@ index 7e5cf9b..1f3ec01 100644
245231 MTMD_API int32_t mtmd_helper_gen_audio_get_output(
246232 mtmd_helper_gen_audio * ctx,
247233 int32_t * out_sample_rate,
248- @@ -224 ,6 +229 ,10 @@ MTMD_API int32_t mtmd_helper_gen_audio_get_output(
234+ @@ -228 ,6 +233 ,10 @@ MTMD_API int32_t mtmd_helper_gen_audio_get_output(
249235 size_t * out_data_len,
250236 int64_t * out_n_samples);
251237
@@ -256,7 +242,7 @@ index 7e5cf9b..1f3ec01 100644
256242 #ifdef __cplusplus
257243 } // extern "C"
258244 #endif
259- @@ -250 ,8 +259 ,41 @@ struct mtmd_helper_gen_audio_deleter {
245+ @@ -254 ,8 +263 ,41 @@ struct mtmd_helper_gen_audio_deleter {
260246 };
261247 using gen_audio_ptr = std::unique_ptr<mtmd_helper_gen_audio, mtmd_helper_gen_audio_deleter>;
262248 struct gen_audio {
@@ -299,7 +285,7 @@ index 7e5cf9b..1f3ec01 100644
299285 void reset() {
300286 mtmd_helper_gen_audio_reset(ctx.get());
301287 }
302- @@ -267 ,6 +309 ,9 @@ struct gen_audio {
288+ @@ -271 ,6 +313 ,9 @@ struct gen_audio {
303289 int32_t get_output(int32_t * out_sample_rate, const char ** out_data, size_t * out_data_len, int64_t * out_n_samples = nullptr) {
304290 return mtmd_helper_gen_audio_get_output(ctx.get(), out_sample_rate, out_data, out_data_len, out_n_samples);
305291 }
@@ -310,7 +296,7 @@ index 7e5cf9b..1f3ec01 100644
310296
311297 } // namespace mtmd_helper
312298diff --git a/tools/server/server-context.cpp b/tools/server/server-context.cpp
313- index d0e18e6..0765065 100644
299+ index 9069463fe..b7fa1e534 100644
314300--- a/tools/server/server-context.cpp
315301+++ b/tools/server/server-context.cpp
316302@@ -16,6 +16,7 @@
@@ -373,7 +359,7 @@ index d0e18e6..0765065 100644
373359 }
374360
375361 void init_sampler() const {
376- @@ -946 ,6 +974 ,14 @@ public:
362+ @@ -941 ,6 +969 ,14 @@ public:
377363 mtmd_context * mctx = nullptr;
378364 const llama_vocab * vocab = nullptr;
379365
@@ -388,7 +374,7 @@ index d0e18e6..0765065 100644
388374 server_queue queue_tasks;
389375 server_response queue_results;
390376
391- @@ -1399 ,6 +1435 ,10 @@ private:
377+ @@ -1394 ,6 +1430 ,10 @@ private:
392378 slot.mctx = mctx;
393379 slot.prompt.tokens.has_mtmd = mctx != nullptr;
394380
@@ -399,7 +385,7 @@ index d0e18e6..0765065 100644
399385 SLT_TRC(slot, "new slot, n_ctx = %d\n", slot.n_ctx);
400386
401387 slot.callback_on_release = [this](int id_slot) {
402- @@ -1852 ,6 +1892 ,28 @@ private:
388+ @@ -1847 ,6 +1887 ,28 @@ private:
403389
404390 SLT_DBG(slot, "launching slot : %s\n", safe_json_to_str(slot.to_json()).c_str());
405391
@@ -428,7 +414,7 @@ index d0e18e6..0765065 100644
428414 // initialize samplers
429415 if (task.need_sampling()) {
430416 try {
431- @@ -1869 ,6 +1931 ,9 @@ private:
417+ @@ -1864 ,6 +1926 ,9 @@ private:
432418 // TODO: getting pre sampling logits is not yet supported with backend sampling
433419 use_backend_sampling &= !need_pre_sample_logits;
434420
@@ -438,7 +424,7 @@ index d0e18e6..0765065 100644
438424 // TODO: tmp until backend sampling is fully implemented
439425 if (use_backend_sampling) {
440426 llama_set_sampler(ctx_tgt, slot.id, common_sampler_get(slot.smpl.get()));
441- @@ -1884 ,9 +1949 ,13 @@ private:
427+ @@ -1879 ,9 +1944 ,13 @@ private:
442428
443429 slot.task = std::make_unique<const server_task>(std::move(task));
444430
@@ -455,7 +441,7 @@ index d0e18e6..0765065 100644
455441
456442 // reset server kill-switch counter
457443 n_empty_consecutive = 0;
458- @@ -2163 ,6 +2232 ,18 @@ private:
444+ @@ -2158 ,6 +2227 ,18 @@ private:
459445 queue_results.send(std::move(res));
460446 }
461447
@@ -474,15 +460,15 @@ index d0e18e6..0765065 100644
474460 void send_final_response(server_slot & slot) {
475461 auto res = std::make_unique<server_task_result_cmpl_final>();
476462
477- @@ -2662 ,6 +2743 ,7 @@ private:
463+ @@ -2657 ,6 +2738 ,7 @@ private:
478464 case SERVER_TASK_TYPE_EMBEDDING:
479465 case SERVER_TASK_TYPE_RERANK:
480466 case SERVER_TASK_TYPE_SCORE:
481467+ case SERVER_TASK_TYPE_TTS:
482468 {
483469 // special case: if input is provided via CLI, tokenize it first
484470 // otherwise, no need to tokenize as it's already done inside the HTTP thread
485- @@ -3097 ,6 +3179 ,14 @@ private:
471+ @@ -3092 ,6 +3174 ,14 @@ private:
486472 abort_all_slots("pre_decode() failed: " + std::string(e.what()));
487473 }
488474
@@ -497,7 +483,7 @@ index d0e18e6..0765065 100644
497483 GGML_ASSERT(batch.slot_batched || batch.size() == 0);
498484
499485 if (batch.slot_batched) {
500- @@ -3167 ,10 +3257 ,77 @@ private:
486+ @@ -3162 ,10 +3252 ,77 @@ private:
501487 }
502488 }
503489
@@ -575,7 +561,7 @@ index d0e18e6..0765065 100644
575561 if (slot.state == SLOT_STATE_GENERATING && slot.prompt.n_tokens() + 1 >= slot.n_ctx) {
576562 if (!params_base.ctx_shift) {
577563 // this check is redundant (for good)
578- @@ -3243 ,7 +3400 ,7 @@ private:
564+ @@ -3238 ,7 +3395 ,7 @@ private:
579565
580566 // determine which slots are generating and drafting
581567 iterate(slots, [&](server_slot & slot) {
@@ -584,7 +570,7 @@ index d0e18e6..0765065 100644
584570 return;
585571 }
586572
587- @@ -3375 ,7 +3532 ,7 @@ private:
573+ @@ -3370 ,7 +3527 ,7 @@ private:
588574 return; // batch is full, skip remaining slots
589575 }
590576
@@ -593,7 +579,7 @@ index d0e18e6..0765065 100644
593579 return;
594580 }
595581
596- @@ -4384 ,6 +4541 ,8 @@ server_context_meta server_context::get_meta() const {
582+ @@ -4379 ,6 +4536 ,8 @@ server_context_meta server_context::get_meta() const {
597583 /* has_inp_image */ impl->chat_params.allow_image,
598584 /* has_inp_audio */ impl->chat_params.allow_audio,
599585 /* has_inp_video */ impl->chat_params.allow_video,
@@ -602,7 +588,7 @@ index d0e18e6..0765065 100644
602588 /* json_ui_settings */ impl->json_ui_settings,
603589 /* slot_n_ctx */ impl->get_slot_n_ctx(),
604590 /* pooling_type */ llama_pooling_type(impl->ctx_tgt),
605- @@ -4463 ,6 +4622 ,11 @@ std::unique_ptr<server_res_generator> server_routes::handle_completions_impl(
591+ @@ -4458 ,6 +4617 ,11 @@ std::unique_ptr<server_res_generator> server_routes::handle_completions_impl(
606592
607593 res->set_req(&req); // will also set spipe if needed
608594
@@ -614,7 +600,7 @@ index d0e18e6..0765065 100644
614600 int32_t sse_ping_interval = params.sse_ping_interval;
615601
616602 try {
617- @@ -5440 ,6 +5604 ,150 @@ void server_routes::init_routes() {
603+ @@ -5435 ,6 +5599 ,150 @@ void server_routes::init_routes() {
618604 return res;
619605 };
620606
@@ -766,7 +752,7 @@ index d0e18e6..0765065 100644
766752 auto res = create_response();
767753
768754diff --git a/tools/server/server-context.h b/tools/server/server-context.h
769- index f9ab113..6105126 100644
755+ index f9ab1132b..610512678 100644
770756--- a/tools/server/server-context.h
771757+++ b/tools/server/server-context.h
772758@@ -22,6 +22,8 @@ struct server_context_meta {
@@ -787,7 +773,7 @@ index f9ab113..6105126 100644
787773 server_http_context::handler_t post_lora_adapters;
788774
789775diff --git a/tools/server/server-task.cpp b/tools/server/server-task.cpp
790- index 1ee6775..939630b 100644
776+ index 1ee677553..939630b8b 100644
791777--- a/tools/server/server-task.cpp
792778+++ b/tools/server/server-task.cpp
793779@@ -1523,6 +1523,17 @@ json server_task_result_rerank::to_json() {
@@ -809,7 +795,7 @@ index 1ee6775..939630b 100644
809795 // server_task_result_error
810796 //
811797diff --git a/tools/server/server-task.h b/tools/server/server-task.h
812- index 5bedf19..e6ca67a 100644
798+ index 5bedf1987..e6ca67a65 100644
813799--- a/tools/server/server-task.h
814800+++ b/tools/server/server-task.h
815801@@ -10,6 +10,7 @@
@@ -846,7 +832,7 @@ index 5bedf19..e6ca67a 100644
846832 return true;
847833 default:
848834 return false;
849- @@ -514,6 +520,16 @@ struct server_task_result_embd : server_task_result {
835+ @@ -514,5 +520,15 @@ struct server_task_result_embd : server_task_result {
850836 json to_json_oaicompat();
851837 };
852838
@@ -862,6 +848,3 @@ index 5bedf19..e6ca67a 100644
862848+
863849 struct server_task_result_rerank : server_task_result {
864850 float score = -1e6;
865-
866- - -
867- 2.39.5
0 commit comments