mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 07:17:54 +08:00
cli/history: print a row's reasoning before its answer
A reasoning trace was appended after the body it produced, which read as if the answer had come first and the thinking had followed it. It now leads the row, under its own `reasoning:` label with a blank line before the answer - the order the live stream uses. The trace only prints where it already did: a turn's ends (the default view) and -vv; previews stay silent.
This commit is contained in:
@@ -243,23 +243,36 @@ def echo_row(row: Row, *, detail: Detail) -> None:
|
||||
click.echo()
|
||||
|
||||
|
||||
def _echo_reasoning(message: AssistantChatMessage) -> None:
|
||||
"""Print the model's reasoning trace for *message*, when it has one."""
|
||||
shown = message.reasoning_content
|
||||
if not isinstance(shown, str) or not shown.strip():
|
||||
return
|
||||
click.secho("reasoning:", fg="bright_black")
|
||||
click.echo(shown)
|
||||
click.echo()
|
||||
|
||||
|
||||
def _echo_assistant(row: Row, *, reasoning: bool) -> None:
|
||||
"""Print an assistant row: the thinking first, then the answer it produced.
|
||||
|
||||
A transcript reads in the order the model produced it, and the live stream
|
||||
prints the reasoning before the answer; printing it after the body made the
|
||||
answer look like it had come before the thinking behind it.
|
||||
"""
|
||||
from plyngent.cli.display import markdown_render_available, print_markdown
|
||||
|
||||
message = row.message
|
||||
assert isinstance(message, AssistantChatMessage)
|
||||
click.echo(row.prefix())
|
||||
if reasoning:
|
||||
_echo_reasoning(message)
|
||||
content = message.content
|
||||
if isinstance(content, str) and content.strip():
|
||||
if markdown_render_available():
|
||||
print_markdown(content, label="")
|
||||
else:
|
||||
click.echo(content)
|
||||
if reasoning:
|
||||
shown = message.reasoning_content
|
||||
if isinstance(shown, str) and shown.strip():
|
||||
click.secho("reasoning:", fg="bright_black")
|
||||
click.echo(shown)
|
||||
names = _tool_call_names(message)
|
||||
if names:
|
||||
click.secho(f" tool_calls=[{', '.join(names)}]", fg="yellow")
|
||||
|
||||
@@ -140,6 +140,44 @@ async def test_double_verbose_prints_full_bodies(
|
||||
assert "You are plyngent." in out
|
||||
|
||||
|
||||
async def test_reasoning_prints_before_the_answer(
|
||||
state: ReplState,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
) -> None:
|
||||
"""A reasoning trace leads the answer it produced, as it does live."""
|
||||
state.agent.messages = [
|
||||
UserChatMessage(content="why is the sky blue?"),
|
||||
AssistantChatMessage(content="Rayleigh scattering.", reasoning_content="Light scatters off air."),
|
||||
]
|
||||
assert await handle_slash(state, "/history") is True
|
||||
out = capsys.readouterr().out
|
||||
assert "2. assistant:" in out
|
||||
assert "reasoning:\nLight scatters off air." in out
|
||||
assert out.index("reasoning:") < out.index("Rayleigh scattering.")
|
||||
assert out.index("2. assistant:") < out.index("reasoning:")
|
||||
|
||||
|
||||
async def test_reasoning_is_absent_without_one(
|
||||
state: ReplState,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
) -> None:
|
||||
state.agent.messages = [UserChatMessage(content="hi"), AssistantChatMessage(content="hello")]
|
||||
assert await handle_slash(state, "/history -vv") is True
|
||||
assert "reasoning:" not in capsys.readouterr().out
|
||||
|
||||
|
||||
async def test_preview_never_prints_reasoning(
|
||||
state: ReplState,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
) -> None:
|
||||
state.agent.messages = [
|
||||
UserChatMessage(content="why?"),
|
||||
AssistantChatMessage(content="Because.", reasoning_content="Because the docs say so."),
|
||||
]
|
||||
assert await handle_slash(state, "/history --preview") is True
|
||||
assert "Because the docs say so." not in capsys.readouterr().out
|
||||
|
||||
|
||||
async def test_verbose_keeps_local_rows_out_of_the_way(
|
||||
state: ReplState,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
|
||||
Reference in New Issue
Block a user