Skip to content

Commit 16737d3

Browse files
authoredFeb 28, 2025··
Fix Issue #218 by ensuring system instructions are always formatted, not just when TTL is specified on Cache creation (#358)
* Fix System Instructions on Cache creation in the abscence of TTL * Add Changeset * Formatting fix
1 parent e175360 commit 16737d3

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed
 

‎.changeset/afraid-buckets-decide.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@google/generative-ai": patch
3+
---
4+
5+
Fixes issue #218 by ensuring system instructions are formatted always, not just when TTL is specified

‎src/server/cache-manager.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use(chaiAsPromised);
2828

2929
const FAKE_CONTENTS = [{ role: "user", parts: [{ text: "some text" }] }];
3030
const FAKE_CACHE_NAME = "cachedContents/hash1234";
31+
const SYSTEM_INSTRUCTION = "You are a fish";
3132
const fakeResponseJson: () => Promise<{}> = () =>
3233
Promise.resolve({ name: FAKE_CACHE_NAME });
3334
const model = "models/gemini-1.5-pro-001";
@@ -124,6 +125,12 @@ describe("GoogleAICacheManager", () => {
124125
expect(makeRequestStub.args[0][0].toString()).to.match(
125126
/^http:\/\/mysite\.com/,
126127
);
128+
expect(typeof makeRequestStub.args[0][2]).to.eq("string");
129+
const body = JSON.parse(makeRequestStub.args[0][2] as string);
130+
expect(body.contents[0].parts[0].text).to.eq(
131+
FAKE_CONTENTS[0].parts[0].text,
132+
);
133+
expect(body.contents[0].role).to.eq(FAKE_CONTENTS[0].role);
127134
});
128135
it("passes update request info", async () => {
129136
const makeRequestStub = stub(request, "makeServerRequest").resolves({
@@ -294,4 +301,31 @@ describe("GoogleAICacheManager", () => {
294301
const cacheManager = new GoogleAICacheManager("apiKey");
295302
await expect(cacheManager.delete("")).to.be.rejectedWith("Invalid name");
296303
});
304+
it("passes system instructions", async () => {
305+
const makeRequestStub = stub(request, "makeServerRequest").resolves({
306+
ok: true,
307+
json: fakeResponseJson,
308+
} as Response);
309+
const cacheManager = new GoogleAICacheManager("apiKey", {
310+
apiVersion: "v3000",
311+
baseUrl: "http://mysite.com",
312+
});
313+
await cacheManager.create({
314+
model,
315+
contents: FAKE_CONTENTS,
316+
systemInstruction: SYSTEM_INSTRUCTION,
317+
});
318+
expect(makeRequestStub.args[0][0].task).to.equal(RpcTask.CREATE);
319+
expect(makeRequestStub.args[0][1]).to.be.instanceOf(Headers);
320+
expect(makeRequestStub.args[0][0].toString()).to.include(
321+
"v3000/cachedContents",
322+
);
323+
expect(makeRequestStub.args[0][0].toString()).to.match(
324+
/^http:\/\/mysite\.com/,
325+
);
326+
expect(typeof makeRequestStub.args[0][2]).to.eq("string");
327+
const body = JSON.parse(makeRequestStub.args[0][2] as string);
328+
expect(body.systemInstruction.parts[0].text).to.eq(SYSTEM_INSTRUCTION);
329+
expect(body.systemInstruction.role).to.eq("system");
330+
});
297331
});

‎src/server/cache-manager.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ export class GoogleAICacheManager {
5555
" a content cache. You must choose one.",
5656
);
5757
}
58-
if (createOptions.systemInstruction) {
59-
newCachedContent.systemInstruction = formatSystemInstruction(
60-
createOptions.systemInstruction,
61-
);
62-
}
6358
newCachedContent.ttl = createOptions.ttlSeconds.toString() + "s";
6459
delete (newCachedContent as CachedContentCreateParams).ttlSeconds;
6560
}
61+
if (createOptions.systemInstruction) {
62+
newCachedContent.systemInstruction = formatSystemInstruction(
63+
createOptions.systemInstruction,
64+
);
65+
}
6666
if (!newCachedContent.model) {
6767
throw new GoogleGenerativeAIRequestInputError(
6868
"Cached content must contain a `model` field.",

0 commit comments

Comments
 (0)
Please sign in to comment.