UNPKG

@genkit-ai/ai

Version:

Genkit AI framework generative AI APIs.

1 lines 19.6 kB
{"version":3,"sources":["../../src/generate/action.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 {\n Action,\n defineAction,\n GenkitError,\n getStreamingCallback,\n runWithStreamingCallback,\n stripUndefinedProps,\n z,\n} from '@genkit-ai/core';\nimport { logger } from '@genkit-ai/core/logging';\nimport { Registry } from '@genkit-ai/core/registry';\nimport { runInNewSpan, SPAN_TYPE_ATTR } from '@genkit-ai/core/tracing';\nimport {\n injectInstructions,\n resolveFormat,\n resolveInstructions,\n} from '../formats/index.js';\nimport { Formatter } from '../formats/types.js';\nimport {\n GenerateResponse,\n GenerateResponseChunk,\n GenerationResponseError,\n tagAsPreamble,\n} from '../generate.js';\nimport {\n GenerateActionOptions,\n GenerateActionOptionsSchema,\n GenerateActionOutputConfig,\n GenerateRequest,\n GenerateRequestSchema,\n GenerateResponseChunkData,\n GenerateResponseChunkSchema,\n GenerateResponseData,\n GenerateResponseSchema,\n ModelAction,\n ModelInfo,\n ModelMiddleware,\n ModelRequest,\n Part,\n resolveModel,\n Role,\n} from '../model.js';\nimport { resolveTools, ToolAction, toToolDefinition } from '../tool.js';\nimport {\n assertValidToolNames,\n resolveResumeOption,\n resolveToolRequests,\n} from './resolve-tool-requests.js';\n\nexport type GenerateAction = Action<\n typeof GenerateActionOptionsSchema,\n typeof GenerateResponseSchema,\n typeof GenerateResponseChunkSchema\n>;\n\n/** Defines (registers) a utilty generate action. */\nexport function defineGenerateAction(registry: Registry): GenerateAction {\n return defineAction(\n registry,\n {\n actionType: 'util',\n name: 'generate',\n inputSchema: GenerateActionOptionsSchema,\n outputSchema: GenerateResponseSchema,\n streamSchema: GenerateResponseChunkSchema,\n },\n async (request, { sendChunk }) => {\n const generateFn = () =>\n generate(registry, {\n rawRequest: request,\n currentTurn: 0,\n messageIndex: 0,\n // Generate util action does not support middleware. Maybe when we add named/registered middleware....\n middleware: [],\n });\n return sendChunk\n ? runWithStreamingCallback(\n registry,\n (c: GenerateResponseChunk) => sendChunk(c.toJSON ? c.toJSON() : c),\n generateFn\n )\n : generateFn();\n }\n );\n}\n\n/**\n * Encapsulates all generate logic. This is similar to `generateAction` except not an action and can take middleware.\n */\nexport async function generateHelper(\n registry: Registry,\n options: {\n rawRequest: GenerateActionOptions;\n middleware?: ModelMiddleware[];\n currentTurn?: number;\n messageIndex?: number;\n }\n): Promise<GenerateResponseData> {\n let currentTurn = options.currentTurn ?? 0;\n let messageIndex = options.messageIndex ?? 0;\n // do tracing\n return await runInNewSpan(\n registry,\n {\n metadata: {\n name: 'generate',\n },\n labels: {\n [SPAN_TYPE_ATTR]: 'util',\n },\n },\n async (metadata) => {\n metadata.name = 'generate';\n metadata.input = options.rawRequest;\n const output = await generate(registry, {\n rawRequest: options.rawRequest,\n middleware: options.middleware,\n currentTurn,\n messageIndex,\n });\n metadata.output = JSON.stringify(output);\n return output;\n }\n );\n}\n\n/** Take the raw request and resolve tools, model, and format into their registry action counterparts. */\nasync function resolveParameters(\n registry: Registry,\n request: GenerateActionOptions\n) {\n const [model, tools, format] = await Promise.all([\n resolveModel(registry, request.model, { warnDeprecated: true }).then(\n (r) => r.modelAction\n ),\n resolveTools(registry, request.tools),\n resolveFormat(registry, request.output),\n ]);\n return { model, tools, format };\n}\n\n/** Given a raw request and a formatter, apply the formatter's logic and instructions to the request. */\nfunction applyFormat(\n rawRequest: GenerateActionOptions,\n resolvedFormat?: Formatter\n) {\n const outRequest = { ...rawRequest };\n // If is schema is set but format is not explicitly set, default to `json` format.\n if (rawRequest.output?.jsonSchema && !rawRequest.output?.format) {\n outRequest.output = { ...rawRequest.output, format: 'json' };\n }\n\n const instructions = resolveInstructions(\n resolvedFormat,\n outRequest.output?.jsonSchema,\n outRequest?.output?.instructions\n );\n\n if (resolvedFormat) {\n if (\n shouldInjectFormatInstructions(resolvedFormat.config, rawRequest?.output)\n ) {\n outRequest.messages = injectInstructions(\n outRequest.messages,\n instructions\n );\n }\n outRequest.output = {\n // use output config from the format\n ...resolvedFormat.config,\n // if anything is set explicitly, use that\n ...outRequest.output,\n };\n }\n\n return outRequest;\n}\n\nexport function shouldInjectFormatInstructions(\n formatConfig?: Formatter['config'],\n rawRequestConfig?: z.infer<typeof GenerateActionOutputConfig>\n) {\n return (\n formatConfig?.defaultInstructions !== false ||\n rawRequestConfig?.instructions\n );\n}\n\nfunction applyTransferPreamble(\n rawRequest: GenerateActionOptions,\n transferPreamble?: GenerateActionOptions\n): GenerateActionOptions {\n if (!transferPreamble) {\n return rawRequest;\n }\n\n return stripUndefinedProps({\n ...rawRequest,\n messages: [\n ...tagAsPreamble(transferPreamble.messages!)!,\n ...rawRequest.messages.filter((m) => !m.metadata?.preamble),\n ],\n toolChoice: transferPreamble.toolChoice || rawRequest.toolChoice,\n tools: transferPreamble.tools || rawRequest.tools,\n config: transferPreamble.config || rawRequest.config,\n });\n}\n\nasync function generate(\n registry: Registry,\n {\n rawRequest,\n middleware,\n currentTurn,\n messageIndex,\n }: {\n rawRequest: GenerateActionOptions;\n middleware: ModelMiddleware[] | undefined;\n currentTurn: number;\n messageIndex: number;\n }\n): Promise<GenerateResponseData> {\n const { model, tools, format } = await resolveParameters(\n registry,\n rawRequest\n );\n rawRequest = applyFormat(rawRequest, format);\n\n // check to make sure we don't have overlapping tool names *before* generation\n await assertValidToolNames(tools);\n\n const {\n revisedRequest,\n interruptedResponse,\n toolMessage: resumedToolMessage,\n } = await resolveResumeOption(registry, rawRequest);\n // NOTE: in the future we should make it possible to interrupt a restart, but\n // at the moment it's too complicated because it's not clear how to return a\n // response that amends history but doesn't generate a new message, so we throw\n if (interruptedResponse) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'One or more tools triggered an interrupt during a restarted execution.',\n detail: { message: interruptedResponse.message },\n });\n }\n rawRequest = revisedRequest!;\n\n const request = await actionToGenerateRequest(\n rawRequest,\n tools,\n format,\n model\n );\n\n const previousChunks: GenerateResponseChunkData[] = [];\n\n let chunkRole: Role = 'model';\n // convenience method to create a full chunk from role and data, append the chunk\n // to the previousChunks array, and increment the message index as needed\n const makeChunk = (\n role: Role,\n chunk: GenerateResponseChunkData\n ): GenerateResponseChunk => {\n if (role !== chunkRole && previousChunks.length) messageIndex++;\n chunkRole = role;\n\n const prevToSend = [...previousChunks];\n previousChunks.push(chunk);\n\n return new GenerateResponseChunk(chunk, {\n index: messageIndex,\n role,\n previousChunks: prevToSend,\n parser: format?.handler(request.output?.schema).parseChunk,\n });\n };\n\n const streamingCallback = getStreamingCallback(registry);\n\n // if resolving the 'resume' option above generated a tool message, stream it.\n if (resumedToolMessage && streamingCallback) {\n streamingCallback(makeChunk('tool', resumedToolMessage));\n }\n\n const response = await runWithStreamingCallback(\n registry,\n streamingCallback &&\n ((chunk: GenerateResponseChunkData) =>\n streamingCallback(makeChunk('model', chunk))),\n async () => {\n const dispatch = async (\n index: number,\n req: z.infer<typeof GenerateRequestSchema>\n ) => {\n if (!middleware || index === middleware.length) {\n // end of the chain, call the original model action\n return await model(req);\n }\n\n const currentMiddleware = middleware[index];\n return currentMiddleware(req, async (modifiedReq) =>\n dispatch(index + 1, modifiedReq || req)\n );\n };\n\n return new GenerateResponse(await dispatch(0, request), {\n request,\n parser: format?.handler(request.output?.schema).parseMessage,\n });\n }\n );\n\n // Throw an error if the response is not usable.\n response.assertValid();\n const generatedMessage = response.message!; // would have thrown if no message\n\n const toolRequests = generatedMessage.content.filter(\n (part) => !!part.toolRequest\n );\n\n if (rawRequest.returnToolRequests || toolRequests.length === 0) {\n if (toolRequests.length === 0) response.assertValidSchema(request);\n return response.toJSON();\n }\n\n const maxIterations = rawRequest.maxTurns ?? 5;\n if (currentTurn + 1 > maxIterations) {\n throw new GenerationResponseError(\n response,\n `Exceeded maximum tool call iterations (${maxIterations})`,\n 'ABORTED',\n { request }\n );\n }\n\n const { revisedModelMessage, toolMessage, transferPreamble } =\n await resolveToolRequests(registry, rawRequest, generatedMessage);\n\n // if an interrupt message is returned, stop the tool loop and return a response\n if (revisedModelMessage) {\n return {\n ...response.toJSON(),\n finishReason: 'interrupted',\n finishMessage: 'One or more tool calls resulted in interrupts.',\n message: revisedModelMessage,\n };\n }\n\n // if the loop will continue, stream out the tool response message...\n streamingCallback?.(\n makeChunk('tool', {\n content: toolMessage!.content,\n })\n );\n\n let nextRequest = {\n ...rawRequest,\n messages: [...rawRequest.messages, generatedMessage.toJSON(), toolMessage!],\n };\n nextRequest = applyTransferPreamble(nextRequest, transferPreamble);\n\n // then recursively call for another loop\n return await generateHelper(registry, {\n rawRequest: nextRequest,\n middleware: middleware,\n currentTurn: currentTurn + 1,\n messageIndex: messageIndex + 1,\n });\n}\n\nasync function actionToGenerateRequest(\n options: GenerateActionOptions,\n resolvedTools: ToolAction[] | undefined,\n resolvedFormat: Formatter | undefined,\n model: ModelAction\n): Promise<GenerateRequest> {\n const modelInfo = model.__action.metadata?.model as ModelInfo;\n if (\n (options.tools?.length ?? 0) > 0 &&\n modelInfo?.supports &&\n !modelInfo?.supports?.tools\n ) {\n logger.warn(\n `The model '${model.__action.name}' does not support tools (you set: ${options.tools?.length} tools). ` +\n 'The model may not behave the way you expect.'\n );\n }\n if (\n options.toolChoice &&\n modelInfo?.supports &&\n !modelInfo?.supports?.toolChoice\n ) {\n logger.warn(\n `The model '${model.__action.name}' does not support the 'toolChoice' option (you set: ${options.toolChoice}). ` +\n 'The model may not behave the way you expect.'\n );\n }\n const out: ModelRequest = {\n messages: options.messages,\n config: options.config,\n docs: options.docs,\n tools: resolvedTools?.map(toToolDefinition) || [],\n output: stripUndefinedProps({\n constrained: options.output?.constrained,\n contentType: options.output?.contentType,\n format: options.output?.format,\n schema: options.output?.jsonSchema,\n }),\n };\n if (options.toolChoice) {\n out.toolChoice = options.toolChoice;\n }\n if (out.output && !out.output.schema) delete out.output.schema;\n return out;\n}\n\nexport function inferRoleFromParts(parts: Part[]): Role {\n const uniqueRoles = new Set<Role>();\n for (const part of parts) {\n const role = getRoleFromPart(part);\n uniqueRoles.add(role);\n if (uniqueRoles.size > 1) {\n throw new Error('Contents contain mixed roles');\n }\n }\n return Array.from(uniqueRoles)[0];\n}\n\nfunction getRoleFromPart(part: Part): Role {\n if (part.toolRequest !== undefined) return 'model';\n if (part.toolResponse !== undefined) return 'tool';\n if (part.text !== undefined) return 'user';\n if (part.media !== undefined) return 'user';\n if (part.data !== undefined) return 'user';\n throw new Error('No recognized fields in content');\n}\n"],"mappings":"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","names":[]}