Skip to content

Commit 482d5c7

Browse files
authored
fix(js/ai): default to JSON format when schema is set (#1728)
1 parent 4db4e9a commit 482d5c7

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

js/ai/src/generate.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,10 @@ export async function generate<
358358
});
359359

360360
// If is schema is set but format is not explicitly set, default to `json` format.
361-
if (resolvedOptions.output?.schema && !resolvedOptions.output?.format) {
361+
if (
362+
(resolvedOptions.output?.schema || resolvedOptions.output?.jsonSchema) &&
363+
!resolvedOptions.output?.format
364+
) {
362365
resolvedOptions.output.format = 'json';
363366
}
364367
const resolvedFormat = await resolveFormat(registry, resolvedOptions.output);

js/genkit/tests/prompts/output.prompt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
model: staticResponseModel
3+
input:
4+
schema:
5+
name: string
6+
output:
7+
schema:
8+
bar: string
9+
---
10+
11+
Hi {{ name }}

js/genkit/tests/prompts_test.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import { ModelMiddleware, modelRef } from '@genkit-ai/ai/model';
1818
import * as assert from 'assert';
1919
import { beforeEach, describe, it } from 'node:test';
20+
import { stripUndefinedProps } from '../../core/src';
2021
import { GenkitBeta, genkit } from '../src/beta';
2122
import { PromptAction, z } from '../src/index';
2223
import {
@@ -61,7 +62,7 @@ const wrapResponse: ModelMiddleware = async (req, next) => {
6162
};
6263
};
6364

64-
describe('definePrompt - functional', () => {
65+
describe('definePrompt', () => {
6566
let ai: GenkitBeta;
6667

6768
beforeEach(() => {
@@ -172,7 +173,7 @@ describe('definePrompt - functional', () => {
172173
});
173174
});
174175

175-
describe('definePrompt - dotprompt', () => {
176+
describe.only('definePrompt', () => {
176177
describe('default model', () => {
177178
let ai: GenkitBeta;
178179

@@ -309,14 +310,15 @@ describe('definePrompt - dotprompt', () => {
309310
});
310311
});
311312

312-
describe('default model ref', () => {
313+
describe.only('default model ref', () => {
313314
let ai: GenkitBeta;
314315

315316
beforeEach(() => {
316317
ai = genkit({
317318
model: modelRef({
318319
name: 'echoModel',
319320
}),
321+
promptDir: './tests/prompts',
320322
});
321323
defineEchoModel(ai);
322324
});
@@ -400,6 +402,52 @@ describe('definePrompt - dotprompt', () => {
400402
assert.deepStrictEqual(foo, { bar: 'baz' });
401403
});
402404

405+
it('defaults to json format from a loaded prompt', async () => {
406+
defineStaticResponseModel(ai, {
407+
role: 'model',
408+
content: [
409+
{
410+
text: '```json\n{bar: "baz"}\n```',
411+
},
412+
],
413+
});
414+
const hi = ai.prompt('output');
415+
416+
const response = await hi({ name: 'Genkit' });
417+
const foo = response.output;
418+
assert.deepStrictEqual(stripUndefinedProps(response.request), {
419+
config: {},
420+
messages: [
421+
{
422+
content: [
423+
{
424+
text: 'Hi Genkit',
425+
},
426+
],
427+
role: 'user',
428+
},
429+
],
430+
output: {
431+
constrained: true,
432+
contentType: 'application/json',
433+
format: 'json',
434+
schema: {
435+
additionalProperties: false,
436+
properties: {
437+
bar: {
438+
type: 'string',
439+
},
440+
},
441+
required: ['bar'],
442+
type: 'object',
443+
},
444+
},
445+
tools: [],
446+
});
447+
448+
assert.deepStrictEqual(foo, { bar: 'baz' });
449+
});
450+
403451
it('streams dotprompt with default model', async () => {
404452
const hi = ai.definePrompt({
405453
name: 'hi',

0 commit comments

Comments
 (0)