ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Genkit Model Action 规范全解:从 GenerateRequest 到流式响应的模型契约与实现

2026/9/17 13:08:53 拓冰建站 浏览量
Genkit Model Action 规范全解:从 GenerateRequest 到流式响应的模型契约与实现 Genkit Model Action 规范全解从 GenerateRequest 到流式响应的模型契约与实现【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkitGenkit由 Google 构建并用于生产环境的开源 AI 应用框架支持 JavaScript、Go、Dart 与 Python将“模型”统一抽象为一种特殊的 Action。本文以仓库 docs/model-spec.md 为核心骨架结合 JavaScript 与 Go 两套实现的源码证据系统讲解模型动作的输入输出契约、Part 统一内容模型、元数据能力声明以及系统消息、配置透传、工具调用、结构化输出等实现要求。读完本文你将掌握在 Genkit 中定义一个新模型插件、实现流式响应与多轮工具循环的全部规范细节并能对照源码理解这些契约在框架内部是如何被校验与执行的。模型动作Model Action定义在 Genkit 中一个模型就是一个 Action它具备以下固定特征见 docs/model-spec.md特征取值Action 类型Action Typemodel输入 SchemaInput SchemaGenerateRequest输出 SchemaOutput SchemaGenerateResponse流式 SchemaStreaming SchemaGenerateResponseChunk在 JavaScript 实现中这一契约被建模为 model.ts 中的ModelAction类型export type ModelActionCustomOptionsSchema extends z.ZodTypeAny z.ZodTypeAny Action typeof GenerateRequestSchema, // 输入GenerateRequest typeof GenerateResponseSchema, // 输出GenerateResponse typeof GenerateResponseChunkSchema // 流式GenerateResponseChunk { __configSchema: CustomOptionsSchema; };创建模型动作有两种方式defineModel()注册到 registry供应用查找和model()仅创建不注册适合插件作者从 resolver 返回模型动作。两者最终都会调用modelActionOptions()把输入输出 schema 与元数据打包成标准 Action 参数model.tsreturn { actionType: model, name: options.name, description: label, inputSchema: GenerateRequestSchema, outputSchema: GenerateResponseSchema, metadata: { model: { label, customOptions, versions, supports } }, };在 Go 实现中对应的是 gen.go 中的ModelAction内嵌core.Action[*ModelRequest, *ModelResponse, *ModelResponseChunk]与 generate.go 中的Model接口——Generate(ctx, req *ModelRequest, cb ModelStreamCallback)同时承担普通调用与流式回调。模型元数据Metadata模型动作通过metadata.model声明自身能力供框架、开发者工具如 CLI和上层应用做能力发现与校验。规范定义的字段如下label人类可读名称例如Google AI - Gemini Pro。versions支持的版本字符串数组。supports能力声明对象multiturn是否支持多轮历史消息media是否支持多模态输入tools是否支持工具调用systemRole是否支持system角色消息output支持的输出格式数组如[json, text]contentType支持的输出内容类型数组context是否原生支持文档上下文RAG groundingconstrained原生约束生成支持级别枚举none/all/no-toolstoolChoice是否支持强制指定工具选择longRunning是否支持长时运行操作。stage开发阶段枚举featured/stable/unstable/legacy/deprecated。customOptions模型特有配置的 JSON Schema在请求中通过config暴露。Go 端结构体ModelInfo与ModelSupports完整对应了上述字段且为stage、constrained定义了具名常量ModelStageFeatured…、ConstrainedSupportNone/All/NoTools见 gen.go。能力声明如何被框架使用supports并非摆设它在 model/middleware.ts 中被两类内置中间件消费validateSupport在请求进入模型前做能力预检——例如supports.media false时请求中若出现 media part、supports.tools false时请求若带 tools、supports.multiturn false时若传入多条消息都会直接抛错错误信息中会完整回显请求体便于排查。getModelMiddlewaremodel.ts当模型未声明context支持时自动挂载augmentWithContext()当constrained为none、或为no-tools且请求携带工具时自动挂载simulateConstrainedGeneration()用提示词模拟约束生成。也就是说模型作者只需如实声明能力框架会自动补齐“不支持能力”的降级路径这正是 Model Action 规范的价值所在。数据契约GenerateRequest 与 GenerateResponseGenerateRequest模型动作输入字段类型说明messagesMessage[]必填会话历史消息列表configany模型特有配置如 temperature、topK按模型 config schema 校验toolsToolDefinition[]可供模型调用的工具列表toolChoiceenum工具选择策略auto、required、noneoutputOutputConfig期望输出格式/结构的配置docsDocumentData[]作为上下文使用的检索文档JS 端对应 model-types.ts 中的ModelRequestSchema/GenerateRequestSchema后者额外保留了一个已被废弃的candidates字段注释明确说明“所有响应现在只返回单一候选”可作为版本演进线索。Go 端对应 gen.go 中的ModelRequest结构体。toolChoice的三个取值在GenerateActionOptionsSchema的注释中有精确语义auto让模型自行决定是否使用工具required强制模型选择一个工具none强制模型不使用任何工具默认auto。OutputConfig字段类型说明formatstring期望格式如json、textschemaRecordstring, any定义期望输出结构的 JSON Schemaconstrainedboolean是否原生强制 schema 约束contentTypestring输出的具体内容类型JS 实现OutputConfigSchema位于 model-types.ts。此外框架内部还有更丰富的GenerateActionOutputConfig含instructions、jsonSchema供上层 generate action 使用。GenerateResponse模型动作输出字段类型说明messageMessage生成的消息finishReasonenum结束原因stop、length、blocked、interrupted、other、unknown、failedfinishMessagestring结束原因的补充信息errorRuntimeError当finishReason为failed或被中止的模型停止时的分类失败信息blocked时不存在usageGenerationUsageToken 与字符用量统计latencyMsnumber生成耗时毫秒customany模型特有附加信息requestGenerateRequest触发本次响应的请求值得注意的是latencyMs并非由插件手工填充而是defineModel/model在 runner 外层用performance.now()自动计时的model.ts插件只需返回普通响应即可。finishReason在 JS 端为FinishReasonSchema枚举model-types.ts实际枚举含aborted共 8 项。Go 端在 generate.go 中定义了isAbnormal()辅助方法blocked、aborted、failed、interrupted、other均视为异常结束驱动多轮工具循环的提前终止与错误归因。usage的GenerationUsageSchema非常完整除了 input/output/total tokens还统计字符数、图片数、视频数、音频文件数以及thoughtsTokens、cachedContentTokens和自定义custom计数。GenerateResponseChunk流式响应块字段类型说明roleRole正在生成消息的角色通常为modelindexnumber响应中消息的索引通常为 0contentPart[]必填本块包含的内容 partsaggregatedboolean为 true 时本块包含到目前为止的全部累计内容customany模型特有附加信息JS 实现ModelResponseChunkSchemaGenerateResponseChunkSchema为其别名位于 model-types.ts注释明确了aggregated与增量incremental两种语义。统一内容模型Message 与 PartMessage字段类型说明roleenum必填消息发送者角色system、user、model、toolcontentPart[]必填消息内容由一个或多个 part 组成metadataRecordstring, any与消息关联的任意元数据RoleSchema z.enum([system, user, model, tool])MessageSchema见 model-types.ts。Part统一的内容单元Genkit 用统一的Part结构表示不同类型的内容Part 是若干具体 part 类型的联合。JS 端的完整定义见 parts.tsPartSchema由 8 种 part 联合而成比规范文档多出resource类型。文本 PartText Part{ text: Hello, world! }媒体 PartMedia Part——多模态内容内联数据应编码为data:URIbase64。图片{ media: { url: data:image/jpeg;base64,/9j/4AAQSkZJRg..., contentType: image/jpeg } }音频{ media: { url: data:audio/L16;codecpcm;rate24000;base64,AAAAAA..., contentType: audio/L16;codecpcm;rate24000 } }视频{ media: { url: https://example.com/video.mp4, contentType: video/mp4 } }所有 part 都可携带metadata用于存放放不进主 schema 的提供者特有信息。常见用途包括图片/视频的mediaResolution、视频的videoMetadata如时长、偏移量或内部签名如thoughtSignature{ media: { url: ... }, metadata: { mediaResolution: { level: MEDIA_RESOLUTION_HIGH }, videoMetadata: { startOffset: { seconds: 10 } } } }工具请求 PartTool Request Part——模型请求执行某个工具{ toolRequest: { name: weatherTool, ref: call_123, input: { city: New York } } }JS 端ToolRequestSchema还包含partial: boolean可选字段用于流式工具调用的部分请求见下文“部分工具请求”。工具响应 PartTool Response Part——工具执行结果回传给模型{ toolResponse: { name: weatherTool, ref: call_123, output: { temperature: 72 }, content: [ ] } }注意ref必须与请求的 ref 匹配output通常是结构化 JSONcontent为可选内容 parts例如工具返回图片等富内容。JS 实现ToolResponseSchema支持{ output, content, metadata }的多部件multipart结构parts.ts。自定义 PartCustom Part——表示未被其他类型覆盖的提供者特有内容典型场景是服务端工具如代码执行的结果返回{ custom: { executableCode: { code: print(Hello World), language: PYTHON }, codeExecutionResult: { outcome: OUTCOME_OK, output: Hello World\n } } }推理 PartReasoning Part——模型提供的思维链chain-of-thought或推理文本{ reasoning: First, I will calculate... }数据 PartData Part——规范中标注为“保留供未来使用目前没有任何已知插件支持”表示通用结构化数据{ data: { key: value } }提供者特有功能Provider-Specific Features许多模型提供超出纯文本生成或客户端工具调用的服务端能力规范要求统一通过config对象或特定 metadata 处理。服务端工具Server-Side ToolsWeb SearchGrounding、Code Execution、URL Context 等通常实现为“服务端工具”——因为客户端不执行它们所以配置在config中而非tools列表里。Web Search 配置示例{ config: { googleSearch: {}, tools: [{ googleSearch: {} }] } }注googleSearch为提供者特有键某些提供者可能使用tools配置键。URL Context 配置示例{ config: { urlContext: { urls: [https://example.com/article] } } }编码准则Encoding Guidelines请求侧启用/配置服务端功能一律使用config除非客户端确实要执行该工具否则不要使用ToolRequestPart。响应侧若服务端工具产生了内容如代码执行输出它可以作为TextPart若已融入回答或CustomPart出现执行相关的元数据如搜索来源、grounding 元数据应放在GenerateResponse.custom字段或Message.metadata中。行为规范Behavior请求处理流程校验模型动作校验GenerateRequest。上下文若提供了docs模型动作应将其纳入上下文典型做法是增强消息历史。工具若提供了tools将其转换为底层模型 API 期望的格式。配置应用config选项。对应地JS 框架为docs提供了augmentWithContext()中间件把检索到的上下文文档渲染成文本追加到最后一条 user 消息默认前言为\n\nUse the following information to complete your task:\n\n每条文档按[引用键]: 文本模板渲染model/middleware.ts。该中间件仅在模型未声明原生context支持时挂载这正是规范第 2 条“典型做法是增强消息历史”的框架级实现。系统消息处理Genkit 将系统指令标准化为messages数组中的role: system消息。但许多提供者如 Google GenAI要求系统指令作为独立配置字段而非会话历史的一部分。实现要求MUST模型动作必须接受输入messages数组中的role: system消息若底层提供者要求独立系统指令从messages数组中提取系统消息按提供者要求转换/格式化如systemInstruction字段若提供者不支持历史中的system角色确保这些消息不会被传入常规会话历史。框架为不支持原生 system role 的模型提供了simulateSystemPrompt()中间件model/middleware.ts把system消息改写成一对 user 消息SYSTEM INSTRUCTIONS:\n 指令与 model 消息Understood.插入历史实现模拟系统提示。配置处理透传模式Passthrough模型插件应遵循“透传”模式处理配置这样底层模型 API 新增的功能无需更新插件即可被用户立即使用提取已知选项显式解构已知配置键如temperature、topK、topP按 Genkit 通用 schema 或特定逻辑处理透传其余选项把所有剩余未知键直接传给底层模型 API 的配置对象。const { temperature, topK, ...restOfConfig } request.config || {}; const apiRequest { model: modelName, temperature: temperature, // 处理已知键 top_k: topK, ...restOfConfig // 透传未知键 };合并工具若提供者支持通过配置传工具如config.tools应与标准request.tools合并让用户能在标准 Genkit 工具之外附带提供者特有的工具定义如服务端工具const tools request.tools?.map(toProviderTool) || []; if (config.tools) { tools.push(...config.tools); }JS 框架侧GenerationCommonConfigSchemamodel-types.ts本身就以.passthrough()声明已定义version、temperature、maxOutputTokens、topK、topP、stopSequences最多 5 条、apiKey等通用键其余键原样透传。规范中“已知键按通用 schema 处理、未知键透传”的双层设计与插件实现侧如google-genai的 config overrides配合形成完整的配置链路。响应生成内容模型输出被解析为Part对象——文本映射为TextPart函数调用映射为ToolRequestPart。流式流式时模型发出GenerateResponseChunk理想情况下 chunk 应包含增量更新若底层模型在流式时只支持完整响应则应设置aggregated: true。结束原因模型必须把提供者特有的 finish reason 映射为 Genkit 标准枚举。JS 端defineModel会为响应自动补latencyMsperformance.now()计时同时modelActionOptions会把configSchema转成 JSON Schema 写入metadata.model.customOptions供工具链校验用户传入的config。工具处理工具是 Genkit 模型的核心能力实现涉及定义转换、请求处理含流式与响应处理三部分。工具定义转换模型动作必须把 Genkit 的ToolDefinition转换为提供者期望的格式名称若提供者有严格命名规则需做清洗例如 Gemini 把/替换为__输入 Schema把inputSchema中的 JSON Schema 转换为提供者的 schema 格式描述透传工具描述。ToolDefinition在 JS 端包含name、key、description、inputSchema、outputSchema、metadatamodel-types.ts。工具请求当模型决定调用工具时发出ToolRequestPartref若提供者支持分配稳定的refcall ID用于关联响应input工具参数。部分工具请求流式部分模型如 Gemini 3.0支持流式工具调用此时模型发出partial: true的ToolRequestPartpartial请求中的input应包含到目前为止累计的参数取决于插件状态管理逻辑或当前 delta工具调用的最后一个 chunk 应为partial: false或省略该字段。JS 端ToolRequestSchema的partial字段parts.ts正是为这一场景设计的。工具响应工具执行结果以role: tool消息中的ToolResponsePart回传给模型ref必须匹配对应ToolRequestPart的refoutput工具执行结果通常是 JSON 对象content可选 parts 列表如工具返回图片或其他富内容。多轮流程Multi-turn Flow支持工具的模型必须处理如下对话循环User MessageModel Message包含ToolRequestPartTool Message包含ToolResponsePartModel Message最终回答Go 端 generate.go 中实现了完整的工具循环框架负责执行工具并把结果回填Response.ToolRequests()、FinishReason.isAbnormal()用于判断异常终止插件只需在一次调用中正确产出ToolRequestPart并在后续收到tool角色消息后给出最终回答。JS 端GenerateActionOptionsSchema中的maxTurns默认 5与returnToolRequests则控制了这一循环的迭代上限与是否交由上层手动处理工具请求。结构化输出Structured Output若提供output.schema模型应尝试生成匹配该 schema 的内容若output.constrained为 true 且模型支持则由模型生成过程原生强制 schema否则schema 可被包含在提示词指令中结果的结构化数据通常序列化在TextPart中。框架为不支持原生约束生成的模型提供了simulateConstrainedGeneration()中间件model/middleware.ts把 schema 以Output should be in JSON format and conform to the following schema:\n\n\\n{...}\n的形式注入 user 消息同时对底层模型关闭constrained标记实现“模拟约束生成”。而constrained声明为all 的模型则直接透传由其自身保证 schema 遵守。跨语言一致性一份规范三套实现规范文档描述的契约在仓库中并非单一语言的孤例而是通过多语言实现保持一致JavaScript/TypeScriptmodel-types.ts 定义全部 Zod schemaGenerateRequestSchema、ModelResponseSchema、GenerateResponseChunkSchema、FinishReasonSchema、GenerationUsageSchema等parts.ts 定义 Part 联合类型model.ts 定义defineModel/model创建入口model/middleware.ts 提供能力校验与降级中间件Gogen.go 定义ModelInfo、ModelSupports、ModelStage、ConstrainedSupport与ModelRequestgenerate.go 定义Model接口、ModelAction与多轮工具循环Pythonpy/packages/genkit包亦实现了同等的模型抽象如genkit/ai模块可用于对照阅读。实战清单实现一个符合规范的模型插件综合规范与源码一个合规的 Genkit 模型插件作者需要落实声明式能力如实填写label、versions、supports尤其是constrained与context它们直接决定框架是否挂载模拟中间件与stage配置透传解构通用键后把剩余配置透传给底层 API不要拦截未知参数Part 双向转换输入侧把提供者返回的文本/函数调用/媒体映射为TextPart/ToolRequestPart/MediaPart输出侧把服务端工具内容放入CustomPart系统消息适配接受role: system输入按提供者要求提取到独立字段流式语义正确增量时发增量 chunk只能给整段时设aggregated: true流式工具调用用partial标记finish reason 映射把提供者结束原因归一化到标准枚举异常结束blocked/failed/interrupted等不要继续走工具循环结构化输出原生约束按output.constrained透传否则依赖框架的模拟约束中间件。对照本文的契约表与源码路径你可以逐项核对自己的模型实现确保它能在 Genkit 的 generate action、开发者工具与多语言生态中无缝工作。【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考