15 Commits
Author SHA1 Message Date
Stevan Freeborn e08c94ec57 chore(release): 0.4.0 [skip ci] 2025-01-03 02:56:09 +00:00
Stevan Freeborn 5a1bf4ca41 Merge pull request #29 from StevanFreeborn/stevanfreeborn/feat/add-support-for-counting-tokens
feat: add support for counting tokens
2025-01-02 20:55:47 -06:00
Stevan Freeborn de326abe25 docs: add count message tokens example to README.md 2025-01-02 20:52:52 -06:00
Stevan Freeborn 57f66d3619 chore: remove need for beta header when using prompt caching or PDF support 2025-01-02 20:47:35 -06:00
Stevan Freeborn a23938961f tests: add integration tests to cover both 😁 and 🥲 paths when counting message tokens 2025-01-02 20:41:12 -06:00
Stevan Freeborn 4fe8bfaf0e refactor: put public method above private methods 2025-01-02 20:40:38 -06:00
Stevan Freeborn 944822060c feat: add support for count tokens endpoint 2025-01-01 20:13:01 -06:00
Stevan Freeborn 31a7097cdc fix: remove model id validation 2025-01-01 20:12:26 -06:00
Stevan Freeborn 8ef9a21a93 docs: documentation for v0.3.0 [skip ci] 2025-01-02 00:52:34 +00:00
Stevan Freeborn 87ecb6e5ad chore(release): 0.3.0 [skip ci] 2025-01-02 00:51:59 +00:00
Stevan Freeborn abf4154432 Merge pull request #28 from StevanFreeborn/stevanfreeborn/feat/add-all-UTD-model-identifiers
feat: add model identifiers
2025-01-01 18:51:37 -06:00
Stevan Freeborn 9c0a2e37b7 chore: run dotnet format 2025-01-01 18:49:52 -06:00
Stevan Freeborn f861155551 tests: add tests for new model identifiers 2025-01-01 18:46:49 -06:00
Stevan Freeborn 6e0c0654af feat: add missing model identifiers
- Added additional identifiers for existing Models
  but included the date for consistency while maintaining
  backwards compatibility for those using the existing
  identifiers.
- Added missing identifiers for new versions of the
  Models
- Added identifiers for the models supporting the
  `latest` identifier
- All identifiers sourced from this doc:
  https://docs.anthropic.com/en/docs/about-claude/models
2025-01-01 00:48:25 -06:00
Stevan Freeborn 6b6bc1b015 docs: documentation for v0.2.0 [skip ci] 2024-11-21 20:08:15 +00:00
34 changed files with 1856 additions and 143 deletions
+32 -38
View File
@@ -105,9 +105,38 @@ The primary use case for working with the Anthropic API is to create a message i
> [!NOTE] > [!NOTE]
> The following examples assume that you have already created an instance of the `AnthropicApiClient` class named `client`. You can also find these snippets in the examples directory. > The following examples assume that you have already created an instance of the `AnthropicApiClient` class named `client`. You can also find these snippets in the examples directory.
### Count Message Tokens
The `AnthropicApiClient` exposes a method named `CountMessageTokensAsync` that can be used to count the number of tokens in a message. The method requires a `CountMessageTokensRequest` instance as a parameter.
```csharp
using AnthropicClient;
using AnthropicClient.Models;
var response = await client.CountMessageTokensAsync(new CountMessageTokensRequest(
AnthropicModels.Claude3Haiku,
[
new(
MessageRole.User,
[new TextContent("Please write a haiku about the ocean.")]
)
]
));
if (response.IsFailure)
{
Console.WriteLine("Failed to count message tokens");
Console.WriteLine("Error Type: {0}", response.Error.Error.Type);
Console.WriteLine("Error Message: {0}", response.Error.Error.Message);
return;
}
Console.WriteLine("Token Count: {0}", response.Value.InputTokens);
```
### Create a message ### Create a message
The `AnthropicApiClient` exposes a single method named `CreateMessageAsync` that can be used to create a message. The method requires a `MessageRequest` or a `StreamMessageRequest` instance as a parameter. The `MessageRequest` class is used to create a message whose response is not streamed and the `StreamMessageRequest` class is used to create a message whose response is streamed. The `MessageRequest` instance's properties can be set to configure how the message is created. The `AnthropicApiClient` exposes a method named `CreateMessageAsync` that can be used to create a message. The method requires a `MessageRequest` or a `StreamMessageRequest` instance as a parameter. The `MessageRequest` class is used to create a message whose response is not streamed and the `StreamMessageRequest` class is used to create a message whose response is streamed. The `MessageRequest` instance's properties can be set to configure how the message is created.
#### Non-Streaming #### Non-Streaming
@@ -694,22 +723,7 @@ foreach (var content in response.Value.Content)
### Prompt Caching ### Prompt Caching
Anthropic has recently introduced a feature called [Prompt Caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching) that allows you to cache all or part of the prompt you send to the model. This can be used to improve the performance of your application by reducing latency and token usage. This feature is covered in depth in [Anthropic's API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching). Anthropic provides a feature called [Prompt Caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching) that allows you to cache all or part of the prompt you send to the model. This can be used to improve the performance of your application by reducing latency and token usage. This feature is covered in depth in [Anthropic's API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching).
> [!NOTE]
> This feature is in beta and requires you to set an `anthropic-beta` header on your requests to use it.
> The value of the header should be `prompt-caching-2024-07-31`.
When using this library you can opt-in to prompt caching by adding the required header to the `HttpClient` instance you provide to the `AnthropicApiClient` constructor.
```csharp
using AnthropicClient;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "prompt-caching-2024-07-31");
var client = new AnthropicApiClient(apiKey, httpClient);
```
Prompt caching can be used to cache all parts of the prompt including system messages, user messages, and tools. You should refer to the [Anthropic API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching) for specifics on limitations and requirements for using prompt caching. This library aims to make using prompt caching convenient and give you complete control over what parts of the prompt are cached. Currently there is only one type of cache control available - `EphemeralCacheControl`. Prompt caching can be used to cache all parts of the prompt including system messages, user messages, and tools. You should refer to the [Anthropic API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching) for specifics on limitations and requirements for using prompt caching. This library aims to make using prompt caching convenient and give you complete control over what parts of the prompt are cached. Currently there is only one type of cache control available - `EphemeralCacheControl`.
@@ -850,22 +864,7 @@ foreach (var content in response.Value.Content)
### PDF Support ### PDF Support
Anthropic has recently introduced a feature called [PDF Support](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support) that allows Claude to support PDF input and understand both text and visual content within documents. . This feature is covered in depth in [Anthropic's API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support). Anthropic provides a feature called [PDF Support](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support) that allows Claude to support PDF input and understand both text and visual content within documents. This feature is covered in depth in [Anthropic's API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support).
> [!NOTE]
> This feature is in beta and requires you to set an `anthropic-beta` header on your requests to use it.
> The value of the header should be `pdfs-2024-09-25`.
When using this library you can opt-in to PDF support by adding the required header to the `HttpClient` instance you provide to the `AnthropicApiClient` constructor.
```csharp
using AnthropicClient;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25");
var client = new AnthropicApiClient(apiKey, httpClient);
```
PDF support can be used to provide a PDF document as input to the model. This can be used to provide additional context to the model or to ask for additional information from the model. This library aims to make using PDF support convenient by allowing you to provide the PDF document you want Anthropic's models to consider for use when creating a message. PDF support can be used to provide a PDF document as input to the model. This can be used to provide additional context to the model or to ask for additional information from the model. This library aims to make using PDF support convenient by allowing you to provide the PDF document you want Anthropic's models to consider for use when creating a message.
@@ -885,11 +884,6 @@ var request = new MessageRequest(
] ]
); );
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25");
var client = new AnthropicApiClient(apiKey, httpClient);
var response = await client.CreateMessageAsync(request); var response = await client.CreateMessageAsync(request);
if (response.IsSuccess is false) if (response.IsSuccess is false)
@@ -154,12 +154,74 @@ Class AnthropicModels <a class="header-action link-secondary" title="View sourc
<h3 id="AnthropicClient_Models_AnthropicModels_Claude35Sonnet" data-uid="AnthropicClient.Models.AnthropicModels.Claude35Sonnet"> <h3 id="AnthropicClient_Models_AnthropicModels_Claude35Haiku20241022" data-uid="AnthropicClient.Models.AnthropicModels.Claude35Haiku20241022">
Claude35Sonnet Claude35Haiku20241022
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L21"><i class="bi bi-code-slash"></i></a> <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L66"><i class="bi bi-code-slash"></i></a>
</h3> </h3>
<div class="markdown level1 summary"><p>The Claude-3.5 Sonnet model.</p> <div class="markdown level1 summary"><p>The Claude 3.5 Haiku model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude35Haiku20241022 = &quot;claude-3-5-haiku-20241022&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude35HaikuLatest" data-uid="AnthropicClient.Models.AnthropicModels.Claude35HaikuLatest">
Claude35HaikuLatest
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L71"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3.5 Haiku model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude35HaikuLatest = &quot;claude-3-5-haiku-latest&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude35Sonnet" data-uid="AnthropicClient.Models.AnthropicModels.Claude35Sonnet">
Claude35Sonnet
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L36"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3.5 Sonnet model.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
@@ -185,12 +247,105 @@ Class AnthropicModels <a class="header-action link-secondary" title="View sourc
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Haiku" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Haiku"> <h3 id="AnthropicClient_Models_AnthropicModels_Claude35Sonnet20240620" data-uid="AnthropicClient.Models.AnthropicModels.Claude35Sonnet20240620">
Claude3Haiku Claude35Sonnet20240620
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L26"><i class="bi bi-code-slash"></i></a> <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L41"><i class="bi bi-code-slash"></i></a>
</h3> </h3>
<div class="markdown level1 summary"><p>The Claude-3 Haiku model.</p> <div class="markdown level1 summary"><p>The Claude 3.5 Sonnet model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude35Sonnet20240620 = &quot;claude-3-5-sonnet-20240620&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude35Sonnet20241022" data-uid="AnthropicClient.Models.AnthropicModels.Claude35Sonnet20241022">
Claude35Sonnet20241022
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L46"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3.5 Sonnet model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude35Sonnet20241022 = &quot;claude-3-5-sonnet-20241022&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude35SonnetLatest" data-uid="AnthropicClient.Models.AnthropicModels.Claude35SonnetLatest">
Claude35SonnetLatest
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L51"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3.5 Sonnet model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude35SonnetLatest = &quot;claude-3-5-sonnet-latest&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Haiku" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Haiku">
Claude3Haiku
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L56"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3 Haiku model.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
@@ -216,12 +371,43 @@ Class AnthropicModels <a class="header-action link-secondary" title="View sourc
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Haiku20240307" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Haiku20240307">
Claude3Haiku20240307
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L61"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3 Haiku model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude3Haiku20240307 = &quot;claude-3-haiku-20240307&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Opus" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Opus"> <h3 id="AnthropicClient_Models_AnthropicModels_Claude3Opus" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Opus">
Claude3Opus Claude3Opus
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L11"><i class="bi bi-code-slash"></i></a> <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L11"><i class="bi bi-code-slash"></i></a>
</h3> </h3>
<div class="markdown level1 summary"><p>The Claude-3 Opus model.</p> <div class="markdown level1 summary"><p>The Claude 3 Opus model.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
@@ -247,12 +433,74 @@ Class AnthropicModels <a class="header-action link-secondary" title="View sourc
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Sonnet" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Sonnet"> <h3 id="AnthropicClient_Models_AnthropicModels_Claude3Opus20241022" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Opus20241022">
Claude3Sonnet Claude3Opus20241022
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L16"><i class="bi bi-code-slash"></i></a> <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L16"><i class="bi bi-code-slash"></i></a>
</h3> </h3>
<div class="markdown level1 summary"><p>The Claude-3 Sonnet model.</p> <div class="markdown level1 summary"><p>The Claude 3 Opus model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude3Opus20241022 = &quot;claude-3-opus-20240229&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3OpusLatest" data-uid="AnthropicClient.Models.AnthropicModels.Claude3OpusLatest">
Claude3OpusLatest
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L21"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3 Opus model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude3OpusLatest = &quot;claude-3-opus-latest&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Sonnet" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Sonnet">
Claude3Sonnet
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L26"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3 Sonnet model.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
@@ -278,6 +526,37 @@ Class AnthropicModels <a class="header-action link-secondary" title="View sourc
<h3 id="AnthropicClient_Models_AnthropicModels_Claude3Sonnet20240229" data-uid="AnthropicClient.Models.AnthropicModels.Claude3Sonnet20240229">
Claude3Sonnet20240229
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/AnthropicModels.cs/#L31"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>The Claude 3 Sonnet model.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Claude3Sonnet20240229 = &quot;claude-3-sonnet-20240229&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
</article> </article>
<div class="contribution d-print-none"> <div class="contribution d-print-none">
@@ -120,6 +120,7 @@ Class Content <a class="header-action link-secondary" title="View source" href=
<dl class="typelist derived"> <dl class="typelist derived">
<dt>Derived</dt> <dt>Derived</dt>
<dd> <dd>
<div><a class="xref" href="AnthropicClient.Models.DocumentContent.html">DocumentContent</a></div>
<div><a class="xref" href="AnthropicClient.Models.ImageContent.html">ImageContent</a></div> <div><a class="xref" href="AnthropicClient.Models.ImageContent.html">ImageContent</a></div>
<div><a class="xref" href="AnthropicClient.Models.TextContent.html">TextContent</a></div> <div><a class="xref" href="AnthropicClient.Models.TextContent.html">TextContent</a></div>
<div><a class="xref" href="AnthropicClient.Models.ToolResultContent.html">ToolResultContent</a></div> <div><a class="xref" href="AnthropicClient.Models.ToolResultContent.html">ToolResultContent</a></div>
@@ -154,6 +154,37 @@ Class ContentType <a class="header-action link-secondary" title="View source" h
<h3 id="AnthropicClient_Models_ContentType_Document" data-uid="AnthropicClient.Models.ContentType.Document">
Document
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/ContentType.cs/#L31"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Represents the document content type.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Document = &quot;document&quot;</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h3 id="AnthropicClient_Models_ContentType_Image" data-uid="AnthropicClient.Models.ContentType.Image"> <h3 id="AnthropicClient_Models_ContentType_Image" data-uid="AnthropicClient.Models.ContentType.Image">
Image Image
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/ContentType.cs/#L16"><i class="bi bi-code-slash"></i></a> <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/ContentType.cs/#L16"><i class="bi bi-code-slash"></i></a>
@@ -0,0 +1,311 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class DocumentContent | AnthropicClient </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class DocumentContent | AnthropicClient ">
<meta name="description" content="Represents content from a document that is part of a message.">
<link rel="icon" href="../favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/StevanFreeborn/anthropic-client/new/main/apiSpec/new?filename=AnthropicClient_Models_DocumentContent.md&amp;value=---%0Auid%3A%20AnthropicClient.Models.DocumentContent%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="AnthropicClient">
AnthropicClient
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="AnthropicClient.Models.DocumentContent">
<h1 id="AnthropicClient_Models_DocumentContent" data-uid="AnthropicClient.Models.DocumentContent" class="text-break">
Class DocumentContent <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentContent.cs/#L10"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="AnthropicClient.html">AnthropicClient</a>.<a class="xref" href="AnthropicClient.Models.html">Models</a></dd></dl>
<dl><dt>Assembly</dt><dd>AnthropicClient.dll</dd></dl>
</div>
<div class="markdown summary"><p>Represents content from a document that is part of a message.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public class DocumentContent : Content</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><a class="xref" href="AnthropicClient.Models.Content.html">Content</a></div>
<div><span class="xref">DocumentContent</span></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="AnthropicClient.Models.Content.html#AnthropicClient_Models_Content_Type">Content.Type</a>
</div>
<div>
<a class="xref" href="AnthropicClient.Models.Content.html#AnthropicClient_Models_Content_CacheControl">Content.CacheControl</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="AnthropicClient_Models_DocumentContent__ctor_" data-uid="AnthropicClient.Models.DocumentContent.#ctor*"></a>
<h3 id="AnthropicClient_Models_DocumentContent__ctor_System_String_System_String_" data-uid="AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String)">
DocumentContent(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentContent.cs/#L35"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Initializes a new instance of the <a class="xref" href="AnthropicClient.Models.DocumentContent.html">DocumentContent</a> class.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public DocumentContent(string mediaType, string data)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>mediaType</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The media type of the document.</p>
</dd>
<dt><code>data</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The data of the document.</p>
</dd>
</dl>
<h4 class="section">Exceptions</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.argumentnullexception">ArgumentNullException</a></dt>
<dd><p>Thrown when the media type or data is null.</p>
</dd>
</dl>
<a id="AnthropicClient_Models_DocumentContent__ctor_" data-uid="AnthropicClient.Models.DocumentContent.#ctor*"></a>
<h3 id="AnthropicClient_Models_DocumentContent__ctor_System_String_System_String_AnthropicClient_Models_CacheControl_" data-uid="AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String,AnthropicClient.Models.CacheControl)">
DocumentContent(string, string, CacheControl)
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentContent.cs/#L50"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Initializes a new instance of the <a class="xref" href="AnthropicClient.Models.DocumentContent.html">DocumentContent</a> class.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public DocumentContent(string mediaType, string data, CacheControl cacheControl)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>mediaType</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The media type of the document.</p>
</dd>
<dt><code>data</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The data of the document.</p>
</dd>
<dt><code>cacheControl</code> <a class="xref" href="AnthropicClient.Models.CacheControl.html">CacheControl</a></dt>
<dd><p>The cache control to be used for the content.</p>
</dd>
</dl>
<h4 class="section">Exceptions</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.argumentnullexception">ArgumentNullException</a></dt>
<dd><p>Thrown when the media type, data, or cache control is null.</p>
</dd>
</dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="AnthropicClient_Models_DocumentContent_Source_" data-uid="AnthropicClient.Models.DocumentContent.Source*"></a>
<h3 id="AnthropicClient_Models_DocumentContent_Source" data-uid="AnthropicClient.Models.DocumentContent.Source">
Source
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentContent.cs/#L15"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Gets the source of the document.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public DocumentSource Source { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="AnthropicClient.Models.DocumentSource.html">DocumentSource</a></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentContent.cs/#L10" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span>Made with <a href="https://dotnet.github.io/docfx">docfx</a></span>
</div>
</div>
</footer>
</body>
</html>
@@ -0,0 +1,327 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class DocumentSource | AnthropicClient </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class DocumentSource | AnthropicClient ">
<meta name="description" content="Represents a document source.">
<link rel="icon" href="../favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/StevanFreeborn/anthropic-client/new/main/apiSpec/new?filename=AnthropicClient_Models_DocumentSource.md&amp;value=---%0Auid%3A%20AnthropicClient.Models.DocumentSource%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="AnthropicClient">
AnthropicClient
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="AnthropicClient.Models.DocumentSource">
<h1 id="AnthropicClient_Models_DocumentSource" data-uid="AnthropicClient.Models.DocumentSource" class="text-break">
Class DocumentSource <a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L10"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="AnthropicClient.html">AnthropicClient</a>.<a class="xref" href="AnthropicClient.Models.html">Models</a></dd></dl>
<dl><dt>Assembly</dt><dd>AnthropicClient.dll</dd></dl>
</div>
<div class="markdown summary"><p>Represents a document source.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public class DocumentSource</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">DocumentSource</span></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="AnthropicClient_Models_DocumentSource__ctor_" data-uid="AnthropicClient.Models.DocumentSource.#ctor*"></a>
<h3 id="AnthropicClient_Models_DocumentSource__ctor_System_String_System_String_" data-uid="AnthropicClient.Models.DocumentSource.#ctor(System.String,System.String)">
DocumentSource(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L41"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Initializes a new instance of the <a class="xref" href="AnthropicClient.Models.DocumentSource.html">DocumentSource</a> class.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public DocumentSource(string mediaType, string data)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>mediaType</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The media type of the document.</p>
</dd>
<dt><code>data</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd><p>The data of the document.</p>
</dd>
</dl>
<h4 class="section">Exceptions</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.argumentexception">ArgumentException</a></dt>
<dd><p>Thrown when the media type is invalid.</p>
</dd>
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.argumentnullexception">ArgumentNullException</a></dt>
<dd><p>Thrown when the media type or data is null.</p>
</dd>
</dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="AnthropicClient_Models_DocumentSource_Data_" data-uid="AnthropicClient.Models.DocumentSource.Data*"></a>
<h3 id="AnthropicClient_Models_DocumentSource_Data" data-uid="AnthropicClient.Models.DocumentSource.Data">
Data
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L21"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Gets the data of the document.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string Data { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="AnthropicClient_Models_DocumentSource_MediaType_" data-uid="AnthropicClient.Models.DocumentSource.MediaType*"></a>
<h3 id="AnthropicClient_Models_DocumentSource_MediaType" data-uid="AnthropicClient.Models.DocumentSource.MediaType">
MediaType
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L15"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Gets the media type of the document.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">[JsonPropertyName(&quot;media_type&quot;)]
public string MediaType { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="AnthropicClient_Models_DocumentSource_Type_" data-uid="AnthropicClient.Models.DocumentSource.Type*"></a>
<h3 id="AnthropicClient_Models_DocumentSource_Type" data-uid="AnthropicClient.Models.DocumentSource.Type">
Type
<a class="header-action link-secondary" title="View source" href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L26"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Gets the type of encoding of the document data.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string Type { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/StevanFreeborn/anthropic-client/blob/main/src/AnthropicClient/Models/DocumentSource.cs/#L10" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span>Made with <a href="https://dotnet.github.io/docfx">docfx</a></span>
</div>
</div>
</footer>
</body>
</html>
+10
View File
@@ -187,6 +187,16 @@ Classes
<dl class="jumplist"> <dl class="jumplist">
<dt><a class="xref" href="AnthropicClient.Models.ContentType.html">ContentType</a></dt> <dt><a class="xref" href="AnthropicClient.Models.ContentType.html">ContentType</a></dt>
<dd><p>Represents the content type.</p> <dd><p>Represents the content type.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="AnthropicClient.Models.DocumentContent.html">DocumentContent</a></dt>
<dd><p>Represents content from a document that is part of a message.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="AnthropicClient.Models.DocumentSource.html">DocumentSource</a></dt>
<dd><p>Represents a document source.</p>
</dd> </dd>
</dl> </dl>
<dl class="jumplist"> <dl class="jumplist">
+6
View File
@@ -87,6 +87,12 @@
<li> <li>
<a href="AnthropicClient.Models.ContentType.html" name="" title="ContentType">ContentType</a> <a href="AnthropicClient.Models.ContentType.html" name="" title="ContentType">ContentType</a>
</li> </li>
<li>
<a href="AnthropicClient.Models.DocumentContent.html" name="" title="DocumentContent">DocumentContent</a>
</li>
<li>
<a href="AnthropicClient.Models.DocumentSource.html" name="" title="DocumentSource">DocumentSource</a>
</li>
<li> <li>
<a href="AnthropicClient.Models.EphemeralCacheControl.html" name="" title="EphemeralCacheControl">EphemeralCacheControl</a> <a href="AnthropicClient.Models.EphemeralCacheControl.html" name="" title="EphemeralCacheControl">EphemeralCacheControl</a>
</li> </li>
+1 -1
View File
File diff suppressed because one or more lines are too long
+54
View File
@@ -812,6 +812,60 @@ foreach (var content in response.Value.Content)
} }
} }
</code></pre> </code></pre>
<h3 id="pdf-support">PDF Support</h3>
<p>Anthropic has recently introduced a feature called <a href="https://docs.anthropic.com/en/docs/build-with-claude/pdf-support">PDF Support</a> that allows Claude to support PDF input and understand both text and visual content within documents. . This feature is covered in depth in <a href="https://docs.anthropic.com/en/docs/build-with-claude/pdf-support">Anthropic's API Documentation</a>.</p>
<div class="NOTE">
<h5>Note</h5>
<p>This feature is in beta and requires you to set an <code>anthropic-beta</code> header on your requests to use it.
The value of the header should be <code>pdfs-2024-09-25</code>.</p>
</div>
<p>When using this library you can opt-in to PDF support by adding the required header to the <code>HttpClient</code> instance you provide to the <code>AnthropicApiClient</code> constructor.</p>
<pre><code class="lang-csharp">using AnthropicClient;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add(&quot;anthropic-beta&quot;, &quot;pdfs-2024-09-25&quot;);
var client = new AnthropicApiClient(apiKey, httpClient);
</code></pre>
<p>PDF support can be used to provide a PDF document as input to the model. This can be used to provide additional context to the model or to ask for additional information from the model. This library aims to make using PDF support convenient by allowing you to provide the PDF document you want Anthropic's models to consider for use when creating a message.</p>
<h4 id="pdf-document">PDF Document</h4>
<p>You can provide a PDF document by providing its base64 encoded content as a <code>DocumentContent</code> instance in the list of messages in the <code>MessageRequest</code> or <code>StreamMessageRequest</code> constructor.</p>
<pre><code class="lang-csharp">using AnthropicClient;
using AnthropicClient.Models;
var request = new MessageRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [new TextContent(&quot;What is the title of this paper?&quot;)]),
new(MessageRole.User, [new DocumentContent(&quot;application/pdf&quot;, base64Data)])
]
);
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add(&quot;anthropic-beta&quot;, &quot;pdfs-2024-09-25&quot;);
var client = new AnthropicApiClient(apiKey, httpClient);
var response = await client.CreateMessageAsync(request);
if (response.IsSuccess is false)
{
Console.WriteLine(&quot;Failed to create message&quot;);
Console.WriteLine(&quot;Error Type: {0}&quot;, response.Error.Error.Type);
Console.WriteLine(&quot;Error Message: {0}&quot;, response.Error.Error.Message);
return;
}
foreach (var content in response.Value.Content)
{
switch (content)
{
case TextContent textContent:
Console.WriteLine(textContent.Text);
break;
}
}
</code></pre>
</article> </article>
+15 -5
View File
File diff suppressed because one or more lines are too long
+26 -6
View File
@@ -220,6 +220,26 @@
}, },
"version": "" "version": ""
}, },
{
"type": "ManagedReference",
"source_relative_path": "api/AnthropicClient.Models.DocumentContent.yml",
"output": {
".html": {
"relative_path": "api/AnthropicClient.Models.DocumentContent.html"
}
},
"version": ""
},
{
"type": "ManagedReference",
"source_relative_path": "api/AnthropicClient.Models.DocumentSource.yml",
"output": {
".html": {
"relative_path": "api/AnthropicClient.Models.DocumentSource.html"
}
},
"version": ""
},
{ {
"type": "ManagedReference", "type": "ManagedReference",
"source_relative_path": "api/AnthropicClient.Models.EphemeralCacheControl.yml", "source_relative_path": "api/AnthropicClient.Models.EphemeralCacheControl.yml",
@@ -674,11 +694,11 @@
"type": "Toc", "type": "Toc",
"source_relative_path": "api/toc.yml", "source_relative_path": "api/toc.yml",
"output": { "output": {
".json": {
"relative_path": "api/toc.json"
},
".html": { ".html": {
"relative_path": "api/toc.html" "relative_path": "api/toc.html"
},
".json": {
"relative_path": "api/toc.json"
} }
}, },
"version": "" "version": ""
@@ -697,11 +717,11 @@
"type": "Toc", "type": "Toc",
"source_relative_path": "toc.yml", "source_relative_path": "toc.yml",
"output": { "output": {
".json": {
"relative_path": "toc.json"
},
".html": { ".html": {
"relative_path": "toc.html" "relative_path": "toc.html"
},
".json": {
"relative_path": "toc.json"
} }
}, },
"version": "" "version": ""
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+20 -20
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+171
View File
@@ -351,30 +351,84 @@ references:
commentId: T:AnthropicClient.Models.AnthropicModels commentId: T:AnthropicClient.Models.AnthropicModels
fullName: AnthropicClient.Models.AnthropicModels fullName: AnthropicClient.Models.AnthropicModels
nameWithType: AnthropicModels nameWithType: AnthropicModels
- uid: AnthropicClient.Models.AnthropicModels.Claude35Haiku20241022
name: Claude35Haiku20241022
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35Haiku20241022
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35Haiku20241022
fullName: AnthropicClient.Models.AnthropicModels.Claude35Haiku20241022
nameWithType: AnthropicModels.Claude35Haiku20241022
- uid: AnthropicClient.Models.AnthropicModels.Claude35HaikuLatest
name: Claude35HaikuLatest
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35HaikuLatest
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35HaikuLatest
fullName: AnthropicClient.Models.AnthropicModels.Claude35HaikuLatest
nameWithType: AnthropicModels.Claude35HaikuLatest
- uid: AnthropicClient.Models.AnthropicModels.Claude35Sonnet - uid: AnthropicClient.Models.AnthropicModels.Claude35Sonnet
name: Claude35Sonnet name: Claude35Sonnet
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35Sonnet href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35Sonnet
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35Sonnet commentId: F:AnthropicClient.Models.AnthropicModels.Claude35Sonnet
fullName: AnthropicClient.Models.AnthropicModels.Claude35Sonnet fullName: AnthropicClient.Models.AnthropicModels.Claude35Sonnet
nameWithType: AnthropicModels.Claude35Sonnet nameWithType: AnthropicModels.Claude35Sonnet
- uid: AnthropicClient.Models.AnthropicModels.Claude35Sonnet20240620
name: Claude35Sonnet20240620
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35Sonnet20240620
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35Sonnet20240620
fullName: AnthropicClient.Models.AnthropicModels.Claude35Sonnet20240620
nameWithType: AnthropicModels.Claude35Sonnet20240620
- uid: AnthropicClient.Models.AnthropicModels.Claude35Sonnet20241022
name: Claude35Sonnet20241022
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35Sonnet20241022
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35Sonnet20241022
fullName: AnthropicClient.Models.AnthropicModels.Claude35Sonnet20241022
nameWithType: AnthropicModels.Claude35Sonnet20241022
- uid: AnthropicClient.Models.AnthropicModels.Claude35SonnetLatest
name: Claude35SonnetLatest
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude35SonnetLatest
commentId: F:AnthropicClient.Models.AnthropicModels.Claude35SonnetLatest
fullName: AnthropicClient.Models.AnthropicModels.Claude35SonnetLatest
nameWithType: AnthropicModels.Claude35SonnetLatest
- uid: AnthropicClient.Models.AnthropicModels.Claude3Haiku - uid: AnthropicClient.Models.AnthropicModels.Claude3Haiku
name: Claude3Haiku name: Claude3Haiku
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Haiku href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Haiku
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Haiku commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Haiku
fullName: AnthropicClient.Models.AnthropicModels.Claude3Haiku fullName: AnthropicClient.Models.AnthropicModels.Claude3Haiku
nameWithType: AnthropicModels.Claude3Haiku nameWithType: AnthropicModels.Claude3Haiku
- uid: AnthropicClient.Models.AnthropicModels.Claude3Haiku20240307
name: Claude3Haiku20240307
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Haiku20240307
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Haiku20240307
fullName: AnthropicClient.Models.AnthropicModels.Claude3Haiku20240307
nameWithType: AnthropicModels.Claude3Haiku20240307
- uid: AnthropicClient.Models.AnthropicModels.Claude3Opus - uid: AnthropicClient.Models.AnthropicModels.Claude3Opus
name: Claude3Opus name: Claude3Opus
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Opus href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Opus
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Opus commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Opus
fullName: AnthropicClient.Models.AnthropicModels.Claude3Opus fullName: AnthropicClient.Models.AnthropicModels.Claude3Opus
nameWithType: AnthropicModels.Claude3Opus nameWithType: AnthropicModels.Claude3Opus
- uid: AnthropicClient.Models.AnthropicModels.Claude3Opus20241022
name: Claude3Opus20241022
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Opus20241022
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Opus20241022
fullName: AnthropicClient.Models.AnthropicModels.Claude3Opus20241022
nameWithType: AnthropicModels.Claude3Opus20241022
- uid: AnthropicClient.Models.AnthropicModels.Claude3OpusLatest
name: Claude3OpusLatest
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3OpusLatest
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3OpusLatest
fullName: AnthropicClient.Models.AnthropicModels.Claude3OpusLatest
nameWithType: AnthropicModels.Claude3OpusLatest
- uid: AnthropicClient.Models.AnthropicModels.Claude3Sonnet - uid: AnthropicClient.Models.AnthropicModels.Claude3Sonnet
name: Claude3Sonnet name: Claude3Sonnet
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Sonnet href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Sonnet
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Sonnet commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Sonnet
fullName: AnthropicClient.Models.AnthropicModels.Claude3Sonnet fullName: AnthropicClient.Models.AnthropicModels.Claude3Sonnet
nameWithType: AnthropicModels.Claude3Sonnet nameWithType: AnthropicModels.Claude3Sonnet
- uid: AnthropicClient.Models.AnthropicModels.Claude3Sonnet20240229
name: Claude3Sonnet20240229
href: api/AnthropicClient.Models.AnthropicModels.html#AnthropicClient_Models_AnthropicModels_Claude3Sonnet20240229
commentId: F:AnthropicClient.Models.AnthropicModels.Claude3Sonnet20240229
fullName: AnthropicClient.Models.AnthropicModels.Claude3Sonnet20240229
nameWithType: AnthropicModels.Claude3Sonnet20240229
- uid: AnthropicClient.Models.AnyToolChoice - uid: AnthropicClient.Models.AnyToolChoice
name: AnyToolChoice name: AnyToolChoice
href: api/AnthropicClient.Models.AnyToolChoice.html href: api/AnthropicClient.Models.AnyToolChoice.html
@@ -994,6 +1048,12 @@ references:
commentId: T:AnthropicClient.Models.ContentType commentId: T:AnthropicClient.Models.ContentType
fullName: AnthropicClient.Models.ContentType fullName: AnthropicClient.Models.ContentType
nameWithType: ContentType nameWithType: ContentType
- uid: AnthropicClient.Models.ContentType.Document
name: Document
href: api/AnthropicClient.Models.ContentType.html#AnthropicClient_Models_ContentType_Document
commentId: F:AnthropicClient.Models.ContentType.Document
fullName: AnthropicClient.Models.ContentType.Document
nameWithType: ContentType.Document
- uid: AnthropicClient.Models.ContentType.Image - uid: AnthropicClient.Models.ContentType.Image
name: Image name: Image
href: api/AnthropicClient.Models.ContentType.html#AnthropicClient_Models_ContentType_Image href: api/AnthropicClient.Models.ContentType.html#AnthropicClient_Models_ContentType_Image
@@ -1018,6 +1078,117 @@ references:
commentId: F:AnthropicClient.Models.ContentType.ToolUse commentId: F:AnthropicClient.Models.ContentType.ToolUse
fullName: AnthropicClient.Models.ContentType.ToolUse fullName: AnthropicClient.Models.ContentType.ToolUse
nameWithType: ContentType.ToolUse nameWithType: ContentType.ToolUse
- uid: AnthropicClient.Models.DocumentContent
name: DocumentContent
href: api/AnthropicClient.Models.DocumentContent.html
commentId: T:AnthropicClient.Models.DocumentContent
fullName: AnthropicClient.Models.DocumentContent
nameWithType: DocumentContent
- uid: AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String)
name: DocumentContent(string, string)
href: api/AnthropicClient.Models.DocumentContent.html#AnthropicClient_Models_DocumentContent__ctor_System_String_System_String_
commentId: M:AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String)
name.vb: New(String, String)
fullName: AnthropicClient.Models.DocumentContent.DocumentContent(string, string)
fullName.vb: AnthropicClient.Models.DocumentContent.New(String, String)
nameWithType: DocumentContent.DocumentContent(string, string)
nameWithType.vb: DocumentContent.New(String, String)
- uid: AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String,AnthropicClient.Models.CacheControl)
name: DocumentContent(string, string, CacheControl)
href: api/AnthropicClient.Models.DocumentContent.html#AnthropicClient_Models_DocumentContent__ctor_System_String_System_String_AnthropicClient_Models_CacheControl_
commentId: M:AnthropicClient.Models.DocumentContent.#ctor(System.String,System.String,AnthropicClient.Models.CacheControl)
name.vb: New(String, String, CacheControl)
fullName: AnthropicClient.Models.DocumentContent.DocumentContent(string, string, AnthropicClient.Models.CacheControl)
fullName.vb: AnthropicClient.Models.DocumentContent.New(String, String, AnthropicClient.Models.CacheControl)
nameWithType: DocumentContent.DocumentContent(string, string, CacheControl)
nameWithType.vb: DocumentContent.New(String, String, CacheControl)
- uid: AnthropicClient.Models.DocumentContent.#ctor*
name: DocumentContent
href: api/AnthropicClient.Models.DocumentContent.html#AnthropicClient_Models_DocumentContent__ctor_
commentId: Overload:AnthropicClient.Models.DocumentContent.#ctor
isSpec: "True"
name.vb: New
fullName: AnthropicClient.Models.DocumentContent.DocumentContent
fullName.vb: AnthropicClient.Models.DocumentContent.New
nameWithType: DocumentContent.DocumentContent
nameWithType.vb: DocumentContent.New
- uid: AnthropicClient.Models.DocumentContent.Source
name: Source
href: api/AnthropicClient.Models.DocumentContent.html#AnthropicClient_Models_DocumentContent_Source
commentId: P:AnthropicClient.Models.DocumentContent.Source
fullName: AnthropicClient.Models.DocumentContent.Source
nameWithType: DocumentContent.Source
- uid: AnthropicClient.Models.DocumentContent.Source*
name: Source
href: api/AnthropicClient.Models.DocumentContent.html#AnthropicClient_Models_DocumentContent_Source_
commentId: Overload:AnthropicClient.Models.DocumentContent.Source
isSpec: "True"
fullName: AnthropicClient.Models.DocumentContent.Source
nameWithType: DocumentContent.Source
- uid: AnthropicClient.Models.DocumentSource
name: DocumentSource
href: api/AnthropicClient.Models.DocumentSource.html
commentId: T:AnthropicClient.Models.DocumentSource
fullName: AnthropicClient.Models.DocumentSource
nameWithType: DocumentSource
- uid: AnthropicClient.Models.DocumentSource.#ctor(System.String,System.String)
name: DocumentSource(string, string)
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource__ctor_System_String_System_String_
commentId: M:AnthropicClient.Models.DocumentSource.#ctor(System.String,System.String)
name.vb: New(String, String)
fullName: AnthropicClient.Models.DocumentSource.DocumentSource(string, string)
fullName.vb: AnthropicClient.Models.DocumentSource.New(String, String)
nameWithType: DocumentSource.DocumentSource(string, string)
nameWithType.vb: DocumentSource.New(String, String)
- uid: AnthropicClient.Models.DocumentSource.#ctor*
name: DocumentSource
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource__ctor_
commentId: Overload:AnthropicClient.Models.DocumentSource.#ctor
isSpec: "True"
name.vb: New
fullName: AnthropicClient.Models.DocumentSource.DocumentSource
fullName.vb: AnthropicClient.Models.DocumentSource.New
nameWithType: DocumentSource.DocumentSource
nameWithType.vb: DocumentSource.New
- uid: AnthropicClient.Models.DocumentSource.Data
name: Data
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_Data
commentId: P:AnthropicClient.Models.DocumentSource.Data
fullName: AnthropicClient.Models.DocumentSource.Data
nameWithType: DocumentSource.Data
- uid: AnthropicClient.Models.DocumentSource.Data*
name: Data
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_Data_
commentId: Overload:AnthropicClient.Models.DocumentSource.Data
isSpec: "True"
fullName: AnthropicClient.Models.DocumentSource.Data
nameWithType: DocumentSource.Data
- uid: AnthropicClient.Models.DocumentSource.MediaType
name: MediaType
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_MediaType
commentId: P:AnthropicClient.Models.DocumentSource.MediaType
fullName: AnthropicClient.Models.DocumentSource.MediaType
nameWithType: DocumentSource.MediaType
- uid: AnthropicClient.Models.DocumentSource.MediaType*
name: MediaType
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_MediaType_
commentId: Overload:AnthropicClient.Models.DocumentSource.MediaType
isSpec: "True"
fullName: AnthropicClient.Models.DocumentSource.MediaType
nameWithType: DocumentSource.MediaType
- uid: AnthropicClient.Models.DocumentSource.Type
name: Type
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_Type
commentId: P:AnthropicClient.Models.DocumentSource.Type
fullName: AnthropicClient.Models.DocumentSource.Type
nameWithType: DocumentSource.Type
- uid: AnthropicClient.Models.DocumentSource.Type*
name: Type
href: api/AnthropicClient.Models.DocumentSource.html#AnthropicClient_Models_DocumentSource_Type_
commentId: Overload:AnthropicClient.Models.DocumentSource.Type
isSpec: "True"
fullName: AnthropicClient.Models.DocumentSource.Type
nameWithType: DocumentSource.Type
- uid: AnthropicClient.Models.EphemeralCacheControl - uid: AnthropicClient.Models.EphemeralCacheControl
name: EphemeralCacheControl name: EphemeralCacheControl
href: api/AnthropicClient.Models.EphemeralCacheControl.html href: api/AnthropicClient.Models.EphemeralCacheControl.html
+30 -4
View File
@@ -26,6 +26,13 @@ public interface IAnthropicApiClient
/// <param name="request">The message request to create.</param> /// <param name="request">The message request to create.</param>
/// <returns>An asynchronous enumerable that yields the response event by event.</returns> /// <returns>An asynchronous enumerable that yields the response event by event.</returns>
IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request); IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request);
/// <summary>
/// Counts the tokens in a message asynchronously.
/// </summary>
/// <param name="request">The count message tokens request.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the response as an <see cref="AnthropicResult{T}"/> where T is <see cref="TokenCountResponse"/>.</returns>
Task<AnthropicResult<TokenCountResponse>> CountMessageTokensAsync(CountMessageTokensRequest request);
} }
/// <inheritdoc cref="IAnthropicApiClient"/> /// <inheritdoc cref="IAnthropicApiClient"/>
@@ -34,6 +41,7 @@ public class AnthropicApiClient : IAnthropicApiClient
private const string BaseUrl = "https://api.anthropic.com/v1/"; private const string BaseUrl = "https://api.anthropic.com/v1/";
private const string ApiKeyHeader = "x-api-key"; private const string ApiKeyHeader = "x-api-key";
private const string MessagesEndpoint = "messages"; private const string MessagesEndpoint = "messages";
private const string CountTokensEndpoint = "messages/count_tokens";
private const string JsonContentType = "application/json"; private const string JsonContentType = "application/json";
private const string EventPrefix = "event:"; private const string EventPrefix = "event:";
private const string DataPrefix = "data:"; private const string DataPrefix = "data:";
@@ -71,7 +79,7 @@ public class AnthropicApiClient : IAnthropicApiClient
/// <inheritdoc /> /// <inheritdoc />
public async Task<AnthropicResult<MessageResponse>> CreateMessageAsync(MessageRequest request) public async Task<AnthropicResult<MessageResponse>> CreateMessageAsync(MessageRequest request)
{ {
var response = await SendRequestAsync(request); var response = await SendRequestAsync(MessagesEndpoint, request);
var anthropicHeaders = new AnthropicHeaders(response.Headers); var anthropicHeaders = new AnthropicHeaders(response.Headers);
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();
@@ -94,7 +102,7 @@ public class AnthropicApiClient : IAnthropicApiClient
/// <inheritdoc /> /// <inheritdoc />
public async IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request) public async IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request)
{ {
var response = await SendRequestAsync(request); var response = await SendRequestAsync(MessagesEndpoint, request);
if (response.IsSuccessStatusCode is false) if (response.IsSuccessStatusCode is false)
{ {
@@ -255,6 +263,24 @@ public class AnthropicApiClient : IAnthropicApiClient
} while (true); } while (true);
} }
/// <inheritdoc />
public async Task<AnthropicResult<TokenCountResponse>> CountMessageTokensAsync(CountMessageTokensRequest request)
{
var response = await SendRequestAsync(CountTokensEndpoint, request);
var anthropicHeaders = new AnthropicHeaders(response.Headers);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode is false)
{
var error = Deserialize<AnthropicError>(responseContent) ?? new AnthropicError();
return AnthropicResult<TokenCountResponse>.Failure(error, anthropicHeaders);
}
var msgResponse = Deserialize<TokenCountResponse>(responseContent) ?? new TokenCountResponse();
return AnthropicResult<TokenCountResponse>.Success(msgResponse, anthropicHeaders);
}
private ToolCall? GetToolCall(MessageResponse response, List<Tool> tools) private ToolCall? GetToolCall(MessageResponse response, List<Tool> tools)
{ {
var toolUse = response.Content.OfType<ToolUseContent>().FirstOrDefault(); var toolUse = response.Content.OfType<ToolUseContent>().FirstOrDefault();
@@ -274,11 +300,11 @@ public class AnthropicApiClient : IAnthropicApiClient
return new ToolCall(tool, toolUse); return new ToolCall(tool, toolUse);
} }
private async Task<HttpResponseMessage> SendRequestAsync(BaseMessageRequest request) private async Task<HttpResponseMessage> SendRequestAsync<T>(string endpoint, T request)
{ {
var requestJson = Serialize(request); var requestJson = Serialize(request);
var requestContent = new StringContent(requestJson, Encoding.UTF8, JsonContentType); var requestContent = new StringContent(requestJson, Encoding.UTF8, JsonContentType);
return await _httpClient.PostAsync(MessagesEndpoint, requestContent); return await _httpClient.PostAsync(endpoint, requestContent);
} }
private string Serialize<T>(T obj) => JsonSerializer.Serialize(obj, JsonSerializationOptions.DefaultOptions); private string Serialize<T>(T obj) => JsonSerializer.Serialize(obj, JsonSerializationOptions.DefaultOptions);
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageId>AnthropicClient</PackageId> <PackageId>AnthropicClient</PackageId>
<Version>0.2.0</Version> <Version>0.4.0</Version>
<Authors>Stevan Freeborn</Authors> <Authors>Stevan Freeborn</Authors>
<Description>Anthropic Client Library</Description> <Description>Anthropic Client Library</Description>
<PackageProjectUrl>https://anthropicclient.stevanfreeborn.com/</PackageProjectUrl> <PackageProjectUrl>https://anthropicclient.stevanfreeborn.com/</PackageProjectUrl>
+18
View File
@@ -2,6 +2,24 @@
All notable changes to this project will be documented in this file. See [versionize](https://github.com/versionize/versionize) for commit guidelines. All notable changes to this project will be documented in this file. See [versionize](https://github.com/versionize/versionize) for commit guidelines.
<a name="0.4.0"></a>
## [0.4.0](https://www.github.com/StevanFreeborn/anthropic-client/releases/tag/v0.4.0) (2025-01-03)
### Features
* add support for count tokens endpoint ([9448220](https://www.github.com/StevanFreeborn/anthropic-client/commit/944822060cd297c5720d8a1dc366f08ca0ec79ec))
### Bug Fixes
* remove model id validation ([31a7097](https://www.github.com/StevanFreeborn/anthropic-client/commit/31a7097cdc9f9f60a7b6576b8bcee7a49a00552c))
<a name="0.3.0"></a>
## [0.3.0](https://www.github.com/StevanFreeborn/anthropic-client/releases/tag/v0.3.0) (2025-01-02)
### Features
* add missing model identifiers ([6e0c065](https://www.github.com/StevanFreeborn/anthropic-client/commit/6e0c0654af6a7daebac541995e4f082bae4a052e))
<a name="0.2.0"></a> <a name="0.2.0"></a>
## [0.2.0](https://www.github.com/StevanFreeborn/anthropic-client/releases/tag/v0.2.0) (2024-11-21) ## [0.2.0](https://www.github.com/StevanFreeborn/anthropic-client/releases/tag/v0.2.0) (2024-11-21)
+48 -5
View File
@@ -6,24 +6,67 @@ namespace AnthropicClient.Models;
public static class AnthropicModels public static class AnthropicModels
{ {
/// <summary> /// <summary>
/// The Claude-3 Opus model. /// The Claude 3 Opus model.
/// </summary> /// </summary>
public const string Claude3Opus = "claude-3-opus-20240229"; public const string Claude3Opus = "claude-3-opus-20240229";
/// <summary> /// <summary>
/// The Claude-3 Sonnet model. /// The Claude 3 Opus model.
/// </summary>
public const string Claude3Opus20241022 = "claude-3-opus-20240229";
/// <summary>
/// The Claude 3 Opus model.
/// </summary>
public const string Claude3OpusLatest = "claude-3-opus-latest";
/// <summary>
/// The Claude 3 Sonnet model.
/// </summary> /// </summary>
public const string Claude3Sonnet = "claude-3-sonnet-20240229"; public const string Claude3Sonnet = "claude-3-sonnet-20240229";
/// <summary> /// <summary>
/// The Claude-3.5 Sonnet model. /// The Claude 3 Sonnet model.
/// </summary>
public const string Claude3Sonnet20240229 = "claude-3-sonnet-20240229";
/// <summary>
/// The Claude 3.5 Sonnet model.
/// </summary> /// </summary>
public const string Claude35Sonnet = "claude-3-5-sonnet-20240620"; public const string Claude35Sonnet = "claude-3-5-sonnet-20240620";
/// <summary> /// <summary>
/// The Claude-3 Haiku model. /// The Claude 3.5 Sonnet model.
/// </summary>
public const string Claude35Sonnet20240620 = "claude-3-5-sonnet-20240620";
/// <summary>
/// The Claude 3.5 Sonnet model.
/// </summary>
public const string Claude35Sonnet20241022 = "claude-3-5-sonnet-20241022";
/// <summary>
/// The Claude 3.5 Sonnet model.
/// </summary>
public const string Claude35SonnetLatest = "claude-3-5-sonnet-latest";
/// <summary>
/// The Claude 3 Haiku model.
/// </summary> /// </summary>
public const string Claude3Haiku = "claude-3-haiku-20240307"; public const string Claude3Haiku = "claude-3-haiku-20240307";
internal static bool IsValidModel(string modelId) => modelId is Claude3Opus or Claude3Sonnet or Claude35Sonnet or Claude3Haiku; /// <summary>
/// The Claude 3 Haiku model.
/// </summary>
public const string Claude3Haiku20240307 = "claude-3-haiku-20240307";
/// <summary>
/// The Claude 3.5 Haiku model.
/// </summary>
public const string Claude35Haiku20241022 = "claude-3-5-haiku-20241022";
/// <summary>
/// The Claude 3.5 Haiku model.
/// </summary>
public const string Claude35HaikuLatest = "claude-3-5-haiku-latest";
} }
@@ -126,7 +126,6 @@ public abstract class BaseMessageRequest
/// <param name="stream">A value indicating whether the message should be streamed.</param> /// <param name="stream">A value indicating whether the message should be streamed.</param>
/// <param name="stopSequences">The prompt stop sequences.</param> /// <param name="stopSequences">The prompt stop sequences.</param>
/// <param name="systemMessages">The system messages to use for the request.</param> /// <param name="systemMessages">The system messages to use for the request.</param>
/// <exception cref="ArgumentException">Thrown when the model ID is invalid.</exception>
/// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception> /// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception>
/// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception> /// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception>
/// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception> /// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception>
@@ -151,11 +150,6 @@ public abstract class BaseMessageRequest
ArgumentValidator.ThrowIfNull(model, nameof(model)); ArgumentValidator.ThrowIfNull(model, nameof(model));
ArgumentValidator.ThrowIfNull(messages, nameof(messages)); ArgumentValidator.ThrowIfNull(messages, nameof(messages));
if (AnthropicModels.IsValidModel(model) is false)
{
throw new ArgumentException($"Invalid model ID: {model}");
}
if (messages.Count < 1) if (messages.Count < 1)
{ {
throw new ArgumentException("Messages must contain at least one message"); throw new ArgumentException("Messages must contain at least one message");
@@ -0,0 +1,72 @@
using System.Text.Json.Serialization;
using AnthropicClient.Utils;
namespace AnthropicClient.Models;
/// <summary>
/// Represents a request to count the number of tokens in a message.
/// </summary>
public class CountMessageTokensRequest
{
/// <summary>
/// Gets the model ID to be used for the request.
/// </summary>
public string Model { get; init; } = string.Empty;
/// <summary>
/// Gets the messages to count the number of tokens in.
/// </summary>
public List<Message> Messages { get; init; } = [];
/// <summary>
/// Gets the tool choice mode to use for the request.
/// </summary>
[JsonPropertyName("tool_choice")]
public ToolChoice? ToolChoice { get; init; } = null;
/// <summary>
/// Gets the tools to use for the request.
/// </summary>
public List<Tool>? Tools { get; init; } = null;
/// <summary>
/// Gets the system prompt to use for the request.
/// </summary>
[JsonPropertyName("system")]
public List<TextContent>? SystemPrompt { get; init; } = null;
/// <summary>
/// Initializes a new instance of the <see cref="CountMessageTokensRequest"/> class.
/// </summary>
/// <param name="model">The model ID to use for the request.</param>
/// <param name="messages">The messages to count the number of tokens in.</param>
/// <param name="toolChoice">The tool choice mode to use for the request.</param>
/// <param name="tools">The tools to use for the request.</param>
/// <param name="systemPrompt">The system prompt to use for the request.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="model"/> or <paramref name="messages"/> is null.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="messages"/> is empty.</exception>
/// <returns>A new instance of the <see cref="CountMessageTokensRequest"/> class.</returns>
public CountMessageTokensRequest(
string model,
List<Message> messages,
ToolChoice? toolChoice = null,
List<Tool>? tools = null,
List<TextContent>? systemPrompt = null
)
{
ArgumentValidator.ThrowIfNull(model, nameof(model));
ArgumentValidator.ThrowIfNull(messages, nameof(messages));
if (messages.Count < 1)
{
throw new ArgumentException("Messages must contain at least one message");
}
Model = model;
Messages = messages;
ToolChoice = toolChoice;
Tools = tools;
SystemPrompt = systemPrompt;
}
}
@@ -25,7 +25,6 @@ public class MessageRequest : BaseMessageRequest
/// <param name="tools">The tools to use for the request.</param> /// <param name="tools">The tools to use for the request.</param>
/// <param name="stopSequences">The prompt stop sequences.</param> /// <param name="stopSequences">The prompt stop sequences.</param>
/// <param name="systemMessages">The system messages to include with the request.</param> /// <param name="systemMessages">The system messages to include with the request.</param>
/// <exception cref="ArgumentException">Thrown when the model ID is invalid.</exception>
/// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception> /// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception>
/// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception> /// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception>
/// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception> /// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception>
@@ -25,7 +25,6 @@ public class StreamMessageRequest : BaseMessageRequest
/// <param name="tools">The tools to use for the request.</param> /// <param name="tools">The tools to use for the request.</param>
/// <param name="stopSequences">The prompt stop sequences.</param> /// <param name="stopSequences">The prompt stop sequences.</param>
/// <param name="systemMessages">The system messages to include with the request.</param> /// <param name="systemMessages">The system messages to include with the request.</param>
/// <exception cref="ArgumentException">Thrown when the model ID is invalid.</exception>
/// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception> /// <exception cref="ArgumentNullException">Thrown when the model or messages is null.</exception>
/// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception> /// <exception cref="ArgumentException">Thrown when the messages contain no messages.</exception>
/// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception> /// <exception cref="ArgumentException">Thrown when the max tokens is less than one.</exception>
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
namespace AnthropicClient.Models;
/// <summary>
/// Represents a response to a token count request.
/// </summary>
public class TokenCountResponse
{
/// <summary>
/// The number of input tokens counted.
/// </summary>
[JsonPropertyName("input_tokens")]
public int InputTokens { get; init; }
}
@@ -100,10 +100,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
[Fact] [Fact]
public async Task CreateMessageAsync_WhenSystemMessagesContainCacheControl_ItShouldUseCache() public async Task CreateMessageAsync_WhenSystemMessagesContainCacheControl_ItShouldUseCache()
{ {
var httpClient = new HttpClient(); var client = CreateClient(new HttpClient());
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "prompt-caching-2024-07-31");
var client = CreateClient(httpClient);
var storyPath = GetTestFilePath("story.txt"); var storyPath = GetTestFilePath("story.txt");
var storyText = await File.ReadAllTextAsync(storyPath); var storyText = await File.ReadAllTextAsync(storyPath);
@@ -121,7 +118,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
] ]
); );
var resultOne = await client.CreateMessageAsync(request); var resultOne = await _client.CreateMessageAsync(request);
resultOne.IsSuccess.Should().BeTrue(); resultOne.IsSuccess.Should().BeTrue();
resultOne.Value.Should().BeOfType<MessageResponse>(); resultOne.Value.Should().BeOfType<MessageResponse>();
@@ -142,10 +139,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
[Fact] [Fact]
public async Task CreateMessageAsync_WhenMessagesContainCacheControl_ItShouldUseCache() public async Task CreateMessageAsync_WhenMessagesContainCacheControl_ItShouldUseCache()
{ {
var httpClient = new HttpClient(); var client = CreateClient(new HttpClient());
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "prompt-caching-2024-07-31");
var client = CreateClient(httpClient);
var storyPath = GetTestFilePath("story.txt"); var storyPath = GetTestFilePath("story.txt");
var storyText = await File.ReadAllTextAsync(storyPath); var storyText = await File.ReadAllTextAsync(storyPath);
@@ -181,10 +175,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
[Fact] [Fact]
public async Task CreateMessageAsync_WhenToolsContainCacheControl_ItShouldUseCache() public async Task CreateMessageAsync_WhenToolsContainCacheControl_ItShouldUseCache()
{ {
var httpClient = new HttpClient(); var client = CreateClient(new HttpClient());
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "prompt-caching-2024-07-31");
var client = CreateClient(httpClient);
var func = (string ticker) => ticker; var func = (string ticker) => ticker;
@@ -238,9 +229,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
] ]
); );
var httpClient = new HttpClient(); var client = CreateClient(new HttpClient());
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25");
var client = CreateClient(httpClient);
var result = await client.CreateMessageAsync(request); var result = await client.CreateMessageAsync(request);
@@ -268,9 +257,7 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
var bytes = await File.ReadAllBytesAsync(pdfPath); var bytes = await File.ReadAllBytesAsync(pdfPath);
var base64Data = Convert.ToBase64String(bytes); var base64Data = Convert.ToBase64String(bytes);
var httpClient = new HttpClient(); var client = CreateClient(new HttpClient());
httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25, prompt-caching-2024-07-31");
var client = CreateClient(httpClient);
var request = new MessageRequest( var request = new MessageRequest(
model: AnthropicModels.Claude35Sonnet, model: AnthropicModels.Claude35Sonnet,
@@ -299,4 +286,21 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf
resultTwo.Value.Content.Should().NotBeNullOrEmpty(); resultTwo.Value.Content.Should().NotBeNullOrEmpty();
resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0); resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0);
} }
[Fact]
public async Task CountMessageTokensAsync_WhenCalled_ItShouldReturnResponse()
{
var request = new CountMessageTokensRequest(
model: AnthropicModels.Claude3Haiku,
messages: [
new(MessageRole.User, [new TextContent("Hello!")])
]
);
var result = await _client.CountMessageTokensAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<TokenCountResponse>();
result.Value.InputTokens.Should().BeGreaterThan(0);
}
} }
@@ -418,4 +418,89 @@ public class AnthropicApiClientTests : IntegrationTest
textContent.As<TextContent>().Text.Should().Be("It is a PDF"); textContent.As<TextContent>().Text.Should().Be("It is a PDF");
textContent.As<TextContent>().Type.Should().Be("text"); textContent.As<TextContent>().Type.Should().Be("text");
} }
[Fact]
public async Task CountMessageTokensAsync_WhenCalled_ItShouldReturnCountTokensResponse()
{
_mockHttpMessageHandler
.WhenCountMessageTokensRequest()
.Respond(
HttpStatusCode.OK,
"application/json",
@"{
""input_tokens"": 10
}"
);
var request = new CountMessageTokensRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [new TextContent("Hello!")]),
]
);
var result = await Client.CountMessageTokensAsync(request);
result.IsSuccess.Should().BeTrue();
result.Value.Should().BeOfType<TokenCountResponse>();
result.Value.InputTokens.Should().Be(10);
}
[Fact]
public async Task CountMessageTokensAsync_WhenCalledAndErrorReturned_ItShouldHandleError()
{
_mockHttpMessageHandler
.WhenCountMessageTokensRequest()
.Respond(
HttpStatusCode.BadRequest,
"application/json",
@"{
""type"": ""error"",
""error"": {
""type"": ""invalid_request_error"",
""message"": ""messages: roles must alternate between user and assistant, but found multiple user roles in a row""
}
}"
);
var request = new CountMessageTokensRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [new TextContent("Hello!")]),
new(MessageRole.User, [new TextContent("Hello!")])
]
);
var result = await Client.CountMessageTokensAsync(request);
result.IsSuccess.Should().BeFalse();
result.Error.Should().BeOfType<AnthropicError>();
result.Error.Error.Should().BeOfType<InvalidRequestError>();
}
[Fact]
public async Task CountMessageTokensAsync_WhenCalledRequestFailsAndCanNotSerializeError_ItShouldReturnUnknownError()
{
_mockHttpMessageHandler
.WhenCountMessageTokensRequest()
.Respond(
HttpStatusCode.BadRequest,
"application/json",
@"{}"
);
var request = new CountMessageTokensRequest(
model: AnthropicModels.Claude35Sonnet,
messages: [
new(MessageRole.User, [new TextContent("Hello!")]),
new(MessageRole.User, [new TextContent("Hello!")])
]
);
var result = await Client.CountMessageTokensAsync(request);
result.IsSuccess.Should().BeFalse();
result.Error.Should().BeOfType<AnthropicError>();
result.Error.Error.Should().BeOfType<ApiError>();
}
} }
@@ -13,10 +13,18 @@ public class IntegrationTest
public static class MockHttpMessageHandlerExtensions public static class MockHttpMessageHandlerExtensions
{ {
private static MockedRequest SetupBaseRequest(this MockHttpMessageHandler mockHttpMessageHandler) private const string BaseUrl = "https://api.anthropic.com/v1";
private static readonly string MessagesEndpoint = $"{BaseUrl}/messages";
private static readonly string CountTokensEndpoint = $"{BaseUrl}/messages/count_tokens";
private static MockedRequest SetupBaseRequest(
this MockHttpMessageHandler mockHttpMessageHandler,
HttpMethod method,
string url
)
{ {
return mockHttpMessageHandler return mockHttpMessageHandler
.When(HttpMethod.Post, "https://api.anthropic.com/v1/messages") .When(method, url)
.WithHeaders(new Dictionary<string, string> .WithHeaders(new Dictionary<string, string>
{ {
{ "anthropic-version", "2023-06-01" }, { "anthropic-version", "2023-06-01" },
@@ -27,14 +35,20 @@ public static class MockHttpMessageHandlerExtensions
public static MockedRequest WhenCreateMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler) public static MockedRequest WhenCreateMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler)
{ {
return mockHttpMessageHandler return mockHttpMessageHandler
.SetupBaseRequest() .SetupBaseRequest(HttpMethod.Post, MessagesEndpoint)
.WithJsonContent<MessageRequest>(r => r.Stream == false, JsonSerializationOptions.DefaultOptions); .WithJsonContent<MessageRequest>(r => r.Stream == false, JsonSerializationOptions.DefaultOptions);
} }
public static MockedRequest WhenCreateStreamMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler) public static MockedRequest WhenCreateStreamMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler)
{ {
return mockHttpMessageHandler return mockHttpMessageHandler
.SetupBaseRequest() .SetupBaseRequest(HttpMethod.Post, MessagesEndpoint)
.WithJsonContent<StreamMessageRequest>(r => r.Stream == true, JsonSerializationOptions.DefaultOptions); .WithJsonContent<StreamMessageRequest>(r => r.Stream == true, JsonSerializationOptions.DefaultOptions);
} }
public static MockedRequest WhenCountMessageTokensRequest(this MockHttpMessageHandler mockHttpMessageHandler)
{
return mockHttpMessageHandler
.SetupBaseRequest(HttpMethod.Post, CountTokensEndpoint);
}
} }
@@ -12,6 +12,26 @@ public class AnthropicModelsTests
actual.Should().Be(expected); actual.Should().Be(expected);
} }
[Fact]
public void Claude3Opus20241022_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-opus-20240229";
var actual = AnthropicModels.Claude3Opus20241022;
actual.Should().Be(expected);
}
[Fact]
public void Claude3OpusLatest_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-opus-latest";
var actual = AnthropicModels.Claude3OpusLatest;
actual.Should().Be(expected);
}
[Fact] [Fact]
public void Claude3Sonnet_WhenCalled_ItShouldReturnExpectedValue() public void Claude3Sonnet_WhenCalled_ItShouldReturnExpectedValue()
{ {
@@ -22,6 +42,16 @@ public class AnthropicModelsTests
actual.Should().Be(expected); actual.Should().Be(expected);
} }
[Fact]
public void Claude3Sonnet20240229_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-sonnet-20240229";
var actual = AnthropicModels.Claude3Sonnet20240229;
actual.Should().Be(expected);
}
[Fact] [Fact]
public void Claude35Sonnet_WhenCalled_ItShouldReturnExpectedValue() public void Claude35Sonnet_WhenCalled_ItShouldReturnExpectedValue()
{ {
@@ -32,6 +62,36 @@ public class AnthropicModelsTests
actual.Should().Be(expected); actual.Should().Be(expected);
} }
[Fact]
public void Claude35Sonnet20240620_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-5-sonnet-20240620";
var actual = AnthropicModels.Claude35Sonnet20240620;
actual.Should().Be(expected);
}
[Fact]
public void Claude35Sonnet20241022_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-5-sonnet-20241022";
var actual = AnthropicModels.Claude35Sonnet20241022;
actual.Should().Be(expected);
}
[Fact]
public void Claude35SonnetLatest_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-5-sonnet-latest";
var actual = AnthropicModels.Claude35SonnetLatest;
actual.Should().Be(expected);
}
[Fact] [Fact]
public void Claude3Haiku_WhenCalled_ItShouldReturnExpectedValue() public void Claude3Haiku_WhenCalled_ItShouldReturnExpectedValue()
{ {
@@ -43,24 +103,31 @@ public class AnthropicModelsTests
} }
[Fact] [Fact]
public void Claude35Sonnet_WhenCalled_ItShouldExpectedValue() public void Claude3Haiku20240307_WhenCalled_ItShouldReturnExpectedValue()
{ {
var expected = "claude-3-5-sonnet-20240620"; var expected = "claude-3-haiku-20240307";
var actual = AnthropicModels.Claude35Sonnet; var actual = AnthropicModels.Claude3Haiku20240307;
actual.Should().Be(expected); actual.Should().Be(expected);
} }
[Theory] [Fact]
[InlineData("claude-3-opus-20240229", true)] public void Claude35Haiku_WhenCalled_ItShouldReturnExpectedValue()
[InlineData("claude-3-sonnet-20240229", true)]
[InlineData("claude-3-5-sonnet-20240620", true)]
[InlineData("claude-3-haiku-20240307", true)]
[InlineData("invalid", false)]
public void IsValidModel_WhenCalled_ItShouldReturnExpectedValue(string modelId, bool expected)
{ {
var actual = AnthropicModels.IsValidModel(modelId); var expected = "claude-3-5-haiku-20241022";
var actual = AnthropicModels.Claude35Haiku20241022;
actual.Should().Be(expected);
}
[Fact]
public void Claude35HaikuLatest_WhenCalled_ItShouldReturnExpectedValue()
{
var expected = "claude-3-5-haiku-latest";
var actual = AnthropicModels.Claude35HaikuLatest;
actual.Should().Be(expected); actual.Should().Be(expected);
} }
@@ -0,0 +1,117 @@
namespace AnthropicClient.Tests.Unit.Models;
public class CountMessageTokensRequestTests : SerializationTest
{
private readonly string _testJson = @"{
""model"": ""claude-3-sonnet-20240229"",
""system"": [{
""type"": ""text"",
""text"": ""test-system""
}],
""messages"": [
{ ""role"": ""user"", ""content"": [{ ""text"": ""Hello!"", ""type"": ""text"" }] }
],
""tool_choice"": { ""type"":""auto"" },
""tools"": []
}";
[Fact]
public void Constructor_WhenCalled_ItShouldInitializeProperties()
{
var model = AnthropicModels.Claude3Sonnet;
var messages = new List<Message> { new() };
var systemPrompt = new List<TextContent>() { new("test-system") };
var toolChoice = new AutoToolChoice();
var tools = new List<Tool>();
var request = new CountMessageTokensRequest(
model: model,
messages: messages,
toolChoice: toolChoice,
tools: tools,
systemPrompt: systemPrompt
);
request.Model.Should().Be(model);
request.Messages.Should().BeSameAs(messages);
request.ToolChoice.Should().Be(toolChoice);
request.Tools.Should().BeSameAs(tools);
request.SystemPrompt.Should().BeSameAs(systemPrompt);
}
[Fact]
public void Constructor_WhenCalledAndModelIsNull_ItShouldThrowArgumentNullException()
{
var action = () => new CountMessageTokensRequest(
model: null!,
messages: [new()]
);
action.Should().Throw<ArgumentNullException>();
}
[Fact]
public void Constructor_WhenCalledAndMessagesIsNull_ItShouldThrowArgumentNullException()
{
var action = () => new CountMessageTokensRequest(
model: AnthropicModels.Claude3Sonnet,
messages: null!
);
action.Should().Throw<ArgumentNullException>();
}
[Fact]
public void Constructor_WhenCalledAndMessagesIsEmpty_ItShouldThrowArgumentException()
{
var action = () => new CountMessageTokensRequest(
model: AnthropicModels.Claude3Sonnet,
messages: []
);
action.Should().Throw<ArgumentException>();
}
[Fact]
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
{
var messages = new List<Message>()
{
new()
{
Role = MessageRole.User,
Content = [new TextContent("Hello!")]
}
};
var model = AnthropicModels.Claude3Sonnet;
var systemPrompt = new List<TextContent>() { new("test-system") };
var toolChoice = new AutoToolChoice();
var tools = new List<Tool>();
var request = new CountMessageTokensRequest(
model: model,
messages: messages,
toolChoice: toolChoice,
tools: tools,
systemPrompt: systemPrompt
);
var actual = Serialize(request);
JsonAssert.Equal(_testJson, actual);
}
[Fact]
public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedShape()
{
var request = Deserialize<CountMessageTokensRequest>(_testJson);
request!.Model.Should().Be(AnthropicModels.Claude3Sonnet);
request.SystemPrompt.Should().BeEquivalentTo(new List<TextContent> { new("test-system") });
request.Messages.Should().HaveCount(1);
request.ToolChoice.Should().BeOfType<AutoToolChoice>();
request.ToolChoice!.Type.Should().Be("auto");
request.Tools.Should().HaveCount(0);
}
}
@@ -232,14 +232,14 @@ public class MessageRequestTests : SerializationTest
} }
[Fact] [Fact]
public void Constructor_WhenCalledAndModelIsInvalid_ItShouldThrowArgumentException() public void Constructor_WhenCalledAndModelIsInvalid_ItShouldNotThrowException()
{ {
var action = () => new MessageRequest( var action = () => new MessageRequest(
model: "invalid-model", model: "invalid-model",
messages: [new()] messages: [new()]
); );
action.Should().Throw<ArgumentException>(); action.Should().NotThrow();
} }
[Fact] [Fact]
@@ -85,14 +85,14 @@ public class StreamMessageRequestTests : SerializationTest
} }
[Fact] [Fact]
public void Constructor_WhenCalledAndModelIsInvalid_ItShouldThrowArgumentException() public void Constructor_WhenCalledAndModelIsInvalid_ItShouldNotThrowException()
{ {
var action = () => new StreamMessageRequest( var action = () => new StreamMessageRequest(
model: "invalid-model", model: "invalid-model",
messages: [new()] messages: [new()]
); );
action.Should().Throw<ArgumentException>(); action.Should().NotThrow();
} }
[Fact] [Fact]
@@ -0,0 +1,46 @@
namespace AnthropicClient.Tests.Unit.Models;
public class TokenCountResponseTests : SerializationTest
{
[Fact]
public void Constructor_WhenCalled_ShouldInitializeProperties()
{
var expectedTokenCount = 1;
var response = new TokenCountResponse
{
InputTokens = expectedTokenCount
};
response.InputTokens.Should().Be(expectedTokenCount);
}
[Fact]
public void JsonSerialization_WhenCalled_ItShouldSerializeCorrectly()
{
var expectedJson = @"{
""input_tokens"": 1
}";
var response = new TokenCountResponse
{
InputTokens = 1
};
var actual = Serialize(response);
JsonAssert.Equal(expectedJson, actual);
}
[Fact]
public void JsonDeserialization_WhenCalled_ItShouldDeserializeCorrectly()
{
var json = @"{
""input_tokens"": 1
}";
var response = Deserialize<TokenCountResponse>(json);
response!.InputTokens.Should().Be(1);
}
}