非官方的 Anthropic Claude API .NET 客户端。
我们构建了一个类似于官方 Python SDK 和 TypeScript SDK 的 C# API。它支持 netstandard2.1、net6.0 和 net8.0。
除了纯客户端 SDK 外,它还包含一个用于执行函数调用的 C# 源代码生成器。
该库通过 NuGet 分发,支持 .NET Standard 2.1、.NET 6(.NET 7) 和 .NET 8 或更高版本。
PM> Install-Package Claudia
它还可以在 Unity 游戏引擎的运行时和编辑器中使用。有关使用说明,请参阅 Unity 部分。
您还可以将其与 AWS Bedrock 一起使用。有关更多详细信息,请查看 AWS Bedrock 部分。
有关 API 的详细信息,请查看官方 API 参考。
using Claudia; var anthropic = new Anthropic { ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") // 这是默认设置,可以省略 }; var message = await anthropic.Messages.CreateAsync(new() { Model = "claude-3-5-sonnet-20240620", // 您可以使用 Claudia.Models.Claude3_5Sonnet 字符串常量 MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }] }); Console.WriteLine(message);
Claudia 的设计旨在与官方客户端具有相似的外观和感觉,特别是 TypeScript SDK。然而,它不使用 object
、dynamic
或 Dictionary
,所有内容都是强类型的。通过利用 C# 9.0 目标类型化 new 表达式 和 C# 12 集合表达式,可以以简单的方式编写。
我们提供使用服务器发送事件(SSE)的流式响应支持。
using Claudia; var anthropic = new Anthropic(); var stream = anthropic.Messages.CreateStreamAsync(new() { Model = "claude-3-opus-20240229", MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }] }); await foreach (var messageStreamEvent in stream) { Console.WriteLine(messageStreamEvent); }
如果需要取消流,可以将 CancellationToken
传递给 CreateStreamAsync
。
流返回一个 IAsyncEnumerable<IMessageStreamEvent>
,允许使用 await foreach
进行枚举。IMessageStreamEvent
的实现类型可以在 IMessageStreamEvent.cs 中找到。
例如,输出文本结果。
await foreach (var messageStreamEvent in stream) { if (messageStreamEvent is ContentBlockDelta content) { Console.WriteLine(content.Delta.Text); } }
该库包含所有请求参数和响应字段的 C# 定义。您可以像这样导入和使用它们:
using Claudia; var request = new MessageRequest() { Model = Models.Claude3Opus, MaxTokens = 1024, Messages = [new() { Role = Roles.User, Content = "你好,Claude" }] };
每个方法、请求参数和响应字段的文档都可以在文档字符串中找到,并且在大多数现代编辑器中悬停时会显示。
所有 MessageRequest 定义都在这里 MessageRequest.cs,MessageResponse 定义在这里 MessageResponse.cs。
此外,还定义了常用常量。例如,Models.Claude3Opus
是 claude-3-opus-20240229
,像 "user" 和 "assistant" 这样的角色使用 Roles.User
和 Roles.Assistant
等常量。请参阅 Constant.cs 了解所有常量。另外,Claude 官方聊天界面中使用的系统提示被定义为 SystemPrompts.Claude3
。
您可以通过使用响应属性查看给定请求的确切使用情况,例如:
var message = await anthropic.Messages.CreateAsync(...) // Usage { InputTokens = 11, OutputTokens = 18 } Console.WriteLine(message.Usage);
通过与 R3(新的响应式扩展库)集成,可以以各种方式处理流式事件。
// 转换为数组 var array = await stream.ToObservable().ToArrayAsync(); // 过滤并执行 await stream.ToObservable() .OfType<IMessageStreamEvent, ContentBlockDelta>() .Where(x => x.Delta.Text != null) .ForEachAsync(x => { Console.WriteLine(x.Delta.Text); }); // 分支查询 var branch = stream.ToObservable().Publish(); var messageStartTask = branch.OfType<IMessageStreamEvent, MessageStart>().FirstAsync(); var messageDeltaTask = branch.OfType<IMessageStreamEvent, MessageDelta>().FirstAsync(); branch.Connect(); // 开始消费流 Console.WriteLine((await messageStartTask)); Console.WriteLine((await messageDeltaTask)); // 总计使用情况 var totalUsage = await stream.ToObservable() .Where(x => x is MessageStart or MessageDelta) .Select(x => x switch { MessageStart ms => ms.Message.Usage, MessageDelta delta => delta.Usage, _ => throw new ArgumentException() }) .AggregateAsync((x, y) => new Usage { InputTokens = x.InputTokens + y.InputTokens, OutputTokens = x.OutputTokens + y.OutputTokens }); Console.WriteLine(totalUsage);
当库无法连接到 API,或 API 返回非成功状态码(即 4xx 或 5xx 响应)时,将抛出 ClaudiaException
的子类:
try { var msg = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Opus, MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }] }); } catch (ClaudiaException ex) { Console.WriteLine((int)ex.Status); // 400(ErrorCode.InvalidRequestError) Console.WriteLine(ex.Name); // invalid_request_error Console.WriteLine(ex.Message); // Field required. Input:... }
错误代码如下:
public enum ErrorCode { /// <summary>请求的格式或内容有问题。</summary> InvalidRequestError = 400, /// <summary>API 密钥有问题。</summary> AuthenticationError = 401, /// <summary>您的 API 密钥没有权限使用指定的资源。</summary> PermissionError = 403, /// <summary>未找到请求的资源。</summary> NotFoundError = 404, /// <summary>您的账户已达到速率限制。</summary> RateLimitError = 429, /// <summary>Anthropic 系统内部发生了意外错误。</summary> ApiError = 500, /// <summary>Anthropic 的 API 暂时过载。</summary> OverloadedError = 529 }
默认情况下,某些错误将自动重试 2 次,并使用短指数退避。连接错误(例如,由于网络连接问题)、408 请求超时、409 冲突、429 速率限制和 >=500 内部错误默认都会重试。
您可以使用 MaxRetries
选项来配置或禁用此功能:
// 为所有请求配置默认值: var anthropic = new Anthropic { MaxRetries = 0, // 默认为 2 }; // 或者,按请求配置: await anthropic.Messages.CreateAsync(new() { MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }], Model = "claude-3-opus-20240229" }, new() { MaxRetries = 5 });
默认情况下,请求在 10 分钟后超时。您可以使用 Timeout
选项配置此设置:
// 为所有请求配置默认值: var anthropic = new Anthropic { Timeout = TimeSpan.FromSeconds(20) // 20 秒(默认为 10 分钟) };
// 覆盖每个请求: await anthropic.Messages.CreateAsync(new() { MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }], Model = "claude-3-opus-20240229" }, new() { Timeout = TimeSpan.FromSeconds(5) });
超时时会抛出 `TimeoutException`。
注意,超时的请求默认会[重试两次](#retries)。
默认标头
---
我们会自动发送 `anthropic-version` 标头,值设为 `2023-06-01`。
如果需要,你可以在每个请求的基础上覆盖它。
请注意,这样做可能会导致SDK中的类型不正确和其他意外或未定义的行为。
```csharp
await anthropic.Messages.CreateAsync(new()
{
MaxTokens = 1024,
Messages = [new() { Role = "user", Content = "你好,Claude" }],
Model = "claude-3-opus-20240229"
}, new()
{
Headers = new() { { "anthropic-version", "我的自定义值" } }
});
Anthropic客户端默认使用标准的HttpClient进行通信。如果你想自定义HttpClient的行为,可以传入一个HttpMessageHandler。此外,如果你不想在处理Anthropic客户端时处理HttpClient,可以将disposeHandler标志设置为false。
public class Anthropic : IDisposable { public HttpClient HttpClient => httpClient; public Anthropic() : this(new HttpClientHandler(), true) { } public Anthropic(HttpMessageHandler handler) : this(handler, true) { } public Anthropic(HttpMessageHandler handler, bool disposeHandler) { this.httpClient = new HttpClient(handler, disposeHandler); this.httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan; // 忽略超时,Anthropic客户端使用Timeout属性(或每个请求的覆盖)中的超时设置 } public void Dispose() { httpClient.Dispose(); } }
此外,你可以通过HttpClient
属性检索用于请求的HttpClient
。这允许你修改诸如DefaultRequestHeaders
之类的设置。
// 禁用keep-alive anthropic.HttpClient.DefaultRequestHeaders.ConnectionClose = true;
你可以更改HttpClient.BaseAddress
来更改API地址(例如,用于代理)。
// 请求发送到http://myproxy/messages而不是https://api.anthropic.com/v1/messages anthropic.HttpClient.BaseAddress = new Uri("http://myproxy/");
通过按照HttpClient约定定义DelegatingHandler
,可以在请求之前和之后钩入请求管道。这允许进行日志记录、添加遥测和检查响应标头信息。观察标头时, 你可以看到包含了与RateLimit相关的额外信息。
让我们创建一个DelegatingHandler,它检索此信息,并在发生RateLimit时抛出一个带有RateLimit信息的特殊异常。
public class RateLimitDetailsHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); if ((int)response.StatusCode == (int)ErrorCode.RateLimitError) { var requestLimit = int.Parse(response.Headers.GetValues("anthropic-ratelimit-requests-limit").First()); var requestRemaining = int.Parse(response.Headers.GetValues("anthropic-ratelimit-requests-remaining").First()); var requestReset = DateTime.Parse(response.Headers.GetValues("anthropic-ratelimit-requests-reset").First()); var tokenLimit = int.Parse(response.Headers.GetValues("anthropic-ratelimit-tokens-limit").First()); var tokenRemaining = int.Parse(response.Headers.GetValues("anthropic-ratelimit-tokens-remaining").First()); var tokenReset = DateTime.Parse(response.Headers.GetValues("anthropic-ratelimit-tokens-reset").First()); var error = await response.Content.ReadFromJsonAsync<ErrorResponseShape>(AnthropicJsonSerializerContext.Default.Options, cancellationToken); var message = error!.ErrorResponse.Message; throw new AnthropicRateLimitException(requestLimit, requestRemaining, requestReset, tokenLimit, tokenRemaining, tokenReset, message); } return response; } } public class AnthropicRateLimitException : Exception { public int RateLimitRequestsLimit { get; } public int RateLimitRequestsRemaining { get; } public DateTime RateLimitRequestsReset { get; } public int RateLimitTokensLimit { get; } public int RateLimitTokensRemaining { get; } public DateTime RateLimitTokensReset { get; } public AnthropicRateLimitException( int rateLimitRequestsLimit, int rateLimitRequestsRemaining, DateTime rateLimitRequestsReset, int rateLimitTokensLimit, int rateLimitTokensRemaining, DateTime rateLimitTokensReset, string message) : base(message) { RateLimitRequestsLimit = rateLimitRequestsLimit; RateLimitRequestsRemaining = rateLimitRequestsRemaining; RateLimitRequestsReset = rateLimitRequestsReset; RateLimitTokensLimit = rateLimitTokensLimit; RateLimitTokensRemaining = rateLimitTokensRemaining; RateLimitTokensReset = rateLimitTokensReset; } }
DelegatingHandler(HttpMessageHandler)可以传递给Anthropic
的构造函数。
var anthropic = new Anthropic(new RateLimitDetailsHandler() { InnerHandler = new HttpClientHandler() });
Message.Content
接受多个Content
对象。但是,如果传递单个字符串,它会自动转换为文本数组。
// 这段代码 Content = "你好,Claude" // 会转换为以下内容 Content = [new Content { Type = "text", Text = "你好,Claude" }]
传递图像时,在Content中同时设置图像和文本。
var imageBytes = File.ReadAllBytes(@"dish.jpg"); var anthropic = new Anthropic(); var message = await anthropic.Messages.CreateAsync(new() { Model = "claude-3-opus-20240229", MaxTokens = 1024, Messages = [new() { Role = "user", Content = [ new() { Type = "image", Source = new() { Type = "base64", MediaType = "image/jpeg", Data = imageBytes } }, new() { Type = "text", Text = "描述这张图片。" } ] }], }); Console.WriteLine(message);
上面的代码可以简化。如果将字符串传递给Content构造函数,它会被设置为文本,如果传递ReadOnlyMemory<byte>
,它会被设置为图像。
var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Opus, MaxTokens = 1024, Messages = [new() { Role = Roles.User, Content = [ new(imageBytes, "image/jpeg"), "描述这张图片。" ] }], }); Console.WriteLine(message);
目前,有四种可上传的二进制类型:image/jpeg
、image/png
、image/gif
和image/webp
。例如,如果你想上传markdown文件,最好读取其内容并作为文本发送。如果你想上传PDF,你可以将其转换为文本或图像后再发送。像pptx这样的演示文件也可以作为图像发送,Claude会为你解释内容并提取文本。
MessageRequest
的其他可选属性包括System
、Metadata
、StopSequences
、Temperature
、TopP
和TopK
。
var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = SystemPrompts.Claude3, Temperature = 0.4, Messages = [ new() { Role = Roles.User, Content = "你好,Claude" }, ], });
SystemPrompts.Claude3
是官方聊天UI中使用的系统提示的字符串常量。当然,你也可以设置任意的系统提示。
所有请求和响应模型都可以使用System.Text.Json.JsonSerializer
进行序列化。此外,AnthropicJsonSerializerContext
通过Source Generator提供了预生成的序列化器,可以实现更高的性能。
List<Message> chatMessages; void Save() { var json = JsonSerializer.Serialize(chatMessages, AnthropicJsonSerializerContext.Default.Options); File.WriteAllText("chat.json", json); } void Load() { chatMessages = JsonSerializer.Deserialize<List<Message>>("chat.json", AnthropicJsonSerializerContext.Default.Options)!; }
Claude支持函数调用。
工具使用(函数调用)是函数调用的新形式。目前它处于测试阶段,需要在标头中添加anthropic-beta
标志。
var anthropic = new Anthropic(); anthropic.HttpClient.DefaultRequestHeaders.Add("anthropic-beta", "tools-2024-04-04");
使用Claudia,你只需定义带有[ClaudiaFunction]
注解的静态方法,C# Source Generator就会自动生成必要的代码。
public static partial class FunctionTools { /// <summary> /// 获取指定时区的当前时间,格式为时-分-秒。时区应以标准格式书写,如UTC、US/Pacific、Europe/London。 /// </summary> /// <param name="timeZone">要获取当前时间的时区,如UTC、US/Pacific、Europe/London。</param> [ClaudiaFunction] public static string TimeOfDay(string timeZone) { var time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow, timeZone); return time.ToString("HH:mm:ss"); } }
partial class
包含生成的.AllTools
、.Tools.[Methods]
和.InvokeToolAsync(MessageResponse)
。
函数调用需要向Claude发送两次请求。流程如下:"在系统提示中包含可用工具的初始请求 -> 根据包含必要工具的消息执行函数 -> 将结果包含在新消息中并向Claude发送另一个请求。"
var anthropic = new Anthropic(); anthropic.HttpClient.DefaultRequestHeaders.Add("anthropic-beta", "tools-2024-04-04"); var input = new Message { Role = Roles.User, Content = "洛杉矶现在几点了?" }; var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, Tools = FunctionTools.AllTools, // 使用生成的Tools Messages = [input], }); // 调用本地函数 var toolResult = await FunctionTools.InvokeToolAsync(message); var response = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, Tools = FunctionTools.AllTools, Messages = [ input, new() { Role = Roles.Assistant, Content = message.Content }, new() { Role = Roles.User, Content = toolResult! } ], }); // 洛杉矶现在的时间是上午10:45。 Console.WriteLine(response.Content.ToString());
ClaudiaFunction
的返回类型也可以指定为Task<T>
或ValueTask<T>
。这允许您执行各种任务,如HTTP请求或数据库请求。例如,可以如上所示定义一个获取指定网页内容的函数。
public static partial class FunctionTools { // ... /// <summary> /// 从指定URL获取HTML内容。 /// </summary> /// <param name="url">要获取HTML的URL。</param> [ClaudiaFunction] static async Task<string> GetHtmlFromWeb(string url) { // 在实际应用中,传递原始HTML可能会消耗太多令牌。 // 您可以使用像AngleSharp这样的库在本地解析HTML,并将其转换为紧凑的文本结构以节省令牌。 using var client = new HttpClient(); return await client.GetStringAsync(url); } }
请注意,允许的参数类型是bool
、sbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、decimal
、float
、double
、string
、DateTime
、DateTimeOffset
、Guid
、TimeSpan
和Enum
。
返回值可以是任何类型,但它将使用ToString()
转换为字符串。如果您想返回自定义字符串,请将返回类型设为string
,并在函数内部格式化字符串。
Anthropic Cookbook提供了函数调用的示例。要实现这一点,需要复杂的XML生成和解析处理,以及基于解析结果的执行。
使用Claudia,您只需定义带有[ClaudiaFunction]
注解的静态方法,C#源代码生成器就会自动生成必要的代码,包括解析器和系统消息。
public static partial class FunctionTools { /// <summary> /// 获取指定时区的当前时间,格式为时-分-秒。时区应以标准格式书写,如UTC、US/Pacific、Europe/London。 /// </summary> /// <param name="timeZone">要获取当前时间的时区,如UTC、US/Pacific、Europe/London。</param> [ClaudiaFunction] public static string TimeOfDay(string timeZone) { var time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow, timeZone); return time.ToString("HH:mm:ss"); } }
partial class
包含生成的.SystemPrompt
和.InvokeAsync(MessageResponse)
。
函数调用需要向Claude发送两次请求。流程如下:"在系统提示中包含可用工具的初始请求 -> 根据包含必要工具的消息执行函数 -> 将结果包含在新消息中并向Claude发送另一个请求。"
// `FunctionTools.SystemPrompt`包含用于通知Claude可用工具的XML。 // 这个XML是从方法的XML文档注释生成的。 /* 在这个环境中,您可以使用一组工具来回答用户的问题。 ... 您可以这样调用它们: ... 以下是可用的工具: <tools> <tool_description> <tool_name>TimeOfDay</tool_name> <description>获取指定时区的当前时间,格式为时-分-秒。时区应以标准格式书写,如UTC、US/Pacific、Europe/London。</description> <parameters> <parameter> <name>timeZone</name> <type>string</type> <description>要获取当前时间的时区,如UTC、US/Pacific、Europe/London。</description> </parameter> </parameters> </tool_description> </tools> */ // Console.WriteLine(FunctionTools.SystemPrompt); var input = new Message { Role = Roles.User, Content = "洛杉矶现在几点了?" }; var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, // 设置生成的提示 StopSequences = [StopSequnces.CloseFunctionCalls], // 将</function_calls>设置为停止序列 Messages = [input], }); // Claude返回xml以调用工具 /* <function_calls> <invoke> <tool_name>TimeOfDay</tool_name> <parameters> <timeZone>US/Pacific</timeZone> </parameters> </invoke> */ // Console.WriteLine(message); // 自动生成的`FunctionTools.InvokeAsync`从`MessageResponse`中解析函数名和参数, // 执行相应的函数,并生成XML以通知Claude函数执行结果。 var partialAssistantMessage = await FunctionTools.InvokeAsync(message); // 通过将此消息作为Assistant响应的开头传递给Claude, // 它将提供一个考虑了函数执行结果的续写。 /* <function_calls> <invoke> <tool_name>TimeOfDay</tool_name> <parameters> <timeZone>US/Pacific</timeZone> </parameters> </invoke> </function_calls> <function_results> <result> <tool_name>TimeOfDay</tool_name> <stdout>03:27:03</stdout> </result> </function_results> */ // Console.WriteLine(partialAssistantMessage); var callResult = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, Messages = [ input, // 用户:"洛杉矶现在几点了?" new() { Role = Roles.Assistant, Content = partialAssistantMessage! } // 设置为Assistant ], }); // 洛杉矶(US/Pacific时区)的当前时间是03:36:04。 Console.WriteLine(callResult);
对于初始请求,指定StopSequences.CloseFunctionCalls
是高效的。此外,如果您想包含自己的系统提示,最好将其与生成的SystemPrompt连接起来。
ClaudiaFunction
的返回类型也可以指定为Task<T>
或ValueTask<T>
。这允许您执行各种任务,如HTTP请求或数据库请求。例如,可以如上所示定义一个获取指定网页内容的函数。
public static partial class FunctionTools { // ... /// <summary> /// 从指定URL获取HTML内容。 /// </summary> /// <param name="url">要获取HTML的URL。</param> [ClaudiaFunction] static async Task<string> GetHtmlFromWeb(string url) { // 在实际应用中,传递原始HTML可能会消耗太多令牌。 // 您可以使用像AngleSharp这样的库在本地解析HTML,并将其转换为紧凑的文本结构以节省令牌。 using var client = new HttpClient(); return await client.GetStringAsync(url); } }
var input = new Message { Role = Roles.User, Content = """ 能用三行话总结这个页面吗? https://docs.anthropic.com/claude/docs/intro-to-claude """ }; var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, // 设置生成的提示 StopSequences = [StopSequnces.CloseFunctionCalls], // 将</function_calls>设置为停止序列 Messages = [input], }); var partialAssistantMessage = await FunctionTools.InvokeAsync(message);
var callResult = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, Messages = [ input, new() { Role = Roles.Assistant, Content = partialAssistantMessage! } // 设置为助手 ], });
// 该页面可以用三行概括: // 1. Claude是由Anthropic开发的一系列大型语言模型,旨在彻底改变您与AI交互的方式。 // 2. 本文档旨在帮助您充分利用Claude,提供清晰的解释、示例、最佳实践和额外资源的链接。 // 3. Claude在涉及语言、推理、分析、编码等广泛任务中表现出色,文档涵盖了关键功能、提示入门和API使用。 Console.WriteLine(callResult);
可以定义多个函数,它们可以在一个请求中多次执行。
```csharp
public static partial class FunctionTools
{
[ClaudiaFunction]
public static string TimeOfDay(string timeZone) //...
// 示例来自 https://github.com/anthropics/anthropic-cookbook/blob/main/function_calling/function_calling.ipynb
/// <summary>
/// 用于进行基本算术的计算器函数。
/// 支持加法、减法、乘法
/// </summary>
/// <param name="firstOperand">第一个操作数(运算符之前)</param>
/// <param name="secondOperand">第二个操作数(运算符之后)</param>
/// <param name="operator">要执行的操作。必须是 +, -, *, 或 / 之一</param>
[ClaudiaFunction]
static double DoPairwiseArithmetic(double firstOperand, double secondOperand, string @operator)
{
return @operator switch
{
"+" => firstOperand + secondOperand,
"-" => firstOperand - secondOperand,
"*" => firstOperand * secondOperand,
"/" => firstOperand / secondOperand,
_ => throw new ArgumentException("不支持的操作")
};
}
}
var input = new Message { Role = Roles.User, Content = """ 西雅图和东京现在几点了? 顺便把1,984,135乘以9,343,116。 """ }; var message = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, // 设置生成的提示 StopSequences = [StopSequnces.CloseFunctionCalls], // 设置</function_calls>作为停止序列 Messages = [input], }); var partialAssistantMessage = await FunctionTools.InvokeAsync(message); var callResult = await anthropic.Messages.CreateAsync(new() { Model = Models.Claude3Haiku, MaxTokens = 1024, System = FunctionTools.SystemPrompt, Messages = [ input, new() { Role = Roles.Assistant, Content = partialAssistantMessage! } // 设置为助手 ], }); // 西雅图(美国太平洋时区)的时间是8:06:53。 // 东京(亚洲/东京时区)的时间是00:06:53。 // 1,984,135乘以9,343,116的结果是18,524,738,326,760。 Console.WriteLine(callResult);
注意,允许的参数类型为bool
、sbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、decimal
、float
、double
、string
、DateTime
、DateTimeOffset
、Guid
、TimeSpan
和Enum
。
返回值可以是任何类型,但会使用ToString()
转换为字符串。如果你想返回自定义字符串,请将返回类型设为string
并在函数内格式化字符串。
通过在Blazor中使用Claudia,你可以轻松创建如下所示的聊天界面。
所有代码可以在BlazorApp1中找到。
关键部分是Program.cs
和Home.razor.cs
中的设置。
// Program.cs // 从用户机密获取ANTHROPIC_API_KEY // https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets Environment.SetEnvironmentVariable("ANTHROPIC_API_KEY", builder.Configuration["ANTHROPIC_API_KEY"]); // 添加Anthropic客户端 builder.Services.AddSingleton<Anthropic>(); var app = builder.Build();
// Home.razor.cs using Claudia; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; namespace BlazorApp1.Components.Pages; public partial class Home { [Inject] public required Anthropic Anthropic { get; init; } double temperature = 1.0; string textInput = ""; string systemInput = SystemPrompts.Claude3; List<Message> chatMessages = new(); bool running = false; async Task SendClick() { if (running) return; if (string.IsNullOrWhiteSpace(textInput)) return; running = true; try { chatMessages.Add(new() { Role = Roles.User, Content = textInput }); var stream = Anthropic.Messages.CreateStreamAsync(new() { Model = Models.Claude3Opus, MaxTokens = 1024, Temperature = temperature, System = string.IsNullOrWhiteSpace(systemInput) ? null : systemInput, Messages = chatMessages.ToArray() }); var currentMessage = new Message { Role = Roles.Assistant, Content = "" }; chatMessages.Add(currentMessage); textInput = ""; // 清空输入 StateHasChanged(); await foreach (var messageStreamEvent in stream) { if (messageStreamEvent is ContentBlockDelta content) { currentMessage.Content[0].Text += content.Delta.Text; StateHasChanged(); } } } finally { running = false; } } }
如果需要存储聊天消息历史,可以将List<Message> chatMessages
序列化为JSON并保存到文件或数据库中。
我们通过一个单独的包提供对Anthropic Bedrock API的支持。
PM> Install-Package Claudia.Bedrock
要从AWS SDK创建AmazonBedrockRuntimeClient
并使用UseAnthropic
指定Bedrock模型ID,请将RequestMessage的Model属性设置为anthropic_version
。其余部分与常规Anthropic客户端相同。
// credentials是你自己的 AWSConfigs.AWSProfileName = ""; var bedrock = new AmazonBedrockRuntimeClient(RegionEndpoint.USEast1); var anthropic = bedrock.UseAnthropic("anthropic.claude-3-haiku-20240307-v1:0"); // 模型ID var response = await anthropic.Messages.CreateAsync(new() { Model = "bedrock-2023-05-31", // anthropic_version MaxTokens = 1024, Messages = [new() { Role = "user", Content = "你好,Claude" }] }); Console.WriteLine(response);