Skip to content

Commit 51bb210

Browse files
committed
Add vertex provider
Add vertex example Add explicit body check for vertex Readd explicit check for model value in bedrock client lint reintroduce null forgiving operator as required by build
1 parent 46db22f commit 51bb210

13 files changed

+399
-2
lines changed

Anthropic.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2424
SECURITY.md = SECURITY.md
2525
EndProjectSection
2626
EndProject
27+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Anthropic.Vertex", "src\Anthropic.Vertex\Anthropic.Vertex.csproj", "{A316C280-3880-4674-9B0C-2F6FE77B8B49}"
28+
EndProject
2729
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{B36A84DF-456D-A817-6EDD-3EC3E7F6E11F}"
2830
EndProject
2931
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StreamingAggregationBetaExample", "StreamingAggregationBetaExample", "{6D5DEC39-3673-615E-54FA-C74C69400686}"
@@ -88,6 +90,18 @@ Global
8890
{72FC9906-07F4-4911-8D6B-F9814974BB37}.Release|x64.Build.0 = Release|Any CPU
8991
{72FC9906-07F4-4911-8D6B-F9814974BB37}.Release|x86.ActiveCfg = Release|Any CPU
9092
{72FC9906-07F4-4911-8D6B-F9814974BB37}.Release|x86.Build.0 = Release|Any CPU
93+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
94+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|Any CPU.Build.0 = Debug|Any CPU
95+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|x64.ActiveCfg = Debug|Any CPU
96+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|x64.Build.0 = Debug|Any CPU
97+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|x86.ActiveCfg = Debug|Any CPU
98+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Debug|x86.Build.0 = Debug|Any CPU
99+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
100+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|Any CPU.Build.0 = Release|Any CPU
101+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|x64.ActiveCfg = Release|Any CPU
102+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|x64.Build.0 = Release|Any CPU
103+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|x86.ActiveCfg = Release|Any CPU
104+
{A316C280-3880-4674-9B0C-2F6FE77B8B49}.Release|x86.Build.0 = Release|Any CPU
91105
{0E525CB1-B565-4ABE-B477-48C53F9BB258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
92106
{0E525CB1-B565-4ABE-B477-48C53F9BB258}.Debug|Any CPU.Build.0 = Debug|Any CPU
93107
{0E525CB1-B565-4ABE-B477-48C53F9BB258}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -109,6 +123,7 @@ Global
109123
{0732C8A6-7313-4C33-AE2E-FFAA82EFB481} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
110124
{DD0E539D-6D5F-45EB-A807-01BE0A443604} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
111125
{72FC9906-07F4-4911-8D6B-F9814974BB37} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
126+
{A316C280-3880-4674-9B0C-2F6FE77B8B49} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
112127
{6D5DEC39-3673-615E-54FA-C74C69400686} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F}
113128
{0E525CB1-B565-4ABE-B477-48C53F9BB258} = {6D5DEC39-3673-615E-54FA-C74C69400686}
114129
EndGlobalSection

examples/Anthropic.Examples.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagesExample.Foundry", "
1818
EndProject
1919
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagesExample.Bedrock", "MessagesExample.Bedrock\MessagesExample.Bedrock.csproj", "{7AD57F3D-FF5A-472B-ABEF-FC381D5CCC0C}"
2020
EndProject
21+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagesExample.Vertex", "MessagesExample.Vertex\MessagesExample.Vertex.csproj", "{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}"
22+
EndProject
2123
Global
2224
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2325
Debug|Any CPU = Debug|Any CPU
@@ -124,6 +126,18 @@ Global
124126
{7AD57F3D-FF5A-472B-ABEF-FC381D5CCC0C}.Release|x64.Build.0 = Release|Any CPU
125127
{7AD57F3D-FF5A-472B-ABEF-FC381D5CCC0C}.Release|x86.ActiveCfg = Release|Any CPU
126128
{7AD57F3D-FF5A-472B-ABEF-FC381D5CCC0C}.Release|x86.Build.0 = Release|Any CPU
129+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
130+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|Any CPU.Build.0 = Debug|Any CPU
131+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|x64.ActiveCfg = Debug|Any CPU
132+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|x64.Build.0 = Debug|Any CPU
133+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|x86.ActiveCfg = Debug|Any CPU
134+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Debug|x86.Build.0 = Debug|Any CPU
135+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|Any CPU.ActiveCfg = Release|Any CPU
136+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|Any CPU.Build.0 = Release|Any CPU
137+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|x64.ActiveCfg = Release|Any CPU
138+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|x64.Build.0 = Release|Any CPU
139+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|x86.ActiveCfg = Release|Any CPU
140+
{E2B0C44D-3B9C-4ACD-BA53-2E27F4111004}.Release|x86.Build.0 = Release|Any CPU
127141
EndGlobalSection
128142
GlobalSection(SolutionProperties) = preSolution
129143
HideSolutionNode = FALSE
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\..\src\Anthropic\Anthropic.csproj" />
12+
<ProjectReference Include="..\..\src\Anthropic.Vertex\Anthropic.Vertex.csproj" />
13+
</ItemGroup>
14+
</Project>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Anthropic.Models.Messages;
2+
using Anthropic.Vertex;
3+
using Google.Apis.Auth.OAuth2;
4+
5+
// The google vertex client needs a Project ID, use the ID from the google cloud dashboard.
6+
// The region parameter is optional.
7+
8+
// By default the Vertex Credential provider tries to load system wide credentials generated via the "gcloud" tool.
9+
// For application wide credentials we recommend using service accounts instead and providing your own GoogleCredentials. Example:
10+
/*
11+
var client = new AnthropicVertexClient(new AnthropicVertexCredentials(null, "YourProjectId", GoogleCredential.FromJson(
12+
"""
13+
{
14+
ServiceAccount JSON
15+
}
16+
""").CreateScoped("https://www.googleapis.com/auth/cloud-platform")));
17+
*/
18+
19+
var client = new AnthropicVertexClient(new AnthropicVertexCredentials(null, "YourProjectId"));
20+
21+
MessageCreateParams parameters = new()
22+
{
23+
MaxTokens = 2048,
24+
Messages =
25+
[
26+
new() { Content = "Tell me a story about building the best SDK!", Role = Role.User },
27+
],
28+
Model = "claude-sonnet-4-5",
29+
};
30+
31+
var response = await client.Messages.Create(parameters);
32+
33+
var message = string.Join(
34+
"",
35+
response
36+
.Content.Where(message => message.Value is TextBlock)
37+
.Select(message => message.Value as TextBlock)
38+
.Select((textBlock) => textBlock.Text)
39+
);
40+
41+
Console.WriteLine(message);

src/Anthropic.Bedrock/AnthropicBedrockClient.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ [.. betaVersions.Select(v => JsonValue.Create(v))]
124124

125125
bodyContent["anthropic_version"] = JsonValue.Create(AnthropicVersion);
126126

127-
var modelValue = bodyContent["model"]!;
127+
var modelValue =
128+
bodyContent["model"]
129+
?? throw new AnthropicInvalidDataException(
130+
"Expected to find property model in request json but found none."
131+
);
128132
bodyContent.Root.AsObject().Remove("model");
129133
var parsedStreamValue = ((bool?)bodyContent["stream"]?.AsValue()) ?? false;
130134
bodyContent.Root.AsObject().Remove("stream");

src/Anthropic.Tests/Anthropic.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<ProjectReference Include="..\Anthropic\Anthropic.csproj" />
2424
<ProjectReference Include="..\Anthropic.Foundry\Anthropic.Foundry.csproj" />
2525
<ProjectReference Include="..\Anthropic.Bedrock\Anthropic.Bedrock.csproj" />
26-
26+
<ProjectReference Include="..\Anthropic.Vertex\Anthropic.Vertex.csproj" />
2727
<Using Include="Xunit" />
2828
</ItemGroup>
2929
</Project>

src/Anthropic.Tests/AnthropicTestClients.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using Anthropic.Bedrock;
77
using Anthropic.Foundry;
8+
using Anthropic.Vertex;
89
using Xunit.Sdk;
910
using Xunit.v3;
1011

@@ -91,6 +92,25 @@ .. testData
9192
)
9293
);
9394
}
95+
if (TestSupportTypes.HasFlag(TestSupportTypes.Vertex))
96+
{
97+
rows.Add(
98+
new TheoryDataRow(
99+
[
100+
new AnthropicVertexClient(
101+
new AnthropicVertexCredentials(Resource, "VertexProject")
102+
)
103+
{
104+
BaseUrl = DataServiceUrl,
105+
},
106+
.. testData
107+
.Where(e => e.TestSupport.HasFlag(TestSupportTypes.Vertex))
108+
.SelectMany(f => f.TestData)
109+
.ToArray(),
110+
]
111+
)
112+
);
113+
}
94114

95115
return new ValueTask<IReadOnlyCollection<ITheoryDataRow>>(rows);
96116
}
@@ -116,4 +136,5 @@ public enum TestSupportTypes
116136
Anthropic = 1 << 1,
117137
Foundry = 1 << 2,
118138
Bedrock = 1 << 3,
139+
Vertex = 1 << 4,
119140
}

src/Anthropic.Tests/Services/MessageServiceTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class MessageServiceTest
4747
[AnthropicTestData(TestSupportTypes.Anthropic, "Claude3_7SonnetLatest")]
4848
[AnthropicTestData(TestSupportTypes.Foundry, "claude-sonnet-4-5")]
4949
[AnthropicTestData(TestSupportTypes.Bedrock, "global.anthropic.claude-haiku-4-5-20251001-v1:0")]
50+
[AnthropicTestData(TestSupportTypes.Vertex, "claude-3-7-sonnet@20250219")]
5051
public async Task Create_Works(IAnthropicClient client, string modelName)
5152
{
5253
var message = await client.Messages.Create(
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
7+
<PackageId>Anthropic.Vertex</PackageId>
8+
<VersionPrefix>0.1.0</VersionPrefix>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\Anthropic\Anthropic.csproj" />
13+
14+
<None Include="..\logo.png" Pack="true" PackagePath="\" />
15+
<Compile Include="..\Anthropic\Shims.cs" />
16+
</ItemGroup>
17+
18+
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
19+
<PackageReference Include="Microsoft.Bcl.Memory" Version="10.0.0" />
20+
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
21+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<PackageReference Include="Google.Apis.Oauth2.v2" Version="1.68.0.1869" />
26+
</ItemGroup>
27+
</Project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Anthropic.Core;
2+
3+
namespace Anthropic.Vertex;
4+
5+
/// <summary>
6+
/// Provides methods for invoking the vertex hosted Anthropic api.
7+
/// </summary>
8+
public class AnthropicVertexClient : AnthropicClient
9+
{
10+
private readonly IAnthropicVertexCredentials _vertexCredentials;
11+
12+
private readonly Lazy<IAnthropicClientWithRawResponse> _withRawResponse;
13+
14+
/// <summary>
15+
/// Creates a new Instance of the <see cref="AnthropicBedrockClient"/>.
16+
/// </summary>
17+
/// <param name="vertexCredentials">The credential Provider used to authenticate with the AWS Bedrock service.</param>
18+
public AnthropicVertexClient(IAnthropicVertexCredentials vertexCredentials)
19+
: base()
20+
{
21+
_vertexCredentials = vertexCredentials;
22+
BaseUrl =
23+
$"https://{(_vertexCredentials.Region is "global" or null ? "" : _vertexCredentials.Region + "-")}aiplatform.googleapis.com";
24+
_withRawResponse = new(() =>
25+
new AnthropicVertexClientWithRawResponse(_vertexCredentials, _options)
26+
);
27+
}
28+
29+
private AnthropicVertexClient(
30+
IAnthropicVertexCredentials vertexCredentials,
31+
ClientOptions clientOptions
32+
)
33+
: base(clientOptions)
34+
{
35+
_vertexCredentials = vertexCredentials;
36+
BaseUrl =
37+
$"https://{(_vertexCredentials.Region is "global" or null ? "" : _vertexCredentials.Region + "-")}aiplatform.googleapis.com";
38+
_withRawResponse = new(() =>
39+
new AnthropicVertexClientWithRawResponse(_vertexCredentials, _options)
40+
);
41+
}
42+
43+
/// <inheritdoc />
44+
public override IAnthropicClient WithOptions(Func<ClientOptions, ClientOptions> modifier)
45+
{
46+
return new AnthropicVertexClient(_vertexCredentials, modifier(this._options));
47+
}
48+
49+
/// <inheritdoc/>
50+
public override IAnthropicClientWithRawResponse WithRawResponse => _withRawResponse.Value;
51+
}

0 commit comments

Comments
 (0)