@fugood/buttress-server 2.26.0-beta.20 → 2.26.0-beta.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/mlx-bridge.py
CHANGED
|
@@ -242,6 +242,17 @@ def clear_cancel(req_id):
|
|
|
242
242
|
_cancel_flags.discard(req_id)
|
|
243
243
|
|
|
244
244
|
|
|
245
|
+
def _partial_stop_length(text, stop_sequences):
|
|
246
|
+
"""Length of the longest end of `text` that a stop sequence starts with."""
|
|
247
|
+
longest = 0
|
|
248
|
+
for seq in filter(None, stop_sequences):
|
|
249
|
+
for length in range(min(len(seq) - 1, len(text)), longest, -1):
|
|
250
|
+
if text.endswith(seq[:length]):
|
|
251
|
+
longest = length
|
|
252
|
+
break
|
|
253
|
+
return longest
|
|
254
|
+
|
|
255
|
+
|
|
245
256
|
def _get_tokenizer():
|
|
246
257
|
"""Return the underlying tokenizer from the processor."""
|
|
247
258
|
if _processor is None:
|
|
@@ -407,6 +418,19 @@ def handle_generate(req_id, params):
|
|
|
407
418
|
|
|
408
419
|
full_text = ""
|
|
409
420
|
last_response = None
|
|
421
|
+
# Token events carry full_text[:sent_end]. The client builds its output
|
|
422
|
+
# from them, so they must never contain stop sequence text.
|
|
423
|
+
sent_end = 0
|
|
424
|
+
|
|
425
|
+
def send_text_until(end, token_id):
|
|
426
|
+
nonlocal sent_end
|
|
427
|
+
if end > sent_end:
|
|
428
|
+
send({
|
|
429
|
+
"id": req_id,
|
|
430
|
+
"event": "token",
|
|
431
|
+
"data": {"token": full_text[sent_end:end], "token_id": token_id},
|
|
432
|
+
})
|
|
433
|
+
sent_end = end
|
|
410
434
|
|
|
411
435
|
if _is_vlm:
|
|
412
436
|
from mlx_vlm import stream_generate
|
|
@@ -430,9 +454,11 @@ def handle_generate(req_id, params):
|
|
|
430
454
|
**kwargs,
|
|
431
455
|
)
|
|
432
456
|
|
|
457
|
+
should_stop = False
|
|
433
458
|
for response in gen_iter:
|
|
434
459
|
if is_cancelled(req_id):
|
|
435
460
|
clear_cancel(req_id)
|
|
461
|
+
send_text_until(len(full_text), None)
|
|
436
462
|
send({
|
|
437
463
|
"id": req_id,
|
|
438
464
|
"event": "result",
|
|
@@ -451,15 +477,6 @@ def handle_generate(req_id, params):
|
|
|
451
477
|
full_text += response.text
|
|
452
478
|
last_response = response
|
|
453
479
|
|
|
454
|
-
send({
|
|
455
|
-
"id": req_id,
|
|
456
|
-
"event": "token",
|
|
457
|
-
"data": {
|
|
458
|
-
"token": response.text,
|
|
459
|
-
"token_id": getattr(response, "token", None),
|
|
460
|
-
},
|
|
461
|
-
})
|
|
462
|
-
|
|
463
480
|
# Check stop sequences
|
|
464
481
|
should_stop = False
|
|
465
482
|
for seq in stop_sequences:
|
|
@@ -469,22 +486,41 @@ def handle_generate(req_id, params):
|
|
|
469
486
|
idx = full_text.index(seq)
|
|
470
487
|
full_text = full_text[:idx]
|
|
471
488
|
break
|
|
489
|
+
|
|
490
|
+
# Like llama.node, hold back an end that may still become a stop
|
|
491
|
+
# sequence until a later token completes or breaks it.
|
|
492
|
+
safe_end = len(full_text)
|
|
493
|
+
if not should_stop:
|
|
494
|
+
safe_end -= _partial_stop_length(full_text, stop_sequences)
|
|
495
|
+
send_text_until(safe_end, getattr(response, "token", None))
|
|
472
496
|
if should_stop:
|
|
473
497
|
break
|
|
474
498
|
|
|
499
|
+
# Generation ended without completing the held-back stop sequence
|
|
500
|
+
send_text_until(len(full_text), None)
|
|
501
|
+
|
|
475
502
|
# Send final result
|
|
476
503
|
result_data = {
|
|
477
504
|
"text": full_text,
|
|
478
505
|
"interrupted": False,
|
|
479
506
|
}
|
|
480
507
|
if last_response:
|
|
508
|
+
generation_tokens = getattr(last_response, "generation_tokens", 0)
|
|
509
|
+
finish_reason = getattr(last_response, "finish_reason", None)
|
|
481
510
|
result_data.update({
|
|
482
511
|
"prompt_tokens": getattr(last_response, "prompt_tokens", 0),
|
|
483
512
|
"prompt_tps": getattr(last_response, "prompt_tps", 0),
|
|
484
|
-
"generation_tokens":
|
|
513
|
+
"generation_tokens": generation_tokens,
|
|
485
514
|
"generation_tps": getattr(last_response, "generation_tps", 0),
|
|
486
515
|
"peak_memory": getattr(last_response, "peak_memory", 0),
|
|
487
|
-
"finish_reason":
|
|
516
|
+
"finish_reason": finish_reason,
|
|
517
|
+
# Same name as llama.node's parallel result, which the completion routes read.
|
|
518
|
+
# mlx_lm reports "length" at max_tokens; mlx_vlm reports no reason, so a run
|
|
519
|
+
# that produced max_tokens tokens without a stop sequence hit the limit.
|
|
520
|
+
"stopped_limit": not should_stop and (
|
|
521
|
+
finish_reason == "length"
|
|
522
|
+
or (finish_reason is None and 0 < max_tokens <= generation_tokens)
|
|
523
|
+
),
|
|
488
524
|
})
|
|
489
525
|
|
|
490
526
|
send({"id": req_id, "event": "result", "data": result_data})
|