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
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</Choose>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.9.1" />
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</Choose>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.9.1" />
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
<dependencies>
<group targetFramework="net472">
<dependency id="AWSSDK.Core" version="4.0.3.3" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.11.1" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="9.9.1" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.13" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="10.0.1" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="AWSSDK.Core" version="4.0.3.3" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.11.1" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="9.9.1" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.13" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="10.0.1" />
</group>
<group targetFramework="net8.0">
<dependency id="AWSSDK.Core" version="4.0.3.3" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.11.1" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="9.9.1" />
<dependency id="AWSSDK.BedrockRuntime" version="4.0.13" />
<dependency id="Microsoft.Extensions.AI.Abstractions" version="10.0.1" />
</group>
</dependencies>
</metadata>
Expand Down
62 changes: 44 additions & 18 deletions extensions/src/AWSSDK.Extensions.Bedrock.MEAI/BedrockChatClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ public async Task<ChatResponse> GetResponseAsync(
TextContent tc = new(citations.Content[i]?.Text) { RawRepresentation = citations.Content[i] };
tc.Annotations = [new CitationAnnotation()
{
Snippet = citations.Citations[i].SourceContent?.Select(c => c.Text).FirstOrDefault() ?? citations.Citations[i].Source,
Title = citations.Citations[i].Title,
Snippet = citations.Citations[i].SourceContent?.Select(c => c.Text).FirstOrDefault(),
Url = Uri.TryCreate(citations.Citations[i].Location?.Web?.Url, UriKind.Absolute, out Uri? uri) ? uri : null,
}];
result.Contents.Add(tc);
}
Expand Down Expand Up @@ -398,8 +399,7 @@ private static List<SystemContentBlock> CreateSystem(List<SystemContentBlock>? r
});
}

foreach (var message in messages
.Where(m => m.Role == ChatRole.System && m.Contents.Any(c => c is TextContent)))
foreach (var message in messages.Where(m => m.Role == ChatRole.System && m.Contents.Any(c => c is TextContent)))
{
system.Add(new SystemContentBlock()
{
Expand Down Expand Up @@ -500,6 +500,10 @@ private static List<ContentBlock> CreateContents(ChatMessage message)
{
switch (content)
{
case AIContent when content.RawRepresentation is ContentBlock cb:
contents.Add(cb);
break;

case TextContent tc:
if (message.Role == ChatRole.Assistant)
{
Expand Down Expand Up @@ -582,32 +586,54 @@ private static List<ContentBlock> CreateContents(ChatMessage message)
break;

case FunctionResultContent frc:
Document result = frc.Result switch
{
int i => i,
long l => l,
float f => f,
double d => d,
string s => s,
bool b => b,
JsonElement json => ToDocument(json),
{ } other => ToDocument(JsonSerializer.SerializeToElement(other, BedrockJsonContext.DefaultOptions.GetTypeInfo(other.GetType()))),
_ => default,
};

contents.Add(new()
{
ToolResult = new()
{
ToolUseId = frc.CallId,
Content = [new() { Json = new Document(new Dictionary<string, Document>() { ["result"] = result }) }],
Content = ToToolResultContentBlocks(frc.Result),
},
});
break;
}

static List<ToolResultContentBlock> ToToolResultContentBlocks(object? result) =>
result switch
{
AIContent aic => [ToolResultContentBlockFromAIContent(aic)],
IEnumerable<AIContent> aics => [.. aics.Select(ToolResultContentBlockFromAIContent)],
string s => [new () { Text = s }],
_ => [new()
{
Json = new Document(new Dictionary<string, Document>()
{
["result"] = result switch
{
int i => i,
long l => l,
float f => f,
double d => d,
bool b => b,
JsonElement json => ToDocument(json),
{ } other => ToDocument(JsonSerializer.SerializeToElement(other, BedrockJsonContext.DefaultOptions.GetTypeInfo(other.GetType()))),
_ => default,
}
})
}],
};

static ToolResultContentBlock ToolResultContentBlockFromAIContent(AIContent aic) =>
aic switch
{
TextContent tc => new() { Text = tc.Text },
TextReasoningContent trc => new() { Text = trc.Text },
DataContent dc when GetImageFormat(dc.MediaType) is { } imageFormat => new() { Image = new() { Source = new() { Bytes = new(dc.Data.ToArray()) }, Format = imageFormat } },
DataContent dc when GetVideoFormat(dc.MediaType) is { } videoFormat => new() { Video = new() { Source = new() { Bytes = new(dc.Data.ToArray()) }, Format = videoFormat } },
DataContent dc when GetDocumentFormat(dc.MediaType) is { } docFormat => new() { Document = new() { Source = new() { Bytes = new(dc.Data.ToArray()) }, Format = docFormat, Name = dc.Name ?? "file" } },
_ => ToToolResultContentBlocks(JsonSerializer.SerializeToElement(aic, BedrockJsonContext.DefaultOptions.GetTypeInfo(typeof(object)))).First(),
};

if (content.AdditionalProperties?.TryGetValue(nameof(ContentBlock.CachePoint), out var maybeCachePoint) == true)
if (content.AdditionalProperties?.TryGetValue(nameof(ContentBlock.CachePoint), out var maybeCachePoint) is true)
{
if (maybeCachePoint is CachePointBlock cachePointBlock)
{
Expand Down
Loading