generated from amazon-archives/__template_MIT-0
-
Notifications
You must be signed in to change notification settings - Fork 491
Refactor with strands #902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
statefb
wants to merge
78
commits into
v3
Choose a base branch
from
refactor-strands
base: v3
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
78 commits
Select commit
Hold shift + click to select a range
5a69b0a
wip: add strands integration core files
statefb 184f834
update deps
statefb 6666daa
wip
statefb 08ed418
update firecrawl-py version
statefb 804ed54
insert debug logs
statefb 280ff15
fix: on_stop impl
statefb 6c6719f
wip
statefb a0ae60c
Fix reasoning content extraction from Strands AgentResult
statefb 88f9085
fix: tool use id conversion
statefb f868e5d
fix: internet
statefb bb004a2
add debug log on websocket.py
statefb f4b54b7
add pytest
statefb 045817b
add debug log on usePostMessageStreaming
statefb 81eceb7
fix: tool input / output not displayed
statefb bcb27d5
fix: reasoning not persist
statefb af402d6
add calc tool for testing
statefb fc213a2
fix: multi turn conversation
statefb 4012b5a
fix: tool registry
statefb 9093e40
fix: wait complete tool input
statefb 3399dca
fix: citation
statefb b54449a
fix: tool registry
statefb be189d4
fix: tool input consistency
statefb 810a700
fix: support list
statefb 19f7ac5
fix: list citation
statefb 46f9385
fix: citation
statefb 19c4640
remove context
statefb 733d7a9
fix: knowledge tool strands to return list
statefb 07d1798
refactor
statefb 73c77ba
update strands version
statefb 72def29
wip: chat strands refactor
statefb 8e92411
refactor: call back handler
statefb 13503b2
add post processing
statefb 56f81c5
fix: tools / utils
statefb 75b4ff4
fix: attatchment docs
statefb 28ca754
fix: image content
statefb 7187fbe
fix: continue generation
statefb d1ef26f
fix: Skip instruction messages as they are handled separately via mes…
statefb 64a2f36
change log level for websocket.py
statefb 8f2f322
lint and add comment
statefb 47a594b
remove deprecated refactorings
statefb d35a229
fix: unittest
statefb 86bee54
fix tools to return result as strands formats
statefb b3471a6
rename modules
statefb 078b767
fix: skip reasoning / tool content to construct strunds message befor…
statefb 4d207b6
fix: knowledge_search
statefb 6700468
fix: source id citation
statefb 39a9bc6
add: prompt cache (system, tool)
statefb 2ce970d
add message cache
statefb 54508b8
insert debug log
statefb 3f9d42c
return empty list when no tool
statefb 72181ee
fix: tool util
statefb 770ec40
fix bedrock agent tool
statefb ae62ab2
add deprecated decorator
statefb fffef05
update documents including examples
statefb cd59fd6
add deprication decorator
statefb 0f1d7bc
switch fetch_available_agent_tools for strands
statefb cf031d8
refactor modules for readability
statefb 603a486
chore: mypy
statefb a768b83
refactor: simplify on_stop lambda in process_chat_input
statefb 61fd258
remove unused imports on routes/bot.py
statefb 19f20ec
fix: support legacy for `fetch_available_agent_tools`
statefb 496e446
chore: lint
statefb 1e13c42
remove unused tests
statefb 54b5398
feat: implement telemetry management and data extraction for Strands …
statefb 7c0868f
convert relative import to absolute
statefb dac0589
refactor: reorganize imports and remove console exporter setup
statefb 2bc6450
Merge branch 'v3' into refactor-strands
statefb b29246b
add type notation
statefb 1c25b62
fix: change back `bedrock_agent_invoke` to original: `bedrock_agent`
statefb 2a81333
fix: change back `knowledge_search` to original: `knowledge_base_tool`
statefb 83ce685
chore: lint
statefb 1b20fd8
fix: tool example
statefb 8c19b5f
add RAG support for model which does not support tool
statefb c8614f7
Merge branch 'v3' into refactor-strands
Yukinobu-Mine 1263fa2
Merge branch 'v3' into refactor-strands
Yukinobu-Mine 48a1ea5
Refactor implementation of strands agents migration.
Yukinobu-Mine a8946b3
refactor: add _ prefix to local helper functions in strands converters
statefb 9728684
Merge branch 'v3' into refactor-strands
statefb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from .telemetry_manager import StrandsTelemetryManager | ||
from .processors import ReasoningSpanProcessor | ||
from .data_extractor import TelemetryDataExtractor | ||
|
||
__all__ = [ | ||
"StrandsTelemetryManager", | ||
"ReasoningSpanProcessor", | ||
"TelemetryDataExtractor", | ||
] |
22 changes: 22 additions & 0 deletions
22
backend/app/strands_integration/telemetry/data_extractor.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
""" | ||
Data extraction utilities for Strands telemetry. | ||
""" | ||
|
||
import logging | ||
|
||
from app.repositories.models.conversation import ReasoningContentModel | ||
|
||
from .processors import ReasoningSpanProcessor | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class TelemetryDataExtractor: | ||
"""Extracts structured data from telemetry span processors.""" | ||
|
||
def __init__(self, reasoning_processor: ReasoningSpanProcessor): | ||
self.reasoning_processor = reasoning_processor | ||
|
||
def extract_reasoning_content(self) -> list[ReasoningContentModel]: | ||
"""Extract reasoning content from telemetry data.""" | ||
return self.reasoning_processor.get_reasoning_data() |
5 changes: 5 additions & 0 deletions
5
backend/app/strands_integration/telemetry/processors/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from .reasoning_processor import ReasoningSpanProcessor | ||
|
||
__all__ = [ | ||
"ReasoningSpanProcessor", | ||
] |
136 changes: 136 additions & 0 deletions
136
backend/app/strands_integration/telemetry/processors/reasoning_processor.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
""" | ||
Reasoning span processor for Strands telemetry. | ||
""" | ||
|
||
import json | ||
import logging | ||
from typing import Any, Optional | ||
|
||
from app.repositories.models.conversation import ReasoningContentModel | ||
from opentelemetry.context import Context | ||
from opentelemetry.sdk.trace import ReadableSpan, SpanProcessor | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ReasoningSpanProcessor(SpanProcessor): | ||
"""Processes spans to extract reasoning content for DynamoDB storage.""" | ||
|
||
def __init__(self) -> None: | ||
self.reasoning_data: list[ReasoningContentModel] = [] | ||
self.conversation_id: str = "" | ||
self.user_id: str = "" | ||
|
||
def set_context(self, conversation_id: str, user_id: str) -> None: | ||
"""Set conversation context for this processor.""" | ||
self.conversation_id = conversation_id | ||
self.user_id = user_id | ||
|
||
def on_start( | ||
self, span: ReadableSpan, parent_context: Optional[Context] = None | ||
) -> None: | ||
"""Called when a span starts.""" | ||
pass | ||
|
||
def on_end(self, span: ReadableSpan) -> None: | ||
"""Called when a span ends - extract reasoning content.""" | ||
if span.name == "execute_event_loop_cycle": | ||
logger.debug(f"Processing Cycle span: {span.name}") | ||
reasoning = self._extract_reasoning_from_span(span) | ||
if reasoning: | ||
self.reasoning_data.append(reasoning) | ||
logger.debug(f"Extracted reasoning content from span: {span.name}") | ||
else: | ||
logger.debug(f"No reasoning content found in span: {span.name}") | ||
|
||
def shutdown(self) -> None: | ||
"""Called when the processor is shutdown.""" | ||
pass | ||
|
||
def force_flush(self, timeout_millis: int = 30000) -> bool: | ||
"""Force flush any pending data.""" | ||
return True | ||
|
||
def get_reasoning_data(self) -> list[ReasoningContentModel]: | ||
"""Get extracted reasoning data.""" | ||
return self.reasoning_data.copy() | ||
|
||
def _extract_reasoning_from_span( | ||
self, span: ReadableSpan | ||
) -> Optional[ReasoningContentModel]: | ||
""" | ||
Extract reasoning content from span events. | ||
|
||
Expected Data Structure: | ||
|
||
span.events contains gen_ai.choice events with the following structure: | ||
|
||
event.attributes["message"] = JSON string containing: | ||
[ | ||
{ | ||
"reasoningContent": { | ||
"reasoningText": { | ||
"text": "The user has provided what appears to be...", | ||
"signature": "ErcBCkgIBxABGAIiQLG2dqOt..." | ||
} | ||
} | ||
}, | ||
{ | ||
"text": "I'll calculate the result for you." | ||
}, | ||
{ | ||
"toolUse": { | ||
"toolUseId": "tooluse_xxx", | ||
"name": "calculator", | ||
"input": {"expression": "5432/64526234"} | ||
} | ||
} | ||
] | ||
""" | ||
if not span.events: | ||
logger.debug("No events found in span") | ||
return None | ||
|
||
for event in span.events: | ||
if event.name == "gen_ai.choice": | ||
if event.attributes is None: | ||
continue | ||
|
||
logger.debug(f"Found gen_ai.choice event: {event.attributes.keys()}") | ||
try: | ||
message_attr = event.attributes.get("message") | ||
if not isinstance(message_attr, str): | ||
continue | ||
|
||
message_content = json.loads(message_attr) | ||
logger.debug( | ||
f"Parsed message content: {len(message_content)} items" | ||
) | ||
|
||
for content_block in message_content: | ||
if "reasoningContent" in content_block: | ||
reasoning_data = content_block["reasoningContent"] | ||
logger.debug( | ||
f"Found reasoningContent: {reasoning_data.keys()}" | ||
) | ||
|
||
if "reasoningText" in reasoning_data: | ||
reasoning_text_data = reasoning_data["reasoningText"] | ||
text = reasoning_text_data.get("text", "") | ||
signature = reasoning_text_data.get("signature", "") | ||
|
||
if text: | ||
logger.debug( | ||
f"Extracted reasoning text: {len(text)} chars" | ||
) | ||
return ReasoningContentModel( | ||
content_type="reasoning", | ||
text=text, | ||
signature=signature, | ||
redacted_content=b"", | ||
) | ||
except (json.JSONDecodeError, KeyError) as e: | ||
logger.warning(f"Failed to parse reasoning content from event: {e}") | ||
|
||
logger.debug("No reasoning content found in any events") | ||
return None |
32 changes: 32 additions & 0 deletions
32
backend/app/strands_integration/telemetry/telemetry_manager.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
""" | ||
Telemetry manager for Strands integration. | ||
""" | ||
|
||
import logging | ||
from opentelemetry import trace | ||
from opentelemetry.sdk.trace import TracerProvider | ||
from strands.telemetry import StrandsTelemetry | ||
from .processors import ReasoningSpanProcessor | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class StrandsTelemetryManager: | ||
"""Manages Strands telemetry setup and span processors.""" | ||
|
||
def __init__(self): | ||
self.telemetry = StrandsTelemetry() | ||
self.reasoning_processor = ReasoningSpanProcessor() | ||
|
||
def setup(self, conversation_id: str, user_id: str): | ||
"""Setup telemetry with custom span processors.""" | ||
# Setup console exporter for development | ||
self.telemetry.setup_console_exporter() | ||
|
||
# Get the tracer provider and add our custom processors | ||
tracer_provider = trace.get_tracer_provider() | ||
if isinstance(tracer_provider, TracerProvider): | ||
tracer_provider.add_span_processor(self.reasoning_processor) | ||
logger.debug("Added custom span processors to tracer provider") | ||
|
||
self.reasoning_processor.set_context(conversation_id, user_id) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.