@@ -9,6 +9,7 @@ import { GOOGLE_VERTEX_AI, fileExtensionMimeTypeMap } from '../../globals';
9
9
import { ErrorResponse , FinetuneRequest , Logprobs } from '../types' ;
10
10
import { Context } from 'hono' ;
11
11
import { env } from 'hono/adapter' ;
12
+ import { JsonSchema } from '../../types/requestBody' ;
12
13
13
14
/**
14
15
* Encodes an object as a Base64 URL-encoded string.
@@ -209,7 +210,11 @@ export const derefer = (spec: Record<string, any>, defs = null) => {
209
210
if ( key === '$defs' ) {
210
211
continue ;
211
212
}
212
- if ( typeof object === 'string' || Array . isArray ( object ) ) {
213
+ if (
214
+ object === null ||
215
+ typeof object !== 'object' ||
216
+ Array . isArray ( object )
217
+ ) {
213
218
continue ;
214
219
}
215
220
const ref = object ?. [ '$ref' ] ;
@@ -226,8 +231,63 @@ export const derefer = (spec: Record<string, any>, defs = null) => {
226
231
return original ;
227
232
} ;
228
233
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
+
229
289
// 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
231
291
export const recursivelyDeleteUnsupportedParameters = ( obj : any ) => {
232
292
if ( typeof obj !== 'object' || obj === null || Array . isArray ( obj ) ) return ;
233
293
delete obj . additional_properties ;
0 commit comments