UNPKG

@genkit-ai/ai

Version:

Genkit AI framework generative AI APIs.

1 lines 5.98 kB
{"version":3,"sources":["../../src/formats/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JSONSchema } from '@genkit-ai/core';\nimport { Registry } from '@genkit-ai/core/registry';\nimport { OutputOptions } from '../generate.js';\nimport { MessageData, TextPart } from '../model.js';\nimport { arrayFormatter } from './array.js';\nimport { enumFormatter } from './enum.js';\nimport { jsonFormatter } from './json.js';\nimport { jsonlFormatter } from './jsonl.js';\nimport { textFormatter } from './text.js';\nimport { type Formatter } from './types.js';\n\nexport { type Formatter };\n\nexport function defineFormat(\n registry: Registry,\n options: { name: string } & Formatter['config'],\n handler: Formatter['handler']\n): { config: Formatter['config']; handler: Formatter['handler'] } {\n const { name, ...config } = options;\n const formatter = { config, handler };\n registry.registerValue('format', name, formatter);\n return formatter;\n}\n\nexport type FormatArgument =\n | keyof typeof DEFAULT_FORMATS\n | Omit<string, keyof typeof DEFAULT_FORMATS>\n | undefined\n | null;\n\nexport async function resolveFormat(\n registry: Registry,\n outputOpts: OutputOptions | undefined\n): Promise<Formatter<any, any> | undefined> {\n if (!outputOpts) return undefined;\n // If schema is set but no explicit format is set we default to json.\n if (outputOpts.schema && !outputOpts.format) {\n return registry.lookupValue<Formatter>('format', 'json');\n }\n if (outputOpts.format) {\n return registry.lookupValue<Formatter>('format', outputOpts.format);\n }\n return undefined;\n}\n\nexport function resolveInstructions(\n format?: Formatter,\n schema?: JSONSchema,\n instructionsOption?: boolean | string\n): string | undefined {\n if (typeof instructionsOption === 'string') return instructionsOption; // user provided instructions\n if (instructionsOption === false) return undefined; // user says no instructions\n if (!format) return undefined;\n return format.handler(schema).instructions;\n}\n\nexport function injectInstructions(\n messages: MessageData[],\n instructions: string | false | undefined\n): MessageData[] {\n if (!instructions) return messages;\n\n // bail out if a non-pending output part is already present\n if (\n messages.find((m) =>\n m.content.find(\n (p) => p.metadata?.purpose === 'output' && !p.metadata?.pending\n )\n )\n ) {\n return messages;\n }\n\n const newPart: TextPart = {\n text: instructions,\n metadata: { purpose: 'output' },\n };\n\n // find the system message or the last user message\n let targetIndex = messages.findIndex((m) => m.role === 'system');\n if (targetIndex < 0)\n targetIndex = messages.map((m) => m.role).lastIndexOf('user');\n if (targetIndex < 0) return messages;\n\n const m = {\n ...messages[targetIndex],\n content: [...messages[targetIndex].content],\n };\n\n const partIndex = m.content.findIndex(\n (p) => p.metadata?.purpose === 'output' && p.metadata?.pending\n );\n if (partIndex > 0) {\n m.content.splice(partIndex, 1, newPart);\n } else {\n m.content.push(newPart);\n }\n\n const outMessages = [...messages];\n outMessages.splice(targetIndex, 1, m);\n return outMessages;\n}\n\nexport const DEFAULT_FORMATS: Formatter<any, any>[] = [\n jsonFormatter,\n arrayFormatter,\n textFormatter,\n enumFormatter,\n jsonlFormatter,\n];\n\n/**\n * configureFormats registers the default built-in formats on a registry.\n */\nexport function configureFormats(registry: Registry) {\n for (const format of DEFAULT_FORMATS) {\n defineFormat(\n registry,\n { name: format.name, ...format.config },\n format.handler\n );\n }\n}\n"],"mappings":"AAoBA,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAKvB,SAAS,aACd,UACA,SACA,SACgE;AAChE,QAAM,EAAE,MAAM,GAAG,OAAO,IAAI;AAC5B,QAAM,YAAY,EAAE,QAAQ,QAAQ;AACpC,WAAS,cAAc,UAAU,MAAM,SAAS;AAChD,SAAO;AACT;AAQA,eAAsB,cACpB,UACA,YAC0C;AAC1C,MAAI,CAAC,WAAY,QAAO;AAExB,MAAI,WAAW,UAAU,CAAC,WAAW,QAAQ;AAC3C,WAAO,SAAS,YAAuB,UAAU,MAAM;AAAA,EACzD;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,SAAS,YAAuB,UAAU,WAAW,MAAM;AAAA,EACpE;AACA,SAAO;AACT;AAEO,SAAS,oBACd,QACA,QACA,oBACoB;AACpB,MAAI,OAAO,uBAAuB,SAAU,QAAO;AACnD,MAAI,uBAAuB,MAAO,QAAO;AACzC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,QAAQ,MAAM,EAAE;AAChC;AAEO,SAAS,mBACd,UACA,cACe;AACf,MAAI,CAAC,aAAc,QAAO;AAG1B,MACE,SAAS;AAAA,IAAK,CAACA,OACbA,GAAE,QAAQ;AAAA,MACR,CAAC,MAAM,EAAE,UAAU,YAAY,YAAY,CAAC,EAAE,UAAU;AAAA,IAC1D;AAAA,EACF,GACA;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAoB;AAAA,IACxB,MAAM;AAAA,IACN,UAAU,EAAE,SAAS,SAAS;AAAA,EAChC;AAGA,MAAI,cAAc,SAAS,UAAU,CAACA,OAAMA,GAAE,SAAS,QAAQ;AAC/D,MAAI,cAAc;AAChB,kBAAc,SAAS,IAAI,CAACA,OAAMA,GAAE,IAAI,EAAE,YAAY,MAAM;AAC9D,MAAI,cAAc,EAAG,QAAO;AAE5B,QAAM,IAAI;AAAA,IACR,GAAG,SAAS,WAAW;AAAA,IACvB,SAAS,CAAC,GAAG,SAAS,WAAW,EAAE,OAAO;AAAA,EAC5C;AAEA,QAAM,YAAY,EAAE,QAAQ;AAAA,IAC1B,CAAC,MAAM,EAAE,UAAU,YAAY,YAAY,EAAE,UAAU;AAAA,EACzD;AACA,MAAI,YAAY,GAAG;AACjB,MAAE,QAAQ,OAAO,WAAW,GAAG,OAAO;AAAA,EACxC,OAAO;AACL,MAAE,QAAQ,KAAK,OAAO;AAAA,EACxB;AAEA,QAAM,cAAc,CAAC,GAAG,QAAQ;AAChC,cAAY,OAAO,aAAa,GAAG,CAAC;AACpC,SAAO;AACT;AAEO,MAAM,kBAAyC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,iBAAiB,UAAoB;AACnD,aAAW,UAAU,iBAAiB;AACpC;AAAA,MACE;AAAA,MACA,EAAE,MAAM,OAAO,MAAM,GAAG,OAAO,OAAO;AAAA,MACtC,OAAO;AAAA,IACT;AAAA,EACF;AACF;","names":["m"]}