Skip to content

Commit 3d03a35

Browse files
feat: add support for web and search result citations (#1344)
Co-authored-by: Dean Schmigelski <[email protected]>
1 parent 4342fda commit 3d03a35

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

src/strands/types/citations.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,55 @@ class DocumentPageLocation(TypedDict, total=False):
7777
end: int
7878

7979

80+
class SearchResultLocation(TypedDict, total=False):
81+
"""Specifies a search result location within the content array.
82+
83+
Provides positioning information for cited content using search result
84+
index and block positions.
85+
86+
Attributes:
87+
searchResultIndex: The index of the search result content block where
88+
the cited content is found. Minimum value of 0.
89+
start: The starting position in the content array where the cited
90+
content begins. Minimum value of 0.
91+
end: The ending position in the content array where the cited
92+
content ends. Minimum value of 0.
93+
"""
94+
95+
searchResultIndex: int
96+
start: int
97+
end: int
98+
99+
100+
class WebLocation(TypedDict, total=False):
101+
"""Provides the URL and domain information for a cited website.
102+
103+
Contains information about the website that was cited when performing
104+
a web search.
105+
106+
Attributes:
107+
url: The URL that was cited when performing a web search.
108+
domain: The domain that was cited when performing a web search.
109+
"""
110+
111+
url: str
112+
domain: str
113+
114+
80115
# Tagged union type aliases following the ToolChoice pattern
81116
DocumentCharLocationDict = dict[Literal["documentChar"], DocumentCharLocation]
82117
DocumentPageLocationDict = dict[Literal["documentPage"], DocumentPageLocation]
83118
DocumentChunkLocationDict = dict[Literal["documentChunk"], DocumentChunkLocation]
119+
SearchResultLocationDict = dict[Literal["searchResultLocation"], SearchResultLocation]
120+
WebLocationDict = dict[Literal["web"], WebLocation]
84121

85122
# Union type for citation locations - tagged union format matching AWS Bedrock API
86123
CitationLocation = Union[
87124
DocumentCharLocationDict,
88125
DocumentPageLocationDict,
89126
DocumentChunkLocationDict,
127+
SearchResultLocationDict,
128+
WebLocationDict,
90129
]
91130

92131

tests/strands/models/test_bedrock.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,14 +2078,15 @@ async def test_citations_content_preserves_tagged_union_structure(bedrock_client
20782078
20792079
This test verifies that when messages contain citationsContent with tagged union CitationLocation objects,
20802080
the structure is preserved when sent to AWS Bedrock API. AWS Bedrock expects CitationLocation to be a
2081-
tagged union with exactly one wrapper key (documentChar, documentPage, etc.) containing the location fields.
2081+
tagged union with exactly one wrapper key (documentChar, documentPage, documentChunk, searchResultLocation, web)
2082+
containing the location fields.
20822083
"""
20832084
# Mock the Bedrock response
20842085
bedrock_client.converse_stream.return_value = {"stream": []}
20852086

2086-
# Messages with citationsContent using tagged union CitationLocation structure
2087+
# Messages with citationsContent using all tagged union CitationLocation types
20872088
messages = [
2088-
{"role": "user", "content": [{"text": "Analyze this document"}]},
2089+
{"role": "user", "content": [{"text": "Analyze multiple sources"}]},
20892090
{
20902091
"role": "assistant",
20912092
"content": [
@@ -2104,8 +2105,34 @@ async def test_citations_content_preserves_tagged_union_structure(bedrock_client
21042105
"sourceContent": [{"text": "Vacation policy allows 15 days per year"}],
21052106
"title": "Vacation Policy",
21062107
},
2108+
{
2109+
"location": {"documentChunk": {"documentIndex": 1, "start": 5, "end": 8}},
2110+
"sourceContent": [{"text": "Company culture emphasizes work-life balance"}],
2111+
"title": "Culture Section",
2112+
},
2113+
{
2114+
"location": {
2115+
"searchResultLocation": {
2116+
"searchResultIndex": 0,
2117+
"start": 25,
2118+
"end": 150,
2119+
}
2120+
},
2121+
"sourceContent": [{"text": "Search results show industry best practices"}],
2122+
"title": "Search Results",
2123+
},
2124+
{
2125+
"location": {
2126+
"web": {
2127+
"url": "https://example.com/hr-policies",
2128+
"domain": "example.com",
2129+
}
2130+
},
2131+
"sourceContent": [{"text": "External HR policy guidelines"}],
2132+
"title": "External Reference",
2133+
},
21072134
],
2108-
"content": [{"text": "Based on the document, employees receive comprehensive benefits."}],
2135+
"content": [{"text": "Based on multiple sources, the company offers comprehensive benefits."}],
21092136
}
21102137
}
21112138
],
@@ -2123,7 +2150,7 @@ async def test_citations_content_preserves_tagged_union_structure(bedrock_client
21232150
formatted_messages = call_args["messages"]
21242151
citations_content = formatted_messages[1]["content"][0]["citationsContent"]
21252152

2126-
# Verify the tagged union structure is preserved
2153+
# Verify the tagged union structure is preserved for all location types
21272154
expected_citations = [
21282155
{
21292156
"location": {"documentChar": {"documentIndex": 0, "start": 150, "end": 300}},
@@ -2135,6 +2162,32 @@ async def test_citations_content_preserves_tagged_union_structure(bedrock_client
21352162
"sourceContent": [{"text": "Vacation policy allows 15 days per year"}],
21362163
"title": "Vacation Policy",
21372164
},
2165+
{
2166+
"location": {"documentChunk": {"documentIndex": 1, "start": 5, "end": 8}},
2167+
"sourceContent": [{"text": "Company culture emphasizes work-life balance"}],
2168+
"title": "Culture Section",
2169+
},
2170+
{
2171+
"location": {
2172+
"searchResultLocation": {
2173+
"searchResultIndex": 0,
2174+
"start": 25,
2175+
"end": 150,
2176+
}
2177+
},
2178+
"sourceContent": [{"text": "Search results show industry best practices"}],
2179+
"title": "Search Results",
2180+
},
2181+
{
2182+
"location": {
2183+
"web": {
2184+
"url": "https://example.com/hr-policies",
2185+
"domain": "example.com",
2186+
}
2187+
},
2188+
"sourceContent": [{"text": "External HR policy guidelines"}],
2189+
"title": "External Reference",
2190+
},
21382191
]
21392192

21402193
assert citations_content["citations"] == expected_citations, (

0 commit comments

Comments
 (0)