Skip to content

Commit 215913a

Browse files
committed
fix: fully dereference schemas to remove / for Gemini tool parameters
1 parent 16d9f39 commit 215913a

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

src/providers/google-vertex-ai/chatComplete.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import type {
4747
import {
4848
getMimeType,
4949
recursivelyDeleteUnsupportedParameters,
50+
transformGeminiToolParameters,
5051
transformVertexLogprobs,
5152
} from './utils';
5253

@@ -299,6 +300,11 @@ export const VertexGoogleChatCompleteConfig: ProviderConfig = {
299300
) {
300301
tools.push(buildGoogleSearchRetrievalTool(tool));
301302
} else {
303+
if (tool.function?.parameters) {
304+
tool.function.parameters = transformGeminiToolParameters(
305+
tool.function.parameters
306+
);
307+
}
302308
functionDeclarations.push(tool.function);
303309
}
304310
}

src/providers/google-vertex-ai/utils.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { GOOGLE_VERTEX_AI, fileExtensionMimeTypeMap } from '../../globals';
99
import { ErrorResponse, FinetuneRequest, Logprobs } from '../types';
1010
import { Context } from 'hono';
1111
import { env } from 'hono/adapter';
12+
import { JsonSchema } from '../../types/requestBody';
1213

1314
/**
1415
* Encodes an object as a Base64 URL-encoded string.
@@ -209,7 +210,11 @@ export const derefer = (spec: Record<string, any>, defs = null) => {
209210
if (key === '$defs') {
210211
continue;
211212
}
212-
if (typeof object === 'string' || Array.isArray(object)) {
213+
if (
214+
object === null ||
215+
typeof object !== 'object' ||
216+
Array.isArray(object)
217+
) {
213218
continue;
214219
}
215220
const ref = object?.['$ref'];
@@ -226,8 +231,63 @@ export const derefer = (spec: Record<string, any>, defs = null) => {
226231
return original;
227232
};
228233

234+
export const transformGeminiToolParameters = (
235+
parameters: JsonSchema
236+
): JsonSchema => {
237+
if (
238+
!parameters ||
239+
typeof parameters !== 'object' ||
240+
Array.isArray(parameters)
241+
) {
242+
return parameters;
243+
}
244+
245+
let schema: JsonSchema = parameters;
246+
if ('$defs' in schema && typeof schema.$defs === 'object') {
247+
schema = derefer(schema);
248+
delete schema.$defs;
249+
}
250+
251+
const transformNode = (node: JsonSchema): JsonSchema => {
252+
if (Array.isArray(node)) {
253+
return node.map(transformNode);
254+
}
255+
if (!node || typeof node !== 'object') return node;
256+
257+
const transformed: JsonSchema = {};
258+
259+
for (const [key, value] of Object.entries(node)) {
260+
if (key === 'enum' && Array.isArray(value)) {
261+
transformed.enum = value;
262+
transformed.format = 'enum';
263+
} else if (
264+
key === 'anyOf' &&
265+
Array.isArray(value) &&
266+
value.length === 2
267+
) {
268+
// Convert anyOf with null type to nullable which is a supported param
269+
const nonNullItems = value.filter(
270+
(item) => !(typeof item === 'object' && item?.type === 'null')
271+
);
272+
if (nonNullItems.length === 1) {
273+
Object.assign(transformed, transformNode(nonNullItems[0]));
274+
transformed.nullable = true;
275+
} else {
276+
// leave true unions as-is which is not supported by Google, let Google raise an error
277+
transformed.anyOf = transformNode(value);
278+
}
279+
} else {
280+
transformed[key] = transformNode(value);
281+
}
282+
}
283+
return transformed;
284+
};
285+
286+
return transformNode(schema);
287+
};
288+
229289
// Vertex AI does not support additionalProperties in JSON Schema
230-
// https://cloud.google.com/vertex-ai/docs/reference/rest/v1/Schema
290+
// https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/function-calling#schema
231291
export const recursivelyDeleteUnsupportedParameters = (obj: any) => {
232292
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) return;
233293
delete obj.additional_properties;

src/providers/google/chatComplete.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
derefer,
1515
getMimeType,
1616
recursivelyDeleteUnsupportedParameters,
17+
transformGeminiToolParameters,
1718
transformVertexLogprobs,
1819
} from '../google-vertex-ai/utils';
1920
import {
@@ -381,6 +382,11 @@ export const GoogleChatCompleteConfig: ProviderConfig = {
381382
) {
382383
tools.push(buildGoogleSearchRetrievalTool(tool));
383384
} else {
385+
if (tool.function?.parameters) {
386+
tool.function.parameters = transformGeminiToolParameters(
387+
tool.function.parameters
388+
);
389+
}
384390
functionDeclarations.push(tool.function);
385391
}
386392
}

0 commit comments

Comments
 (0)