Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions slime/agent/adapters/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ def _build_reply(target: Chain, output_ids: list[int], finish: str, app) -> tupl
tools_schema=target.tools_schema,
tool_parser_name=app[TOOL_PARSER_KEY],
reasoning_parser_name=app[REASONING_PARSER_KEY],
tokenizer=tok,
)
blocks, dispatch_id = _anthropic_blocks(parsed.reasoning, parsed.text, parsed.tool_uses)
return blocks, _stop_reason(parsed.tool_uses, finish), dispatch_id
Expand Down
1 change: 1 addition & 0 deletions slime/agent/adapters/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ def _parse_turn(target: Chain, turn: TurnRecord, app) -> ParsedModelOutput:
tools_schema=target.tools_schema,
tool_parser_name=app[TOOL_PARSER_KEY],
reasoning_parser_name=app[REASONING_PARSER_KEY],
tokenizer=tok,
)


Expand Down
22 changes: 22 additions & 0 deletions slime/agent/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@

logger = logging.getLogger(__name__)

_DEFAULT_EOS_TOKEN = "<|im_end|>"


def _resolve_eos_token(tokenizer: Any | None) -> str:
"""Resolve a single EOS token from tokenizer, with fallback."""
if tokenizer is not None:
eos_token = getattr(tokenizer, "eos_token", None)
if isinstance(eos_token, str) and eos_token:
return eos_token
return _DEFAULT_EOS_TOKEN


def _strip_trailing_eos(text: str, eos_token: str) -> str:
"""Remove exactly one trailing EOS token from text."""
if not text or not eos_token:
return text or ""
if text.endswith(eos_token):
return text[: -len(eos_token)]
return text


@dataclasses.dataclass(frozen=True)
class ParsedModelOutput:
Expand All @@ -27,6 +47,7 @@ def parse_model_output(
tools_schema: list[dict] | None,
tool_parser_name: str | None,
reasoning_parser_name: str | None,
tokenizer: Any | None = None,
) -> ParsedModelOutput:
"""Parse raw model text into reasoning, visible text, and tool uses.

Expand All @@ -47,6 +68,7 @@ def parse_model_output(
reasoning, body_text = body_text.split("</think>", 1)

body_text, tool_uses = parse_tool_uses(body_text, tools_schema, tool_parser_name)
body_text = _strip_trailing_eos(body_text or "", _resolve_eos_token(tokenizer))
return ParsedModelOutput(
reasoning=reasoning,
text=(body_text or "").strip(),
Expand Down
Loading