diff --git a/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs b/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs
index 006a351b..42a76afb 100644
--- a/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs
+++ b/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs
@@ -146,7 +146,7 @@ where p is not null
/// A object representing the given AI content, or null if the content type is unsupported.
public static Part? ToPart(this AIContent content, ChatOptions? options = null)
{
- return content switch
+ var part = content switch
{
TextContent text => new Part { Text = text.Text },
DataContent image => new Part
@@ -175,6 +175,15 @@ where p is not null
},
_ => null,
};
+
+ if (part != null && content.AdditionalProperties != null &&
+ content.AdditionalProperties.TryGetValue(AdditionalPropertiesKeys.ThoughtSignature, out var signature) &&
+ signature is string signatureString)
+ {
+ part.ThoughtSignature = signatureString;
+ }
+
+ return part;
}
///
@@ -590,13 +599,25 @@ public static IList ToAiContents(this List? parts, ChatOptions?
{
if (part.Text is not null)
{
- (contents ??= new()).Add(new TextContent(part.Text));
+ var textContent = new TextContent(part.Text);
+ if (part.ThoughtSignature != null)
+ {
+ textContent.AdditionalProperties ??= new AdditionalPropertiesDictionary();
+ textContent.AdditionalProperties[AdditionalPropertiesKeys.ThoughtSignature] = part.ThoughtSignature;
+ }
+ (contents ??= new()).Add(textContent);
}
if (part.FunctionCall is not null)
{
- (contents ??= new()).Add(new FunctionCallContent(part.FunctionCall.Name, part.FunctionCall.Name,
- ConvertFunctionCallArg(part.FunctionCall.Args, part.FunctionCall.Name, options)));
+ var functionCallContent = new FunctionCallContent(part.FunctionCall.Name, part.FunctionCall.Name,
+ ConvertFunctionCallArg(part.FunctionCall.Args, part.FunctionCall.Name, options));
+ if (part.ThoughtSignature != null)
+ {
+ functionCallContent.AdditionalProperties ??= new AdditionalPropertiesDictionary();
+ functionCallContent.AdditionalProperties[AdditionalPropertiesKeys.ThoughtSignature] = part.ThoughtSignature;
+ }
+ (contents ??= new()).Add(functionCallContent);
}
if (part.FunctionResponse is not null)
diff --git a/tests/GenerativeAI.Microsoft.Tests/MicrosoftExtension_Tests.cs b/tests/GenerativeAI.Microsoft.Tests/MicrosoftExtension_Tests.cs
index b18a3eef..3c137c18 100644
--- a/tests/GenerativeAI.Microsoft.Tests/MicrosoftExtension_Tests.cs
+++ b/tests/GenerativeAI.Microsoft.Tests/MicrosoftExtension_Tests.cs
@@ -310,6 +310,102 @@ public void ToAiContents_BogusData_HandlesVariousParts()
// Add more specific assertions based on your Bogus rules if needed
}
+ [Fact]
+ public void ToAiContents_WithFunctionCallPart_AndThoughtSignature_ReturnsFunctionCallContentWithSignature()
+ {
+ // Arrange
+ var thoughtSignature = "some_signature";
+ var parts = new List { new Part
+ {
+ FunctionCall = new FunctionCall { Name = "myFunction", Args = JsonNode.Parse(" { \"arg1\": \"value1\", \"arg2\": \"value2\" }") },
+ ThoughtSignature = thoughtSignature
+ } };
+
+ // Act
+ var result = parts.ToAiContents();
+
+ // Assert
+ result.ShouldNotBeNull();
+ result.Count.ShouldBe(1);
+ result.FirstOrDefault().ShouldBeOfType();
+ var functionCallContent = (FunctionCallContent)result.FirstOrDefault();
+ functionCallContent.Name.ShouldBe("myFunction");
+ functionCallContent.AdditionalProperties.ShouldNotBeNull();
+ functionCallContent.AdditionalProperties.ContainsKey(AdditionalPropertiesKeys.ThoughtSignature).ShouldBeTrue();
+ functionCallContent.AdditionalProperties[AdditionalPropertiesKeys.ThoughtSignature].ShouldBe(thoughtSignature);
+ }
+
+ [Fact]
+ public void ToPart_WithFunctionCallContent_AndThoughtSignature_ReturnsPartWithSignature()
+ {
+ // Arrange
+ var thoughtSignature = "some_signature";
+ var content = new FunctionCallContent("myFunction", "name")
+ {
+ Arguments = new Dictionary()
+ {
+ {"arg1", "value1"}
+ }
+ };
+ content.AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AdditionalPropertiesKeys.ThoughtSignature, thoughtSignature }
+ };
+
+ // Act
+ var part = content.ToPart();
+
+ // Assert
+ part.ShouldNotBeNull();
+ part.FunctionCall.ShouldNotBeNull();
+ part.ThoughtSignature.ShouldBe(thoughtSignature);
+ }
+
+ [Fact]
+ public void ToAiContents_WithTextPart_AndThoughtSignature_ReturnsTextContentWithSignature()
+ {
+ // Arrange
+ var thoughtSignature = "some_signature";
+ var parts = new List { new Part
+ {
+ Text = "Hello world",
+ ThoughtSignature = thoughtSignature
+ } };
+
+ // Act
+ var result = parts.ToAiContents();
+
+ // Assert
+ result.ShouldNotBeNull();
+ result.Count.ShouldBe(1);
+ result.FirstOrDefault().ShouldBeOfType();
+ var textContent = (TextContent)result.FirstOrDefault();
+ textContent.Text.ShouldBe("Hello world");
+ textContent.AdditionalProperties.ShouldNotBeNull();
+ textContent.AdditionalProperties.ContainsKey(AdditionalPropertiesKeys.ThoughtSignature).ShouldBeTrue();
+ textContent.AdditionalProperties[AdditionalPropertiesKeys.ThoughtSignature].ShouldBe(thoughtSignature);
+ }
+
+ [Fact]
+ public void ToPart_WithTextContent_AndThoughtSignature_ReturnsPartWithSignature()
+ {
+ // Arrange
+ var thoughtSignature = "some_signature";
+ var content = new TextContent("Hello world");
+ content.AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AdditionalPropertiesKeys.ThoughtSignature, thoughtSignature }
+ };
+
+ // Act
+ var part = content.ToPart();
+
+ // Assert
+ part.ShouldNotBeNull();
+ part.Text.ShouldBe("Hello world");
+ part.ThoughtSignature.ShouldBe(thoughtSignature);
+ }
+
#endregion
#region ToGenerateContentRequest