Skip to content

Commit d77f08b

Browse files
fix: only add signature to reasoning blocks if signature is provided (#806)
* fix: only add signature to reasoning blocks if signature is provided --------- Co-authored-by: Mackenzie Zastrow <[email protected]> Co-authored-by: Dean Schmigelski <[email protected]>
1 parent ec000b8 commit d77f08b

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

src/strands/event_loop/streaming.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ async def process_stream(chunks: AsyncIterable[StreamEvent]) -> AsyncGenerator[T
289289
"text": "",
290290
"current_tool_use": {},
291291
"reasoningText": "",
292-
"signature": "",
293292
"citationsContent": [],
294293
}
295294
state["content"] = state["message"]["content"]

tests/strands/event_loop/test_streaming.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import unittest.mock
2+
from typing import cast
23

34
import pytest
45

56
import strands
67
import strands.event_loop
7-
from strands.types._events import TypedEvent
8+
from strands.types._events import ModelStopReason, TypedEvent
9+
from strands.types.content import Message
810
from strands.types.streaming import (
911
ContentBlockDeltaEvent,
1012
ContentBlockStartEvent,
@@ -565,6 +567,88 @@ async def test_process_stream(response, exp_events, agenerator, alist):
565567
assert non_typed_events == []
566568

567569

570+
def _get_message_from_event(event: ModelStopReason) -> Message:
571+
return cast(Message, event["stop"][1])
572+
573+
574+
@pytest.mark.asyncio
575+
async def test_process_stream_with_no_signature(agenerator, alist):
576+
response = [
577+
{"messageStart": {"role": "assistant"}},
578+
{
579+
"contentBlockDelta": {
580+
"delta": {"reasoningContent": {"text": 'User asks: "Reason about 2+2" so I will do that'}},
581+
"contentBlockIndex": 0,
582+
}
583+
},
584+
{"contentBlockDelta": {"delta": {"reasoningContent": {"text": "."}}, "contentBlockIndex": 0}},
585+
{"contentBlockStop": {"contentBlockIndex": 0}},
586+
{
587+
"contentBlockDelta": {
588+
"delta": {"text": "Sure! Let’s do it"},
589+
"contentBlockIndex": 1,
590+
}
591+
},
592+
{"contentBlockStop": {"contentBlockIndex": 1}},
593+
{"messageStop": {"stopReason": "end_turn"}},
594+
{
595+
"metadata": {
596+
"usage": {"inputTokens": 112, "outputTokens": 764, "totalTokens": 876},
597+
"metrics": {"latencyMs": 2970},
598+
}
599+
},
600+
]
601+
602+
stream = strands.event_loop.streaming.process_stream(agenerator(response))
603+
604+
last_event = cast(ModelStopReason, (await alist(stream))[-1])
605+
606+
message = _get_message_from_event(last_event)
607+
608+
assert "signature" not in message["content"][0]["reasoningContent"]["reasoningText"]
609+
assert message["content"][1]["text"] == "Sure! Let’s do it"
610+
611+
612+
@pytest.mark.asyncio
613+
async def test_process_stream_with_signature(agenerator, alist):
614+
response = [
615+
{"messageStart": {"role": "assistant"}},
616+
{
617+
"contentBlockDelta": {
618+
"delta": {"reasoningContent": {"text": 'User asks: "Reason about 2+2" so I will do that'}},
619+
"contentBlockIndex": 0,
620+
}
621+
},
622+
{"contentBlockDelta": {"delta": {"reasoningContent": {"text": "."}}, "contentBlockIndex": 0}},
623+
{"contentBlockDelta": {"delta": {"reasoningContent": {"signature": "test-"}}, "contentBlockIndex": 0}},
624+
{"contentBlockDelta": {"delta": {"reasoningContent": {"signature": "signature"}}, "contentBlockIndex": 0}},
625+
{"contentBlockStop": {"contentBlockIndex": 0}},
626+
{
627+
"contentBlockDelta": {
628+
"delta": {"text": "Sure! Let’s do it"},
629+
"contentBlockIndex": 1,
630+
}
631+
},
632+
{"contentBlockStop": {"contentBlockIndex": 1}},
633+
{"messageStop": {"stopReason": "end_turn"}},
634+
{
635+
"metadata": {
636+
"usage": {"inputTokens": 112, "outputTokens": 764, "totalTokens": 876},
637+
"metrics": {"latencyMs": 2970},
638+
}
639+
},
640+
]
641+
642+
stream = strands.event_loop.streaming.process_stream(agenerator(response))
643+
644+
last_event = cast(ModelStopReason, (await alist(stream))[-1])
645+
646+
message = _get_message_from_event(last_event)
647+
648+
assert message["content"][0]["reasoningContent"]["reasoningText"]["signature"] == "test-signature"
649+
assert message["content"][1]["text"] == "Sure! Let’s do it"
650+
651+
568652
@pytest.mark.asyncio
569653
async def test_stream_messages(agenerator, alist):
570654
mock_model = unittest.mock.MagicMock()

0 commit comments

Comments
 (0)