Genkit 1.0 presenta muchas mejoras de funciones que mejoran la funcionalidad general. También tiene algunos cambios rotundos. Si desarrollaste aplicaciones con Genkit 0.9, debes actualizar el código de la aplicación cuando actualices a la versión más reciente de Genkit. En esta guía, se describen los cambios más significativos y se explica cómo migrar tus aplicaciones existentes sin problemas.
APIs de versión beta
Presentamos un canal de API beta inestable y dejamos las APIs de clientes de sesión, chat y Genkit en versión beta mientras seguimos perfeccionándolas. En particular, las siguientes funciones se encuentran actualmente en el espacio de nombres beta
:
ai.chat
ai.createSession
ai.loadSession
ai.currentSession
ai.defineFormat
ai.defineInterrupt
Anterior:
import { genkit } from 'genkit';
const ai = genkit({...})
const session = ai.createSession({ ... })
Nuevo:
import { genkit } from 'genkit/beta';
const ai = genkit({...})
const session = ai.createSession({ ... })
Anterior:
import { runFlow, streamFlow } from 'genkit/client';
Nuevo:
import { runFlow, streamFlow } from 'genkit/beta/client';
Presentamos el nuevo paquete @genkit-ai/express
Este nuevo paquete contiene utilidades para facilitar la compilación de un servidor Express.js con Genkit. Puedes encontrar más detalles al respecto en esta página.
startFlowServer
pasó de ser parte del objeto genkit a este nuevo paquete @genkit-ai/express
. Para usar startFlowServer, debes actualizar tus importaciones.
Anterior:
const ai = genkit({ ... });
ai.startFlowServer({
flows: [myFlow1, myFlow2],
});
Nuevo:
import { startFlowServer } from '@genkit-ai/express';
startFlowServer({
flows: [myFlow1, myFlow2],
});
Cambios en los flujos
Hay varios cambios en los flujos de la versión 1.0:
ai.defineStreamingFlow
se consolidó enai.defineFlow
.onFlow
se reemplazó poronCallGenkit
.run
se movió aai.run
.- Hay cambios en el trabajo con la autenticación.
La función run
para bloques de seguimiento personalizados se trasladó a una parte del objeto genkit
. En su lugar, usa ai.run
para invocarla.
Anterior:
ai.defineFlow({name: 'banana'}, async (input) => {
const step = await run('myCode', async () => {
return 'something'
});
})
Nuevo:
ai.defineFlow({name: 'banana'}, async (input) => {
const step = await ai.run('myCode', async () => {
return 'something'
});
})
Se quitó ai.defineStreamingFlow
. En su lugar, usa ai.defineFlow
. Además, streamingCallback
se trasladó a un campo dentro del segundo argumento de la función de flujo y ahora se llama sendChunk
.
Anterior:
const flow = ai.defineStreamingFlow({name: 'banana'}, async (input, streamingCallback) => {
streamingCallback({chunk: 1});
})
const {stream} = await flow()
for await (const chunk of stream) {
// ...
}
Nuevo:
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) {
// ...
}
La autenticación de FlowAuth ahora se llama context. Puedes acceder a la autenticación como un campo dentro del contexto:
Anterior:
ai.defineFlow({name: 'banana'}, async (input) => {
const auth = getFlowAuth();
// ...
})
Nuevo:
ai.defineFlow({name: 'banana'}, async (input, { context }) => {
const auth = context.auth;
})
onFlow
se trasladó al paquete firebase-functions/https
y se le cambió el nombre a onCallGenkit
. En el siguiente fragmento, se muestra un ejemplo de cómo usarlo.
Antiguo
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;
}
);
Nuevo:
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);
Se quitaron las políticas de autenticación de defineFlow
. El control de las políticas de autenticación ahora depende del servidor.
Anterior:
export const simpleFlow = ai.defineFlow(
{
name: 'simpleFlow',
authPolicy: (auth, input) => {
// auth policy
},
},
async (input) => {
// Flow logic here...
}
);
En el siguiente fragmento, se muestra un ejemplo de cómo controlar la autenticación en Express.
Nuevo:
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
);
Para obtener más detalles, consulta la documentación de autenticación.
En el siguiente fragmento, se muestra un ejemplo de cómo controlar la autenticación en Cloud Functions para 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);
Instrucciones
Realizamos varios cambios y mejoras en las instrucciones.
Puedes definir plantillas separadas para los mensajes del sistema y de instrucciones:
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'});
Como alternativa, puedes definir instrucciones de varios mensajes en el campo de mensajes:
const hello = ai.definePrompt({
name: 'hello',
messages: '{{ role "system" }} talk like a pirate. {{ role "user" }} hello {{ name }}',
input: {
schema: z.object({
name: z.string()
})
}
});
En lugar de plantillas de instrucciones, puedes usar una función:
ai.definePrompt({
name: 'hello',
prompt: async (input, { context }) => {
return `hello ${input.name}`
},
input: {
schema: z.object({
name: z.string()
})
}
});
Puedes acceder al contexto (incluida la información de autenticación) desde la instrucción:
const hello = ai.definePrompt({
name: 'hello',
messages: 'hello {{ @auth.email }}',
});
Las funciones de transmisión no requieren un await
.
Anterior:
const { stream, response } = await ai.generateStream(`hi`);
const { stream, output } = await myflow.stream(`hi`);
Nuevo:
const { stream, response } = ai.generateStream(`hi`);
const { stream, output } = myflow.stream(`hi`);
La incorporación tiene un nuevo tipo de datos que se muestra
Se agregó compatibilidad con las incorporaciones multimodales. En lugar de mostrar solo un vector de incorporación, Embed muestra un array de objetos de incorporación, cada uno de los cuales contiene un vector de incorporación y metadatos.
Anterior:
const response = await ai.embed({embedder, content, options}); // returns number[]
Nuevo:
const response = await ai.embed({embedder, content, options}); // returns Embedding[]
const firstEmbeddingVector = response[0].embedding; // is number[]