(
state: ServerState, request: TokasaurusRequest, output: RequestOutput
)
| 378 | |
| 379 | |
| 380 | def decode_completion( |
| 381 | state: ServerState, request: TokasaurusRequest, output: RequestOutput |
| 382 | ): |
| 383 | eos_token_ids = get_eos_token_ids(state.generation_config) |
| 384 | |
| 385 | to_decode_list = [] |
| 386 | for seq_out in output.sequence_outputs: |
| 387 | completion_ids = seq_out.completion_ids |
| 388 | |
| 389 | trimmed_completion_ids = completion_ids |
| 390 | if not request.ignore_eos: |
| 391 | for eos in eos_token_ids: |
| 392 | try: |
| 393 | pos = trimmed_completion_ids.index(eos) |
| 394 | trimmed_completion_ids = trimmed_completion_ids[:pos] |
| 395 | except ValueError: |
| 396 | pass |
| 397 | |
| 398 | to_decode_list.append(trimmed_completion_ids) |
| 399 | |
| 400 | # TODO should we be skipping special tokens here? |
| 401 | tokenizer: Tokenizer = state.get_inner_tokenizer() |
| 402 | decoded_list: list[str] = tokenizer.decode_batch( |
| 403 | to_decode_list, |
| 404 | skip_special_tokens=True, |
| 405 | ) |
| 406 | |
| 407 | trimmed_list = [] |
| 408 | |
| 409 | for decoded in decoded_list: |
| 410 | trimmed_text = decoded |
| 411 | |
| 412 | # strip decoded string up to (but not including) the first stop token, |
| 413 | # (this is to be consistent with vLLM and sglang) |
| 414 | earliest_stop_pos = None |
| 415 | for stop in request.stop: |
| 416 | if (pos := trimmed_text.find(stop)) != -1: |
| 417 | if earliest_stop_pos is None or pos < earliest_stop_pos: |
| 418 | earliest_stop_pos = pos |
| 419 | |
| 420 | if earliest_stop_pos is not None: |
| 421 | trimmed_text = trimmed_text[:earliest_stop_pos] |
| 422 | |
| 423 | trimmed_list.append(trimmed_text) |
| 424 | |
| 425 | return trimmed_list |
| 426 | |
| 427 | |
| 428 | def validate_chat_completion_request( |
no test coverage detected