Cómo escribir un complemento de modelo de Genkit

Los complementos de modelos de Genkit agregan uno o más modelos de IA generativa al registro de Genkit. Un modelo representa cualquier modelo generativo capaz de recibir instrucciones como entradas y generar texto, contenido multimedia o datos como resultados.

Antes de comenzar

Lee Cómo escribir complementos de Genkit para obtener información sobre cómo escribir cualquier tipo de complemento de Genkit, incluidos los complementos de modelos. En particular, ten en cuenta que cada complemento debe exportar una función Init, a la que se espera que los usuarios llamen antes de usar el complemento.

Definiciones de modelo

Por lo general, un complemento de modelo realizará una o más llamadas ai.DefineModel en su función Init: una vez para cada modelo para el que el complemento proporciona una interfaz.

Una definición de modelo consta de tres componentes:

  1. Metadatos que declaran las capacidades del modelo.
  2. Un tipo de configuración con cualquier parámetro específico que el modelo admita.
  3. Una función de generación que acepte una ai.GenerateRequest y devuelva una ai.GenerateResponse, presuntamente usando un modelo de IA para generar esta última.

En términos generales, así se ve en el código:

type MyModelConfig struct {
	ai.GenerationCommonConfig
	CustomOption int
	AnotherCustomOption string
}
ai.DefineModel(
	providerID, "my-model",
	&ai.ModelMetadata{
		Label: "my-model",
		Supports: ai.ModelCapabilities{
			Multiturn:  true,  // Does the model support multi-turn chats?
			SystemRole: true,  // Does the model support syatem messages?
			Media:      false, // Can the model accept media input?
			Tools:      false, // Does the model support function calling (tools)?
		},
	},
	func(ctx context.Context,
		genRequest *ai.GenerateRequest,
		_ ai.ModelStreamingCallback,
	) (*ai.GenerateResponse, error) {
		// Verify that the request includes a configuration that conforms to
		// your schema .
		if _, ok := genRequest.Config.(MyModelConfig); !ok {
			return nil, fmt.Errorf("request config must be type MyModelConfig")
		}

		// Use your custom logic to convert Genkit's ai.GenerateRequest
		// into a form usable by the model's native API.
		apiRequest, err := apiRequestFromGenkitRequest(genRequest)
		if err != nil {
			return nil, err
		}

		// Send the request to the model API, using your own code or the
		// model API's client library.
		apiResponse, err := callModelAPI(apiRequest)
		if err != nil {
			return nil, err
		}

		// Use your custom logic to convert the model's response to Genkin's
		// ai.GenerateResponse.
		response, err := genResponseFromAPIResponse(apiResponse)
		if err != nil {
			return nil, err
		}

		return response, nil
	},
)

Cómo declarar las capacidades del modelo

Cada definición de modelo debe contener, como parte de sus metadatos, un valor de ai.ModelCapabilities que declara qué atributos admite el modelo. Genkit usa esta información para determinar ciertos comportamientos, como verificar si ciertas entradas son válidas para el modelo. Por ejemplo, si el modelo no admite interacciones de varios turnos, entonces es un error pasarle un historial de mensajes.

Ten en cuenta que estas declaraciones hacen referencia a las capacidades del modelo como las proporciona el complemento y no se asocian, necesariamente, uno a uno con las capacidades del modelo subyacente y la API del modelo. Por ejemplo, incluso si la API del modelo no proporciona una forma específica de definir los mensajes del sistema, es posible que tu complemento igual declare la compatibilidad con el rol del sistema y lo implemente como una lógica especial que inserta mensajes del sistema en la instrucción del usuario.

Cómo definir el esquema de configuración de tu modelo

Para especificar las opciones de generación que admite un modelo, define y exporta un tipo de configuración. Genkit tiene un tipo ai.GenerationCommonConfig que contiene opciones que los servicios de modelos de IA generativa suelen admitir, que puedes incorporar o utilizar directamente.

La función de generación debe verificar que la solicitud contenga el tipo de opciones correcto.

Cómo transformar solicitudes y respuestas

La función de generación realiza el trabajo principal de un complemento de modelo Genkit: transformar la ai.GenerateRequest del formato común de Genkit en un formato compatible con la API de tu modelo y, luego, transformar la respuesta de tu modelo al formato ai.GenerateResponse que usa Genkit.

A veces, esto puede requerir reorganizar o manipular datos para evitar las limitaciones del modelo. Por ejemplo, si tu modelo no admite de forma nativa un mensaje system, quizás debas transformar el mensaje de sistema de una instrucción en un par de mensajes usuario-modelo.

Exportaciones

Además de los recursos que todos los complementos deben exportar, una función Init y un tipo de Config, un complemento de modelo también debe exportar lo siguiente:

  • Un tipo de configuración de generación, como se explicó antes.

  • Una función Model, que devuelve referencias a los modelos definidos de tu complemento. A menudo, esto puede ser simplemente:

    func Model(name string) *ai.Model {
        return ai.LookupModel(providerID, name)
    }
    
  • Opcional: Una función DefineModel, que permite a los usuarios definir modelos que puede proporcionar tu complemento, pero que tú no defines automáticamente. Existen dos razones principales por las que podrías querer proporcionar esta función:

    • Tu complemento proporciona acceso a demasiados modelos para que se registre cada uno de manera práctica. Por ejemplo, el complemento Ollama puede brindar acceso a decenas de modelos diferentes, y se agregan más con frecuencia. Por este motivo, no define automáticamente ningún modelo y, en cambio, requiere que el usuario llame a DefineModel para cada modelo que desea usar.

    • Para dar a tus usuarios la posibilidad de usar modelos nuevos que aún no hayas agregado a tu complemento.

    Por lo general, la función DefineModel de un complemento es un frontend para ai.DefineModel que define una función de generación, pero permite que el usuario especifique el nombre y las capacidades del modelo.