Manejadores de transformación de LLM

Cada proveedor tiene su propio formato para las cargas útiles de solicitud, respuesta y error. Debido a esto, el proveedor de LLM y Oracle Digital Assistant no se pueden comunicar directamente, por lo que para facilitar el intercambio entre la aptitud y sus proveedores de LLM, debe transformar estas cargas útiles en la interfaz común de LLM de Oracle Digital Assistant y volver de nuevo.

Esta transformación se activa mediante la creación de un manejador de transformación de LLM, un script cuyos métodos transformRequestPayload, transformResponsePayload y transformErrorResponsePayload ejecutan las transformaciones de carga útil. Estos métodos de transformación tienen dos firmas:
  • event: las propiedades utilizadas para este objeto dependen del tipo de evento (transformRequestPayload, transformResponsePayload, transformErrorResponsePayload).
  • context: hace referencia a la clase LlmTransformationContext, que proporciona acceso a los métodos de comodidad que puede utilizar para crear la lógica del manejador de eventos.

Creación de un manejador de transformación de LLM

Para crear un manejador de eventos de transformación de LLM:
  1. Haga clic en Componentes en la barra de navegación izquierda.
  2. Haga clic en Servicio +New.
  3. Complete el cuadro de diálogo Crear servicio:
    • Nombre: introduzca el nombre del servicio.
    • Tipo de servicio: contenedor embebido
    • Tipo de paquete de servicios de componente: Nuevo componente
    • Tipo de componente: transformación de LM
    • Nombre de componente: introduzca un nombre fácilmente identificable para el manejador de eventos de entidad. Hará referencia a este nombre al crear el servicio de LLM para la aptitud.
    • Plantilla: proporcionamos plantillas para las aptitudes que llaman a Cohere directamente o mediante el servicio de IA generativa de Oracle. No es necesario que edite estas plantillas. Si la aptitud llama a un modelo de IA generativa que no sea Cohere/Oracle, como Azure Open AI, deberá agregar el código adecuado.

      Las plantillas para Oracle Generative AI Cohere (generación y resumen de texto) y Llama (resumen de texto) se ordenan en Generative AI en el menú de lista Template (Plantilla). La plantilla para acceder a Cohere directamente se encuentra en Otros. Para acceder a la plantilla que contiene el código de inicio para otros modelos, seleccione Personalizado (que también se encuentra en Otro).

  4. Haga clic en Crear para generar el código de manejador de eventos.
  5. Una vez completado el despliegue, amplíe el servicio y, a continuación, seleccione el manejador de transformación para abrir su página de propiedades, que muestra los tres métodos de transformación de LLM provider-CLMI (transformRequestPayload, transformResponsePayload y transformErrorResponsePayload).

    Si está creando un servicio Cohere o un servicio de IA generativa de Oracle alojado en el mismo arrendamiento que su instancia de Digital Assistant, el código de manejador está completo.

  6. Si está creando un servicio de IA generativa de Oracle alojado en un arrendamiento de OCI diferente, haga clic en Editar para abrir el cuadro de diálogo Editar componente y sustituir la variable event.compartmentId por el ID de compartimento del arrendamiento de OCI en el que está suscrito el servicio de IA generativa.
  7. Si utiliza la plantilla personalizada, haga clic en Editar para abrir el cuadro de diálogo Editar componente y, a continuación, actualice el siguiente código de marcador de posición con el código específico del proveedor:
    Método Ubicación en el editor (plantilla personalizada) Código de marcador de posición (plantilla personalizada)
    transformRequestPayload Líneas 23-25
    transformRequestPayload: async (event, context) => {
          return event.payload;
        },
    transformResponsePayload Líneas 33-35
        transformResponsePayload: async (event, context) => {
          return event.payload;
        },
    transformErrorResponsePayload Líneas 44-46
        transformErrorResponsePayload: async (event, context) => {
          return event.payload;
        }
  8. Verifique el sytnax de las actualizaciones haciendo clic en Validar. Corrija los errores de validación (si los hay) y, a continuación, haga clic en Guardar. A continuación, haga clic en Cerrar.

Ejemplos de código de transformación de proveedor de LLM

Azure OpenAI

Método Código de transformación de manejador de eventos
Solicitud
transformRequestPayload: async (event, context) => {
  let payload = { "model": "gpt-4-0314",
                    "messages": event.payload.messages.map(m => { return {"role": m.role, "content": m.content}; }),                     "max_tokens": event.payload.maxTokens,
                    "temperature": event.payload.temperature,
                    "stream": event.payload.streamResponse
                  };
  return payload;
},
Respuesta (no de transmisión)
transformResponsePayload: async (event, context) => {
     let llmPayload = {};      
     if (event.payload.responseItems) {
       // streaming case
       llmPayload.responseItems = [];
       event.payload.responseItems
           .filter(item => item.choices.length > 0)
           .forEach(item => {
         llmPayload.responseItems.push({"candidates": item.choices.map( c => {return {"content": c.delta.content || "" };})});
       });
     } else {
        // non-streaming case
        llmPayload.candidates = event.payload.choices.map( c => {return {"content": c.message.content || "" };});
     } 
     return llmPayload;
   }
Cuando el flujo está activado, se llama al manejador de eventos de transformación de respuesta en lotes de 20 mensajes de flujo. Esta matriz por lotes de respuestas de flujo se almacena en la clave responseItems.
Error
transformErrorResponsePayload: async (event, context) => {
  let errorCode = 'unknown';
  if (event.payload.error) {
    if ( 'context_length_exceeded' === event.payload.error.code) {
      errorCode = 'modelLengthExceeded';
    }  else if ('content_filter' === event.payload.error.code) {
      errorCode = 'flagged'; 
    } 
    return {"errorCode" : errorCode, "errorMessage": event.payload.error.message};
  } else {
    return {"errorCode" : errorCode, "errorMessage": JSON.stringify(event.payload)};
  }   
}

Servicio de IA generativa de Oracle - Cohere

Nota

Los modelos de comandos se han retirado. Le recomendamos que migre al punto final /chat, que implica declarar un modelo de chat más reciente y sustituir los parámetros específicos del comando por parámetros específicos del chat.
Método Código de manejador de eventos
Solicitud
transformRequestPayload: async (event, context) => {
      // Cohere doesn't support chat completions, so we first print the system prompt, and if there
      // are additional chat entries, we add these to the system prompt under the heading CONVERSATION HISTORY
      let prompt = event.payload.messages[0].content;
      if (event.payload.messages.length > 1) {
         let history = event.payload.messages.slice(1).reduce((acc, cur) => `${acc}\n${cur.role}: ${cur.content}` , '');
         prompt += `\n\nCONVERSATION HISTORY:${history}\nassistant:`
      }
      // using Cohere
      let modelId = "cohere.command"
      let runtimeType = "COHERE";
       return {
        "compartmentId": event.compartmentId,
        "servingMode": {
          "servingType": "ON_DEMAND",
            "modelId": modelId
        },
        "inferenceRequest": {
          "runtimeType": runtimeType,
          "prompt": prompt,
          "isStream": event.payload.streamResponse,
          "maxTokens": event.payload.maxTokens,
          "temperature": event.payload.temperature,
          // parameters set to default values
          "frequencyPenalty": 0,
          "isEcho": false,
          "numGenerations": 1,
          "presencePenalty": 0,
          "returnLikelihoods": "NONE",
          "topK": 0,
          "topP": 0.75,
          "truncate": "NONE"
        }
      };
}
Respuesta
transformResponsePayload: async (event, context) => {      
    let llmPayload = {};
    if (event.payload.responseItems) {
        // streaming case
        llmPayload.responseItems = [];
        event.payload.responseItems.forEach(item => {
          llmPayload.responseItems.push({"candidates": [{"content": item.text || "" }]});
        });
      } else {
        // non-streaming
        llmPayload.candidates = event.payload.inferenceResponse.generatedTexts.map( item => {return {"content": item.text || "" };});
      }
      return llmPayload;
 }
Error
transformErrorResponsePayload: async (event, context) => {      
      const error = event.payload.message || 'unknown error';
      if (error.startsWith('invalid request: total number of tokens')) {
        // returning modelLengthExceeded error code will cause a retry with reduced chat history
        return {"errorCode" : "modelLengthExceeded", "errorMessage": error};
      } else {
        return {"errorCode" : "unknown", "errorMessage": error};
      }
}

IA Generativa de Oracle - Llama

Nota

Los modelos de comandos se han retirado. Recomendamos que migre al punto final /chat, lo que implica declarar el modelo de chat y sustituir los parámetros específicos del comando por parámetros específicos del chat.
Método Código de manejador de eventos
Solicitud
transformRequestPayload: async (event, context) => {
      // Cohere doesn't support chat completions, so we first print the system prompt, and if there
      // are additional chat entries, we add these to the system prompt under the heading CONVERSATION HISTORY
      let prompt = event.payload.messages[0].content;
      if (event.payload.messages.length > 1) {
         let history = event.payload.messages.slice(1).reduce((acc, cur) => `${acc}\n${cur.role}: ${cur.content}` , '');
         prompt += `\n\nCONVERSATION HISTORY:${history}\nassistant:`
      }
      // using Llama
      let modelId = "meta.llama-2-70b-chat"
      let runtimeType = "LLAMA";
       return {
        "compartmentId": event.compartmentId,
        "servingMode": {
          "servingType": "ON_DEMAND",
            "modelId": modelId
        },
        "inferenceRequest": {
          "runtimeType": runtimeType,
          "prompt": prompt,
          "isStream": event.payload.streamResponse,
          "maxTokens": event.payload.maxTokens,
          "temperature": event.payload.temperature,
          // parameters set to default values
          "frequencyPenalty": 0,
          "isEcho": false,
          "numGenerations": 1,
          "presencePenalty": 0,
          "returnLikelihoods": "NONE",
          "topK": 0,
          "topP": 0.75,
          "truncate": "NONE"
        }
      };
}
Respuesta
transformResponsePayload: async (event, context) => {      
    let llmPayload = {};
    if (event.payload.responseItems) {
        // streaming case
        llmPayload.responseItems = [];
        event.payload.responseItems.forEach(item => {
          llmPayload.responseItems.push({"candidates": [{"content": item.text || "" }]});
        });
      } else {
        // non-streaming
        llmPayload.candidates = event.payload.inferenceResponse.choices.map( item => {return {"content": item.text || "" };});
      }
      return llmPayload;
 }
Error
transformErrorResponsePayload: async (event, context) => {      
      const error = event.payload.message || 'unknown error';
      if (error.startsWith('invalid request: total number of tokens')) {
        // returning modelLengthExceeded error code will cause a retry with reduced chat history
        return {"errorCode" : "modelLengthExceeded", "errorMessage": error};
      } else {
        return {"errorCode" : "unknown", "errorMessage": error};
      }
}

IA generativa de Oracle: resumen

Nota

Los modelos de comandos se han retirado. Le recomendamos que migre al punto final /chat, que implica declarar un modelo de chat más reciente y sustituir los parámetros específicos del comando por parámetros específicos del chat.
Método Código de manejador de eventos
Solicitud
transformRequestPayload: async (event, context) => {
      // Cohere doesn't support chat completions, so we first print the system prompt, and if there
      // are additional chat entries, we add these to the system prompt under the heading CONVERSATION HISTORY
      let prompt = event.payload.messages[0].content;
      if (event.payload.messages.length > 1) {
         let history = event.payload.messages.slice(1).reduce((acc, cur) => `${acc}\n${cur.role}: ${cur.content}` , '');
         prompt += `\n\nCONVERSATION HISTORY:${history}\nassistant:`
      }
      let modelId = "cohere.command"
      return {
        "compartmentId": event.compartmentId,
        "servingMode": {
          "servingType": "ON_DEMAND",
          "modelId": modelId
        },
        "input" : prompt,
        "temperature": event.payload.temperature,
        // parameters set to default values
        "length": "AUTO",
        "extractiveness": "AUTO",
        "format": "PARAGRAPH",
        // natural language instructions
        "additionalCommand": "write in a conversational style"
      };
}
Respuesta
transformResponsePayload: async (event, context) => {
      let llmPayload = {};
      // non-streaming only: streaming is not supported
      llmPayload.candidates = [{"content": event.payload.summary}];
      return llmPayload;
}
Error
transformErrorResponsePayload: async (event, context) => {             const error = event.payload.message ||
          'unknown error';      if(error.startsWith('invalid request:
          total number of tokens')) {        // returning modelLengthExceeded error
          code will cause a retry with reduced chat history        return{"errorCode": "modelLengthExceeded", "errorMessage": error};      }
          else{        return{"errorCode": "unknown", "errorMessage": error};      }}

Cohere (modelo de comando) - Acceso directo a Cohere

Los manejadores de este código de transformación soportan la API /generate y el modelo Cohere.command asociado, no la API /chat que se utiliza para el modelo cohere.command.R. Si migra al punto final /chat, deberá actualizar manualmente las cargas útiles de solicitud y respuesta y la plantilla de código generada.
Método Código de manejador de eventos
Solicitud
transformRequestPayload: async (event, context) => {            
      // Cohere doesn't support chat completions, so we first print the system prompt, and if there
      // are additional chat entries, we add these to the system prompt under the heading CONVERSATION HISTORY
      let prompt = event.payload.messages[0].content;
      if (event.payload.messages.length > 1) {
         let history = event.payload.messages.slice(1).reduce((acc, cur) => `${acc}\n${cur.role}: ${cur.content}` , '');
         prompt += `\n\nCONVERSATION HISTORY:${history}\nassistant:`
      }
      return {
        "max_tokens": event.payload.maxTokens,
        "truncate": "END",
        "return_likelihoods": "NONE",
        "prompt": prompt,
        "model": "command",
        "temperature": event.payload.temperature,
        "stream": event.payload.streamResponse
      };
 }
Este manejador gestiona el historial de conversaciones para mantener el contexto de la conversación.
Respuesta
transformResponsePayload: async (event, context) => {
  let llmPayload = {};      
  if (event.payload.responseItems) {
        // streaming case
        llmPayload.responseItems = [];
        event.payload.responseItems.forEach(item => {
          llmPayload.responseItems.push({"candidates": [{"content": item.text || "" }]});
        });
      } else {
        // non-streaming
        llmPayload.candidates = event.payload.generations.map( item => {return {"content": item.text || "" };});
      }
   return llmPayload;
}
Error
transformErrorResponsePayload: async (event, context) => {      
    // NOTE: Depending on the Cohere version, this code might need to be updated
      const error = event.payload.message || 'unknown error';
      if (error.startsWith('invalid request: total number of tokens')) {
        // returning modelLengthExceeded error code will cause a retry with reduced chat history
        return {"errorCode" : "modelLengthExceeded", "errorMessage": error};
      } else {
        return {"errorCode" : "unknown", "errorMessage": error};
      }
 
}

Interfaz LLM común

Cada proveedor de LLM tiene su propio formato para sus cargas útiles de solicitud y respuesta. La interfaz de LLM común, o CLMI, permite al componente invokeLLM manejar estas cargas útiles de solicitud y respuesta propietarias.

El CMLI consta de los siguientes elementos:
  • Especificación de cuerpo de solicitud.
  • Especificación de cuerpo de respuesta correcta, aplicable cuando la llamada REST de LLM devuelve un estado HTTP 200.
  • Especificación de cuerpo de respuesta de error, aplicable cuando la llamada REST de LLM devuelve un estado HTTP distinto de 200, pero la llamada del servicio de LLM aún se ha realizado correctamente.
    Nota

    Para llamadas incorrectas, el componente invokeLLM maneja los errores 401 (no autorizado) o 500 (error interno del servidor).

Especificación de cuerpo de solicitud de CLMI

El cuerpo de la solicitud de JSON CLMI contiene las siguientes propiedades:
Propiedad Tipo Valor por Defecto Descripción ¿Obligatoria?
messages Matriz de objetos de mensajes N/D Una lista de mensajes. El primer mensaje es el indicador con la propiedad role establecida en system. Si el LLM soporta una conversación de varios giros para que la respuesta del LLM se pueda acotar o mejorar, los mensajes posteriores serán pares de mensajes de los roles user y assistant. El mensaje de usuario contiene las instrucciones de seguimiento o la pregunta para el LLM. El mensaje del asistente contiene la respuesta del LLM al mensaje del usuario (la finalización). Si el LLM no admite conversaciones de varias vueltas, la matriz messages solo contendrá un único mensaje del sistema que contenga la petición de datos.
streamResponse booleano false Determina si la respuesta del LLM se devolverá al componente del LLM. La definición de esta propiedad en true mejora la experiencia del usuario, ya que el flujo permite al componente de LLM enviar mensajes de respuesta parcial a los usuarios para que no tengan que esperar a que el LLM complete la respuesta.

Defina streamResponse en false cuando se utilice la validación de respuesta. Debido a que todo el mensaje es necesario para que se pueda realizar la validación, el mensaje se puede presentar para los usuarios varias veces: primero se transmite, luego se valida y, luego, se vuelve a transmitir.

No
maxTokens entero 1024 El modelo genera tokens para las palabras en sus resultados. Los tokens se pueden considerar como piezas de palabras. 100 tokens equivalen a aproximadamente 75 palabras en inglés, por ejemplo. Esta propiedad limita el tamaño del contenido generado por el modelo definiendo el número máximo de tokens que genera para la respuesta. No
temperature número 0 El modelo utiliza la temperatura para medir la aleatoriedad y, por lo tanto, la creatividad de sus respuestas. Esto se define como un valor que va de 0 (resultados predecibles) a 1 (resultados más aleatorios). 0 significa que el modelo enviará los mismos resultados a una petición de datos determinada. 1 significa que los resultados del modelo a una respuesta dada pueden variar enormemente. Utilice un gestor de eventos para aplicar un multiplicador si el proveedor de LLM soporta un rango distinto de 0-1. No
user Cadena N/D Identificador único que representa al usuario final, que se puede utilizar para supervisar y detectar el lenguaje abusivo. No
providerExtension Objeto N/D Activa las opciones de configuración específicas del proveedor de LLM que no están definidas como parte de CLMI. No

Estructura de Objeto de Mensaje

Propiedad Tipo Descripción ¿Obligatoria?
role Cadena Creador del mensaje. Los valores son system, user y assistant.
content Cadena Contenido del mensaje
turn entero Número que indica el giro de acotación actual del intercambio de mensajes de chat. Cuando la primera petición de datos se envía al LLM, el turno es 1.
retry booleano Indicador que indica si el mensaje se envía al LLM para corregir un error en la respuesta No (el valor por defecto es false)
tag Cadena Etiqueta personalizada que marca una petición de datos específica. Si está mejorando la respuesta del LLM mediante Crítica y mejora recursivas (RCI), puede activar la lógica personalizada del manejador validateResponsePayload para detectar el paso actual del proceso de RCI definiendo la etiqueta en "criticize" o "improve". No

Especificación de cuerpo de respuesta correcta

Propiedad Tipo Descripción ¿Obligatoria?
candidates Matriz de objetos candidate Lista de mensajes candidatos devueltos por el LLM

Objetos candidatos

El cuerpo de la solicitud de JSON CLMI contiene las siguientes propiedades:
Propiedad Tipo Descripción ¿Obligatoria?
content Cadena Contenido del mensaje

Especificación de cuerpo de respuesta de error

El cuerpo de respuesta de error de JSON CLMI contiene las siguientes propiedades:
Propiedad Tipo Descripción ¿Obligatoria?
errorCode Cadena
  • notAuthorized: indica que la solicitud de LLM no tiene la clave de autorización adecuada.
  • modelLengthExceeded: indica que la combinación de mensajes de solicitud (la petición de datos del sistema junto con los mensajes de acotación de usuario y asistente) y el número máximo de tokens supera el límite de tokens del modelo.
  • requestFlagged: indica que el LLM no puede cumplir la solicitud porque infringe las políticas de moderación del proveedor de LLM. Por ejemplo, se marcarían las solicitudes que contengan contenido racista o sexualmente abusivo.
  • responseFlagged: indica que la respuesta de LLM viola las políticas de moderación del proveedor de LLM. Por ejemplo, se marcarían las respuestas que contengan contenido tóxico, como lenguaje racista o sexualmente abusivo.
  • requestInvalid: indica que la solicitud al LLM no es válida. Por ejemplo, la solicitud no es válida porque falló algunas de las reglas de validación establecidas en un manejador de eventos o está en un formato que el LLM no reconoce.
  • responseInvalid: indica que la respuesta generada por el LLM no es válida. Por ejemplo, la respuesta no es válida porque ha fallado algunas de las reglas de validación definidas en un gestor de eventos de validación.
  • unknown: cuando se producen otros errores.
errorMessage Cadena Mensaje de error específico del proveedor de LLM. Puede ser un objeto JSON de cadena.