从 0.9 迁移到 1.0

Genkit 1.0 引入了许多功能增强项,以改进整体功能;它还做出了一些重大变更。如果您一直在使用 Genkit 0.9 开发应用,则在升级到最新版 Genkit 时,需要更新应用代码。本指南概述了最重要的变更,并说明了如何顺利迁移现有应用。

Beta 版 API

我们将推出不稳定的 Beta 版 API 渠道,并将会话、聊天和 Genkit 客户端 API 保持 Beta 版状态,以便我们继续对其进行优化。更具体地说,以下函数目前位于 beta 命名空间中:

  • ai.chat
  • ai.createSession
  • ai.loadSession
  • ai.currentSession
  • ai.defineFormat
  • ai.defineInterrupt

旧版

import { genkit } from 'genkit';
const ai = genkit({...})
const session = ai.createSession({ ... })

新功能

import { genkit } from 'genkit/beta';
const ai = genkit({...})
const session = ai.createSession({ ... })

旧版

import { runFlow, streamFlow } from 'genkit/client';

新功能

import { runFlow, streamFlow } from 'genkit/beta/client';

引入了新的 @genkit-ai/express 软件包

这个新软件包包含一些实用程序,可让您更轻松地使用 Genkit 构建 Express.js 服务器。如需了解详情,请参阅此页面

startFlowServer 已从 genkit 对象的一部分移至这个新的 @genkit-ai/express 软件包;如需使用 startFlowServer,您必须更新导入内容。

旧版

const ai = genkit({ ... });
ai.startFlowServer({
  flows: [myFlow1, myFlow2],
});

新功能

import { startFlowServer } from '@genkit-ai/express';
startFlowServer({
  flows: [myFlow1, myFlow2],
});

对流程的更改

1.0 中的流程发生了一些变化:

  • ai.defineStreamingFlow 已合并到 ai.defineFlow
  • onFlow 已替换为 onCallGenkit
  • run 已移至 ai.run
  • 使用身份验证的方式发生了变化。

用于自定义轨迹块的 run 函数已移至 genkit 对象的一部分;请改用 ai.run 调用它。

旧版

ai.defineFlow({name: 'banana'}, async (input) => {
  const step = await run('myCode', async () => {
    return 'something'
  });
})

新功能

ai.defineFlow({name: 'banana'}, async (input) => {
  const step = await ai.run('myCode', async () => {
    return 'something'
  });
})

ai.defineStreamingFlow 已移除;请改用 ai.defineFlow。此外,streamingCallback 已移至流函数的第二个实参内的字段,现在称为 sendChunk

旧版

const flow = ai.defineStreamingFlow({name: 'banana'}, async (input, streamingCallback) => {
  streamingCallback({chunk: 1});
})

const {stream} = await flow()
for await (const chunk of stream) {
  // ...
}

新功能

const flow = ai.defineFlow({name: 'banana'}, async (input, {context, sendChunk}) => {
  sendChunk({chunk: 1});
})

const {stream, output} = flow.stream(input);
for await (const chunk of stream) {
  // ...
}

FlowAuth 身份验证现在称为上下文。您可以将 auth 作为上下文中的字段进行访问:

旧版

ai.defineFlow({name: 'banana'}, async (input) => {
  const auth = getFlowAuth();
  // ...
})

新功能

ai.defineFlow({name: 'banana'}, async (input, { context }) => {
  const auth = context.auth;
})

onFlow 已移至 firebase-functions/https 软件包,并已重命名为 onCallGenkit。以下代码段展示了一个使用方法示例。

import { onFlow } from "@genkit-ai/firebase/functions";

export const generatePoem = onFlow(
  ai,
  {
    name: "jokeTeller",
    inputSchema: z.string().nullable(),
    outputSchema: z.string(),
    streamSchema: z.string(),
  },
  async (type, streamingCallback) => {
    const { stream, response } = await ai.generateStream(
      `Tell me a longish ${type ?? "dad"} joke.`
    );
    for await (const chunk of stream) {
      streamingCallback(chunk.text);
    }
    return (await response).text;
  }
);

新功能

import { onCallGenkit } from "firebase-functions/https";
import { defineSecret } from "firebase-functions/params";
import { genkit, z } from "genkit";

const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
});

export const jokeTeller = ai.defineFlow(
  {
    name: "jokeTeller",
    inputSchema: z.string().nullable(),
    outputSchema: z.string(),
    streamSchema: z.string(),
  },
  async (type, { sendChunk }) => {
    const { stream, response } = ai.generateStream(
      `Tell me a longish ${type ?? "dad"} joke.`
    );
    for await (const chunk of stream) {
      sendChunk(chunk.text);
    }
    return (await response).text;
  }
);

export const tellJoke = onCallGenkit({ secrets: [apiKey] }, jokeTeller);

defineFlow 已移除身份验证政策。现在,对身份验证政策的处理取决于服务器。

旧版

export const simpleFlow = ai.defineFlow(
  {
    name: 'simpleFlow',
    authPolicy: (auth, input) => {
      // auth policy
    },
  },
  async (input) => {
    // Flow logic here...
  }
);

以下代码段展示了在 Express 中处理身份验证的示例。

新功能

import { UserFacingError } from 'genkit';
import { ContextProvider, RequestData } from 'genkit/context';
import { expressHandler, startFlowServer } from '@genkit-ai/express';

const context: ContextProvider<Context> = (req: RequestData) => {
  return {
    auth: parseAuthToken(req.headers['authorization']),
  };
};

export const simpleFlow = ai.defineFlow(
  {
    name: 'simpleFlow',
  },
  async (input, { context }) => {
    if (!context.auth) {
      throw new UserFacingError("UNAUTHORIZED", "Authorization required.");
    }
    if (input.uid !== context.auth.uid) {
      throw new UserFacingError("UNAUTHORIZED", "You may only summarize your own profile data.");
    }
    // Flow logic here...
  }
);

const app = express();
app.use(express.json());
app.post(
  '/simpleFlow',
  expressHandler(simpleFlow, { context })
);
app.listen(8080);

// or

startFlowServer(
  flows: [withContextProvider(simpleFlow, context)],
  port: 8080
);

如需了解详情,请参阅身份验证文档

以下代码段展示了在 Cloud Functions for Firebase 中处理身份验证的示例:

import { genkit } from 'genkit';
import { onCallGenkit } from 'firebase-functions/https';

const ai = genkit({ ... });;

const simpleFlow = ai.defineFlow({
  name: 'simpleFlow',
}, async (input) => {
  // Flow logic here...
});

export const selfSummary = onCallGenkit({
  authPolicy: (auth, data) => auth?.token?.['email_verified'] && auth?.token?.['admin'],
}, simpleFlow);

提示

我们对提示做出了一些更改和改进。

您可以为提示和系统消息分别定义模板:

const hello = ai.definePrompt({
  name: 'hello',
  system: 'talk like a pirate.',
  prompt: 'hello {{ name }}',
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});
const { text } = await hello({name: 'Genkit'});

或者,您也可以在 messages 字段中定义多条消息提示:

const hello = ai.definePrompt({
  name: 'hello',
  messages: '{{ role "system" }} talk like a pirate. {{ role "user" }} hello {{ name }}',
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});

您可以使用函数,而不是提示模板:

ai.definePrompt({
  name: 'hello',
  prompt: async (input, { context }) => {
    return `hello ${input.name}`
  },
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});

您可以在提示中访问上下文(包括身份验证信息):

const hello = ai.definePrompt({
  name: 'hello',
  messages: 'hello {{ @auth.email }}',
});

流式传输函数不需要 await

旧版

const { stream, response } = await ai.generateStream(`hi`);
const { stream, output } = await myflow.stream(`hi`);

新功能

const { stream, response } = ai.generateStream(`hi`);
const { stream, output } = myflow.stream(`hi`);

嵌入有新的返回类型

我们添加了对多模态嵌入的支持。Embed 会返回一个嵌入对象数组,而不是仅返回一个嵌入矢量,每个嵌入对象都包含一个嵌入矢量和元数据。

旧版

const response = await ai.embed({embedder, content, options});  // returns number[]

新功能

const response = await ai.embed({embedder, content, options}); // returns Embedding[]
const firstEmbeddingVector = response[0].embedding;  // is number[]