From 3006ad9b50f90a1e1938293518fd6f9620725a3d Mon Sep 17 00:00:00 2001
From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com>
Date: Sun, 30 Jun 2024 12:21:30 -0500
Subject: [PATCH] feat: add parameter attribute to allow customization of name,
description, and requiredness
---
.../Models/FunctionParameterAttribute.cs | 42 +++++++++++++++
.../Utils/JsonSchemaGenerator.cs | 8 +--
.../Unit/Utils/JsonSchemaGeneratorTests.cs | 54 +++++++++++++++++++
3 files changed, 101 insertions(+), 3 deletions(-)
create mode 100644 src/AnthropicClient/Models/FunctionParameterAttribute.cs
diff --git a/src/AnthropicClient/Models/FunctionParameterAttribute.cs b/src/AnthropicClient/Models/FunctionParameterAttribute.cs
new file mode 100644
index 0000000..5fb4196
--- /dev/null
+++ b/src/AnthropicClient/Models/FunctionParameterAttribute.cs
@@ -0,0 +1,42 @@
+using AnthropicClient.Utils;
+
+namespace AnthropicClient.Models;
+
+///
+/// Attribute to describe a function parameter.
+///
+[AttributeUsage(AttributeTargets.Parameter)]
+public sealed class FunctionParameterAttribute : Attribute
+{
+ ///
+ /// The name of the parameter.
+ ///
+ public string Name { get; }
+
+ ///
+ /// The description of the parameter.
+ ///
+ public string Description { get; }
+
+ ///
+ /// Whether the parameter is required.
+ ///
+ public bool Required { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the parameter.
+ /// The description of the parameter.
+ /// Whether the parameter is required.
+ /// A new instance of the class.
+ public FunctionParameterAttribute(string description, string name = "", bool required = false)
+ {
+ ArgumentValidator.ThrowIfNullOrWhitespace(description, nameof(description));
+ ArgumentValidator.ThrowIfNull(name, nameof(name));
+
+ Name = name;
+ Description = description;
+ Required = required;
+ }
+}
\ No newline at end of file
diff --git a/src/AnthropicClient/Utils/JsonSchemaGenerator.cs b/src/AnthropicClient/Utils/JsonSchemaGenerator.cs
index 4950171..95b3c13 100644
--- a/src/AnthropicClient/Utils/JsonSchemaGenerator.cs
+++ b/src/AnthropicClient/Utils/JsonSchemaGenerator.cs
@@ -36,9 +36,11 @@ static class JsonSchemaGenerator
continue;
}
- var paramName = parameter.Name;
- var paramDescription = string.Empty;
- var paramRequired = parameter.HasDefaultValue;
+ var attribute = parameter.GetCustomAttribute();
+
+ var paramName = attribute?.Name ?? parameter.Name;
+ var paramDescription = attribute?.Description ?? string.Empty;
+ var paramRequired = attribute?.Required ?? !parameter.HasDefaultValue;
var paramObject = new JsonObject();
paramObject[DescriptionKey] = paramDescription;
diff --git a/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTests.cs b/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTests.cs
index 9478caf..7194e08 100644
--- a/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTests.cs
+++ b/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTests.cs
@@ -42,4 +42,58 @@ public class JsonSchemaGeneratorTests
JsonAssert.Equal(expectedSchema, schema);
}
+
+ [Fact]
+ public void GenerateInputSchema_GivenFunctionWithParameterThatDoesNotHaveDefaultValue_ItShouldReturnSchemaWithPropertyNameDescriptionAndRequiredProperties()
+ {
+ var expectedSchema = new JsonObject()
+ {
+ ["type"] = "object",
+ ["properties"] = new JsonObject()
+ {
+ ["name"] = new JsonObject()
+ {
+ ["description"] = string.Empty
+ }
+ },
+ ["required"] = new JsonArray()
+ {
+ "name"
+ },
+ };
+
+ var testMethod = (string name) => name;
+ var function = new AnthropicFunction(testMethod.Method);
+
+ var schema = JsonSchemaGenerator.GenerateInputSchema(function);
+
+ JsonAssert.Equal(expectedSchema, schema);
+ }
+
+ [Fact]
+ public void GenerateInputSchema_GivenFunctionWithParameterThatHasAttribute_ItShouldReturnSchemaWithCorrectPropertyNameDescriptionAndRequiredProperty()
+ {
+ var expectedSchema = new JsonObject()
+ {
+ ["type"] = "object",
+ ["properties"] = new JsonObject()
+ {
+ ["Person's Age"] = new JsonObject()
+ {
+ ["description"] = "The age of the person."
+ }
+ },
+ ["required"] = new JsonArray()
+ {
+ "Person's Age"
+ },
+ };
+
+ var testMethod = ([FunctionParameter("The age of the person.", "Person's Age", true)] int name) => name;
+ var function = new AnthropicFunction(testMethod.Method);
+
+ var schema = JsonSchemaGenerator.GenerateInputSchema(function);
+
+ JsonAssert.Equal(expectedSchema, schema);
+ }
}
\ No newline at end of file