Skip to content

Commit fbc7ccb

Browse files
speedstorm1copybara-github
authored andcommitted
feat: Add Caches module to Dotnet SDK (create, get, delete, update, list)
PiperOrigin-RevId: 832557429
1 parent 39b7e6c commit fbc7ccb

37 files changed

+4744
-3
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using System.Threading.Tasks;
21+
22+
using Google.GenAI;
23+
using Google.GenAI.Types;
24+
25+
using Microsoft.VisualStudio.TestTools.UnitTesting;
26+
27+
using TestServerSdk;
28+
29+
[TestClass]
30+
public class CreateCacheTest
31+
{
32+
private static TestServerProcess? _server;
33+
private Client vertexClient;
34+
private Client geminiClient;
35+
private string modelName;
36+
public TestContext TestContext { get; set; }
37+
38+
[ClassInitialize]
39+
public static void ClassInit(TestContext _)
40+
{
41+
_server = TestServer.StartTestServer();
42+
}
43+
44+
[ClassCleanup]
45+
public static void ClassCleanup()
46+
{
47+
TestServer.StopTestServer(_server);
48+
}
49+
50+
[TestInitialize]
51+
public void TestInit()
52+
{
53+
// Test server specific setup.
54+
if (_server == null)
55+
{
56+
throw new InvalidOperationException("Test server is not initialized.");
57+
}
58+
var geminiClientHttpOptions = new HttpOptions {
59+
Headers = new Dictionary<string, string> { { "Test-Name",
60+
$"{GetType().Name}.{TestContext.TestName}" } },
61+
BaseUrl = "http://localhost:1453"
62+
};
63+
var vertexClientHttpOptions = new HttpOptions {
64+
Headers = new Dictionary<string, string> { { "Test-Name",
65+
$"{GetType().Name}.{TestContext.TestName}" } },
66+
BaseUrl = "http://localhost:1454"
67+
};
68+
69+
// Common setup for both clients.
70+
string project = System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT");
71+
string location =
72+
System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_LOCATION") ?? "us-central1";
73+
string apiKey = System.Environment.GetEnvironmentVariable("GOOGLE_API_KEY");
74+
vertexClient = new Client(project: project, location: location, vertexAI: true,
75+
credential: TestServer.GetCredentialForTestMode(),
76+
httpOptions: vertexClientHttpOptions);
77+
geminiClient =
78+
new Client(apiKey: apiKey, vertexAI: false, httpOptions: geminiClientHttpOptions);
79+
80+
// Specific setup for this test class
81+
modelName = "gemini-2.5-flash";
82+
}
83+
84+
[TestMethod]
85+
public async Task CreateCacheGcsUriVertexTest()
86+
{
87+
// TODO(b/462527852): resolve test failure (temporarily skipped) in replay mode
88+
if (TestServer.IsReplayMode)
89+
{
90+
Assert.Inconclusive("Vertex cache tests run in record mode only.");
91+
}
92+
var config = new CreateCachedContentConfig
93+
{
94+
Contents = new List<Content>
95+
{
96+
new Content
97+
{
98+
Role = "user",
99+
Parts = new List<Part>
100+
{
101+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf", MimeType = "application/pdf" } },
102+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", MimeType = "application/pdf" } }
103+
}
104+
}
105+
},
106+
SystemInstruction = new Content { Parts = new List<Part> { new Part { Text = "What is the sum of the two pdfs?" } } },
107+
DisplayName = "test cache",
108+
Ttl = "86400s"
109+
};
110+
111+
var vertexResponse = await vertexClient.Caches.CreateAsync(model: modelName, config: config);
112+
113+
Assert.IsNotNull(vertexResponse);
114+
Assert.IsNotNull(vertexResponse.Name);
115+
}
116+
117+
[TestMethod]
118+
public async Task CreateCacheGcsUriGeminiTest()
119+
{
120+
var config = new CreateCachedContentConfig
121+
{
122+
Contents = new List<Content>
123+
{
124+
new Content
125+
{
126+
Role = "user",
127+
Parts = new List<Part>
128+
{
129+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf", MimeType = "application/pdf" } },
130+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", MimeType = "application/pdf" } }
131+
}
132+
}
133+
},
134+
SystemInstruction = new Content { Parts = new List<Part> { new Part { Text = "What is the sum of the two pdfs?" } } },
135+
DisplayName = "test cache",
136+
Ttl = "86400s"
137+
};
138+
139+
await Assert.ThrowsExceptionAsync<ClientError>(async () => {
140+
await geminiClient.Caches.CreateAsync(model: modelName, config: config);
141+
});
142+
}
143+
144+
[TestMethod]
145+
public async Task CreateCacheGoogleAiFileGeminiTest()
146+
{
147+
var part = new Part { FileData = new FileData { MimeType = "application/pdf", FileUri = "https://generativelanguage.googleapis.com/v1beta/files/REDACTEDywp4" } };
148+
var config = new CreateCachedContentConfig
149+
{
150+
Contents = new List<Content>
151+
{
152+
new Content
153+
{
154+
Role = "user",
155+
Parts = Enumerable.Repeat(part, 5).ToList()
156+
}
157+
},
158+
SystemInstruction = new Content { Parts = new List<Part> { new Part { Text = "What is in the pdf?" } } },
159+
DisplayName = "test cache",
160+
Ttl = "86400s"
161+
};
162+
163+
var geminiResponse = await geminiClient.Caches.CreateAsync(model: modelName, config: config);
164+
165+
Assert.IsNotNull(geminiResponse);
166+
Assert.IsNotNull(geminiResponse.Name);
167+
}
168+
169+
[TestMethod]
170+
public async Task CreateCacheGoogleAiFileVertexTest()
171+
{
172+
var part = new Part { FileData = new FileData { MimeType = "application/pdf", FileUri = "https://generativelanguage.googleapis.com/v1beta/files/REDACTEDywp4" } };
173+
var config = new CreateCachedContentConfig
174+
{
175+
Contents = new List<Content>
176+
{
177+
new Content
178+
{
179+
Role = "user",
180+
Parts = Enumerable.Repeat(part, 5).ToList()
181+
}
182+
},
183+
SystemInstruction = new Content { Parts = new List<Part> { new Part { Text = "What is in the pdf?" } } },
184+
DisplayName = "test cache",
185+
Ttl = "86400s"
186+
};
187+
188+
await Assert.ThrowsExceptionAsync<ServerError>(async () => {
189+
await vertexClient.Caches.CreateAsync(model: modelName, config: config);
190+
});
191+
}
192+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using System.Threading.Tasks;
21+
22+
using Google.GenAI;
23+
using Google.GenAI.Types;
24+
25+
using Microsoft.VisualStudio.TestTools.UnitTesting;
26+
27+
using TestServerSdk;
28+
29+
[TestClass]
30+
public class DeleteCacheTest
31+
{
32+
private static TestServerProcess? _server;
33+
private Client vertexClient;
34+
private Client geminiClient;
35+
private string modelName;
36+
public TestContext TestContext { get; set; }
37+
38+
[ClassInitialize]
39+
public static void ClassInit(TestContext _)
40+
{
41+
_server = TestServer.StartTestServer();
42+
}
43+
44+
[ClassCleanup]
45+
public static void ClassCleanup()
46+
{
47+
TestServer.StopTestServer(_server);
48+
}
49+
50+
[TestInitialize]
51+
public void TestInit()
52+
{
53+
// Test server specific setup.
54+
if (_server == null)
55+
{
56+
throw new InvalidOperationException("Test server is not initialized.");
57+
}
58+
var geminiClientHttpOptions = new HttpOptions {
59+
Headers = new Dictionary<string, string> { { "Test-Name",
60+
$"{GetType().Name}.{TestContext.TestName}" } },
61+
BaseUrl = "http://localhost:1453"
62+
};
63+
var vertexClientHttpOptions = new HttpOptions {
64+
Headers = new Dictionary<string, string> { { "Test-Name",
65+
$"{GetType().Name}.{TestContext.TestName}" } },
66+
BaseUrl = "http://localhost:1454"
67+
};
68+
69+
// Common setup for both clients.
70+
string project = System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT");
71+
string location =
72+
System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_LOCATION") ?? "us-central1";
73+
string apiKey = System.Environment.GetEnvironmentVariable("GOOGLE_API_KEY");
74+
vertexClient = new Client(project: project, location: location, vertexAI: true,
75+
credential: TestServer.GetCredentialForTestMode(),
76+
httpOptions: vertexClientHttpOptions);
77+
geminiClient =
78+
new Client(apiKey: apiKey, vertexAI: false, httpOptions: geminiClientHttpOptions);
79+
80+
// Specific setup for this test class
81+
modelName = "gemini-2.5-flash";
82+
}
83+
84+
[TestMethod]
85+
public async Task DeleteCacheVertexTest()
86+
{
87+
// TODO(b/462527852): resolve test failure (temporarily skipped) in replay mode
88+
if (TestServer.IsReplayMode)
89+
{
90+
Assert.Inconclusive("Vertex cache tests run in record mode only.");
91+
}
92+
var config = new CreateCachedContentConfig
93+
{
94+
Contents = new List<Content>
95+
{
96+
new Content
97+
{
98+
Role = "user",
99+
Parts = new List<Part>
100+
{
101+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf", MimeType = "application/pdf" } },
102+
new Part { FileData = new FileData { FileUri = "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", MimeType = "application/pdf" } }
103+
}
104+
}
105+
},
106+
DisplayName = "test-delete-cache-vertex",
107+
Ttl = "600s"
108+
};
109+
110+
var created = await vertexClient.Caches.CreateAsync(modelName, config);
111+
Assert.IsNotNull(created);
112+
113+
var deleted = await vertexClient.Caches.DeleteAsync(created.Name, config: null);
114+
}
115+
116+
[TestMethod]
117+
public async Task DeleteCacheGeminiTest()
118+
{
119+
var part = new Part { FileData = new FileData { MimeType = "image/png", FileUri = "https://generativelanguage.googleapis.com/v1beta/files/pof5sdk4965m" } };
120+
var config = new CreateCachedContentConfig
121+
{
122+
Contents = new List<Content>
123+
{
124+
new Content
125+
{
126+
Role = "user",
127+
Parts = Enumerable.Repeat(part, 5).ToList()
128+
}
129+
},
130+
DisplayName = "test-delete-cache-gemini",
131+
Ttl = "600s"
132+
};
133+
var created = await geminiClient.Caches.CreateAsync(modelName, config);
134+
Assert.IsNotNull(created);
135+
136+
var deleted = await geminiClient.Caches.DeleteAsync(created.Name, config: null);
137+
}
138+
}

0 commit comments

Comments
 (0)