Skip to content

Commit

Permalink
fix: fixed gemini model handling of nullish optional fields in respon…
Browse files Browse the repository at this point in the history
…se schema (#1411)
  • Loading branch information
pavelgj authored Nov 26, 2024
1 parent f4261f9 commit 9a8a1d4
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
8 changes: 7 additions & 1 deletion js/plugins/googleai/src/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ export function fromGeminiCandidate(
};
}

function cleanSchema(schema: JSONSchema): JSONSchema {
export function cleanSchema(schema: JSONSchema): JSONSchema {
const out = structuredClone(schema);
for (const key in out) {
if (key === '$schema' || key === 'additionalProperties') {
Expand All @@ -459,6 +459,12 @@ function cleanSchema(schema: JSONSchema): JSONSchema {
if (typeof out[key] === 'object') {
out[key] = cleanSchema(out[key]);
}
// Zod nullish() and picoschema optional fields will produce type `["string", "null"]`
// which is not supported by the model API. Convert them to just `"string"`.
if (key === 'type' && Array.isArray(out[key])) {
// find the first that's not `null`.
out[key] = out[key].find((t) => t !== 'null');
}
}
return out;
}
Expand Down
33 changes: 33 additions & 0 deletions js/plugins/googleai/tests/gemini_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { GenerateContentCandidate } from '@google/generative-ai';
import assert from 'node:assert';
import { describe, it } from 'node:test';
import {
cleanSchema,
fromGeminiCandidate,
toGeminiMessage,
toGeminiSystemInstruction,
Expand Down Expand Up @@ -345,3 +346,35 @@ describe('fromGeminiCandidate', () => {
});
}
});

describe('cleanSchema', () => {
it('strips nulls from type', () => {
const cleaned = cleanSchema({
type: 'object',
properties: {
title: {
type: 'string',
},
subtitle: {
type: ['string', 'null'],
},
},
required: ['title'],
additionalProperties: true,
$schema: 'http://json-schema.org/draft-07/schema#',
});

assert.deepStrictEqual(cleaned, {
type: 'object',
properties: {
title: {
type: 'string',
},
subtitle: {
type: 'string',
},
},
required: ['title'],
});
});
});
8 changes: 7 additions & 1 deletion js/plugins/vertexai/src/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ const convertSchemaProperty = (property) => {
}
};

function cleanSchema(schema: JSONSchema): JSONSchema {
export function cleanSchema(schema: JSONSchema): JSONSchema {
const out = structuredClone(schema);
for (const key in out) {
if (key === '$schema' || key === 'additionalProperties') {
Expand All @@ -425,6 +425,12 @@ function cleanSchema(schema: JSONSchema): JSONSchema {
if (typeof out[key] === 'object') {
out[key] = cleanSchema(out[key]);
}
// Zod nullish() and picoschema optional fields will produce type `["string", "null"]`
// which is not supported by the model API. Convert them to just `"string"`.
if (key === 'type' && Array.isArray(out[key])) {
// find the first that's not `null`.
out[key] = out[key].find((t) => t !== 'null');
}
}
return out;
}
Expand Down
33 changes: 33 additions & 0 deletions js/plugins/vertexai/tests/gemini_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { MessageData } from 'genkit';
import assert from 'node:assert';
import { describe, it } from 'node:test';
import {
cleanSchema,
fromGeminiCandidate,
toGeminiMessage,
toGeminiSystemInstruction,
Expand Down Expand Up @@ -348,3 +349,35 @@ describe('fromGeminiCandidate', () => {
});
}
});

describe('cleanSchema', () => {
it('strips nulls from type', () => {
const cleaned = cleanSchema({
type: 'object',
properties: {
title: {
type: 'string',
},
subtitle: {
type: ['string', 'null'],
},
},
required: ['title'],
additionalProperties: true,
$schema: 'http://json-schema.org/draft-07/schema#',
});

assert.deepStrictEqual(cleaned, {
type: 'object',
properties: {
title: {
type: 'string',
},
subtitle: {
type: 'string',
},
},
required: ['title'],
});
});
});

0 comments on commit 9a8a1d4

Please sign in to comment.