数据截至 (上游 commit 31370a8f9b4b)
Genkit — 架构与原理
30 秒导读: Genkit 是 Google(Firebase 团队)开源的、用来搭 AI 应用的全栈框架。它最核心的一招是:把模型、工具、提示、 流程、检索器……所有能被调用的东西,都做成同一个原语
Action——一个自描述、会校验输入输出、能被追踪、能流式返回、并由一个注册表按"/类型/名字"寻址的函数。你写的ai.generate(...)、ai.defineFlow(...)、插件里的每个模型,底下都是 Action。理解了 Action + 注册表,就理解了整个 Genkit。
1. 这是什么(零基础也能懂)
-
一句话定义: Genkit 是一套"AI 应用脚手架"——用统一的 API 接入各家大模型,帮你把提示模板、结构化输出、工具调用、多轮会话、可观测性这些活儿都标准化。
-
解决什么问题 / 给谁用: 假设你要写一个服务端功能:"用户问一句话,让 Gemini 回答,过程中模型可以自己去查天气、查数据库,最后按一个固定 JSON 结构返回"。裸调各家模型 SDK 你得自己处理:提示拼装、工具往返、把模型输出解析成类型、失败重试、还要能在本地调试看每一步。Genkit 把这些统统封好,给后端工程师用。
-
它能做什么(功能):
- 用统一接口接入 Google / OpenAI / Anthropic / Ollama 等模型(靠插件)。
- 类型安全的结构化输出(给个 Zod schema,拿回校验过的对象)。
- 工具调用 / agentic 循环:模型自己决定调哪个工具,框架自动跑完再问模型。
- Dotprompt 提示模板、多轮 Session/Chat、RAG 检索、评估器。
- 本地 Dev UI:可视化每一次执行的 trace,单独跑某个 flow / prompt。
-
用起来什么样: 最小示例(来自 README.md:15-25):
import { genkit } from 'genkit';import { googleAI } from '@genkit-ai/google-genai';const ai = genkit({ plugins: [googleAI()] }); // 建实例、装插件const { text } = await ai.generate({ // 一次生成model: googleAI.model('gemini-flash-latest'),prompt: 'What is the meaning of life?',}); -
一句话直觉 / 类比: 把 Genkit 想成 AI 版的依赖注入容器 + 中间件框架。所有"能力"(模型、工具、提示)都注册进一个中央注册表,用一个字符串 key 就能取用;所有调用都走同一条"包了追踪和校验"的管道。
2. 顶层全景(它大概怎么转)
Genkit 的骨架就三样:门面 genkit() 负责装配,注册表 Registry 负责存取,Action 是被存取的那唯一一种东西。一次 ai.generate 调用,就是从注册表里按 key 取出模型 Action 和工具 Action,喂进"工具循环"跑完。
怎么读下面这张图: 从上到下是一次调用的生命周期;记住——每个方框里流动、被查找、被执行的,都是同一种 Action。
┌───────────────────────────────────────────────────────────┐
│ genkit({ plugins:[googleAI(), ...] }) —— 门面/装配 │
│ 建注册表、把每个插件的能力注册进去、暴露 defineXxx/generate │
└───────────────────────────┬───────────────────────────────┘
│ 注册 register
▼
┌───────────────────────────────────────────────────────────┐
│ Registry 注册表 —— 按 "/类型/名字" 寻址 │
│ 存的全是同一种东西:Action │
│ /model/googleai/gemini-... /tool/getWeather │
│ /prompt/myPrompt /flow/myFlow /util/generate │
└───────┬───────────────────────────────────────────┬───────┘
ai.generate │ lookupAction("/type/name") │ listActions
▼ ▼
┌──────────────────────── ───────┐ ┌────────────────────┐
│ /util/generate 工具循环 │ │ Reflection Server │
│ 模型 →(要调工具)→ 跑工具 │ │ → 本地 Dev UI │
│ → 回填结果 → 再问模型(≤5 轮) │ │ (看 trace / 试跑) │
└───────────────────────────────┘ └────────────────────┘
部件一句话职责:
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
Action | 框架唯一原语:自描述 + Zod 校验 + 可追踪 + 可流式 + 可远程调用的函数 | js/core/src/action.ts:243 |
Registry | 按 "/type/name" 存取 Action;懒加载插件;可 overlay 出子注册表 | js/core/src/registry.ts:152 |
genkit() 门面 | 建注册表、装插件、暴露 defineFlow/defineTool/generate 等 | js/genkit/src/genkit.ts:171 |
Plugin | 把 model / tool / embedder / retriever 等注册进注册表 | js/core/src/plugin.ts:27 |
| generate 工具循环 | 模型调用 + 自动工具循环(agentic 引擎) | js/ai/src/generate/action.ts:337 |
| Tool / Interrupt | 可被模型自动调用的 Action;interrupt 停机等人工 | js/ai/src/tool.ts:336 |
| Dotprompt / 格式化器 | 提示模板渲染 + 结构化输出解析(json/array/enum…) | js/ai/src/prompt.ts:248、js/ai/src/formats/ |
| Session / Agent | 多轮会话状态与快照持久化 | js/ai/src/session.ts:152 |
| Reflection Server | 把注册表暴露成 HTTP,喂给本地 Dev UI | js/core/src/reflection.ts:73 |
主线走一遍(高层,不进代码):
genkit({ plugins })建一个Registry,把/util/generate这个内置 Action、默认输出格式、以及每个插件都注册进去(genkit.ts:configure650)。插件此时只登记、不初始化。- 你调
ai.generate({ model, prompt, tools })。框架先 overlay 出一个子注册表(放本次的临时动态工具),把模型名、工具名解析成注册表里的 Action。 - 进入"工具循环":调模型 → 若模型回了
toolRequest就跑对应工具 Action → 把结果拼回消息 → 再调模型,直到模型不再要工具,或超过maxTurns(默认 5)。 - 最后按
output里的 schema/格式把模型输出解析成类型化对象返回。 - 开发时,
Reflection Server读同一个注册表,本地 Dev UI 就能列出所有 Action、单独试跑、看每一步 trace。