diff --git a/renderers/laguna_xs2.py b/renderers/laguna_xs2.py index 123d7b8b..4f6c587f 100644 --- a/renderers/laguna_xs2.py +++ b/renderers/laguna_xs2.py @@ -421,6 +421,7 @@ def bridge_to_next_turn( # ``\n`` — the same scaffold the template emits. previous_ids = list(previous_prompt_ids) + list(previous_completion_ids) stop_ids = {self._assistant_end, self._eos} + needs_separator = previous_ids[-1] in stop_ids if ( not previous_ids[len(previous_prompt_ids) :] or previous_ids[-1] not in stop_ids @@ -478,6 +479,9 @@ def emit_text_segments( ext_sampled.append(is_sampled) ext_content.append(is_content) + if needs_separator: + emit_text("\n", -1) + for i, msg in enumerate(new_messages): role = msg.get("role") content = self._visible_text(msg.get("content")) diff --git a/tests/test_bridge.py b/tests/test_bridge.py index a49374e1..3cb6a832 100644 --- a/tests/test_bridge.py +++ b/tests/test_bridge.py @@ -140,6 +140,32 @@ def test_bridge_extends_prev_verbatim_on_clean_stop(br_renderer_all, br_model): ) +@pytest.mark.model +@pytest.mark.parametrize("model", ["poolside/Laguna-XS.2", "poolside/Laguna-M.1"]) +@pytest.mark.parametrize("stop", ["", "〈|EOS|〉", ""]) +@pytest.mark.parametrize( + "role,opening", [("user", ""), ("tool", "")] +) +def test_laguna_bridge_separates_turns(model, stop, role, opening): + from renderers import create_renderer + + tok, _ = _load(model, "auto") + native = create_renderer(tok, chat_template_kwargs={"enable_thinking": False}) + prompt = native.render_ids( + [{"role": "user", "content": "Hi."}], add_generation_prompt=True + ) + completion = tok.encode("\nFour." + stop, add_special_tokens=False) + bridge = native.bridge_to_next_turn( + prompt, completion, [{"role": role, "content": "Next."}] + ) + assert bridge is not None + previous = prompt + completion + assert bridge.token_ids[: len(previous)] == previous + extension = tok.decode(bridge.token_ids[len(previous) :], skip_special_tokens=False) + close = "" if stop else "" + assert extension.startswith(close + "\n" + opening + "\n") + + def test_bridge_rejects_assistant_in_extension(br_renderer): prev_prompt, prev_completion = _simulate_prior_turn(br_renderer) assert (