Migrar para os Modelos de Chat

Os modelos cohere.command, cohere.command-light, meta.llama-2-70b-chat que são usados pelos pontos finais do OCI (Oracle Cloud Infrastructure) Generative AI /generateText e /summarizeText agora obsoletos foram retirados. Você só pode continuar usando esses modelos por meio de um cluster de IA dedicado, que usa o modo de serviço dedicado. No entanto, recomendamos que você continue com o modo de serviço sob demanda usando o ponto final /chat com os (novos) modelos de chat. Veja um exemplo deste ponto final:
https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/chat
Para migrar para esses modelos, você pode criar um novo Serviço LLM ou modificar o existente usando o ponto final /chat que tem como alvo um dos modelos posteriores, como cohere.command-r-08-2024 ou meta.llama-3.2-90b-vision-instruct. Veja um exemplo de um corpo de solicitação atualizado para cohere.command-r-08-2024:
{
   "compartmentId": "ocid1.tenancy.oc1..XXXXXXX",
   "servingMode": {
       "servingType": "ON_DEMAND",
       "modelId": "cohere.command-r-08-2024"
   },
   "chatRequest": {
       "apiFormat": "COHERE",
       "message": "what you want to ask goes here …",
       "maxTokens": 1000,
       "isStream": true,
       "frequencyPenalty": 0,
       "topP": 0.75,
       "temperature": 1
   }
}
Este é um exemplo de corpo de solicitação para meta.llama-3.2-90b-vision-instruct:
{

    "compartmentId": "ocid1.tenancy.oc1..XXXXXXX",
    "servingMode": {
        "servingType": "ON_DEMAND",
        "modelId": "meta.llama-3.2-90b-vision-instruct"
    },

    "chatRequest": {
        "messages": [
            {
                "role": "USER",
                "content": [
                    {
                        "type": "TEXT",
                        "text": "what you want to ask goes here …"
                    }
                ]
            }
        ],
        "apiFormat": "GENERIC",
        "maxTokens": 600,
        "isStream": false,
        "numGenerations": 1,
        "frequencyPenalty": 0,
        "presencePenalty": 0
  }
}
Além disso, você também precisará atualizar manualmente o código do processador gerado com base nos modelos de transformação específicos da IA Generativa para declarar o novo modelo de chat. Para cohere.command-r-08-2024, a declaração tem a seguinte aparência:
let modelId = "cohere.command-r-08-2024"
let apiFormat = "COHERE";
Para meta.llama-3.2-90b-vision-instruct (ou outros modelos não-Cohere), a declaração do modelo é a seguinte. Observe que o valor definido para a declaração da variável apiFormat é GENERIC, que é usado para modelos não-Cohere.
let modelId = "meta.llama-3.2-90b-vision-instruct"
let apiFormat = "GENERIC";
O código do handler também precisará incluir parâmetros específicos do chat (o parâmetro message que substitui o parâmetro prompt, por exemplo).
Observação

Se você continuar com os modelos de Comando, que estão retirados, além de criar o cluster de IA dedicado, precisará alterar o parâmetro servingType no payload de solicitação e no código do handler transformRequestPayload do modelo de IA generativa de ON_DEMAND para DEDICATED.
"servingMode": {
        "modelId": "cohere.command,
        "servingType": "DEDICATED"
    },
Para outros modelos, como meta.llama-3.2-90b-vision-instruct, defina servingType no payload de solicitação e no handler transformRequestPayload como ON_DEMAND:
 "servingMode": {
        "servingType": "ON_DEMAND",
        "modelId": "meta.llama-3.2-90b-vision-instruct"
    },
Por fim, as funções de código do handler precisarão ser modificadas para suportar os payloads atualizados; O caso de streaming para o event.payload.responseItems (items) deve incluir o atributo finishReason que impede uma mensagem duplicada no array de resposta. Aqui está o atributo finishReason, o código do handler atualizado para a Cohere.
       if (item.text) {
            let finshReasonVar = item.finishReason;
            if (finshReasonVar != 'COMPLETE') {
              // check for only the stream items and not the 'complete' message (e.g. the last message returned by the API)
              llmPayload.responseItems.push({ "candidates": [{ "content" : item.text || "" }] });
            }
          }        
Aqui está a definição de atributo no código de modelo Llama atualizado:
       let finshReasonVar = item.finishReason;
          if (finshReasonVar != 'stop') {
              let msgcontent = item.message.content[0];
              let text = msgcontent.text;
              if (text !== "") {
                llmPayload.responseItems.push({ "candidates": [{ "content" : text || "" }] })
Observação

Não é necessário atualizar o código do modelo para o caso não de streaming. Nos trechos de código a seguir, o "isStream": streamResVar é definido pela propriedade Usar Streaming do componente invokeLLM.
Veja um exemplo do código do handler modificado para cohere.command-r-08-2024:
/**
    * Handler to transform the request payload
    * @param {TransformPayloadEvent} event - event object contains the following properties:
    * - payload: the request payload object
    * @param {LlmTransformationContext} context - see https://oracle.github.io/bots-node-sdk/LlmTransformationContext.html
    * @returns {object} the transformed request payload
    */
    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;
      let streamResVar = event.payload.streamResponse;
      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 new OCI gen-ai /chat endpoint
      let modelId = "cohere.command-r-08-2024"
      let apiFormat = "COHERE";
      return {
        "compartmentId": event.compartmentId,
        "servingMode": {
          "servingType": "ON_DEMAND",
          "modelId": modelId
        },

        "chatRequest": {
          "apiFormat": apiFormat,
          "message": prompt,
          "maxTokens": 4000,
          "isStream": streamResVar,
          "frequencyPenalty": 0,
          "topP": 0.75,
          "temperature": 0
        }
      };
    },

    /**
    * Handler to transform the response payload
    * @param {TransformPayloadEvent} event - event object contains the following properties:
    * - payload: the response payload object
    * @param {LlmTransformationContext} context - see https://oracle.github.io/bots-node-sdk/LlmTransformationContext.html
    * @returns {object} the transformed response payload
    */

    transformResponsePayload: async (event, context) => {
      let llmPayload = {};
      if (event.payload.responseItems) {
        // streaming case		
        llmPayload.responseItems = [];
        event.payload.responseItems.forEach(item => {
          // only grab the text items, since last item in the responseItems[] is the finished reason not part of the sentence

if (item.text) {

            let finshReasonVar = item.finishReason;
            if (finshReasonVar != 'COMPLETE') {
              // check for only the stream items and not the 'complete' message (e.g., the last message returned by the API)
              llmPayload.responseItems.push({ "candidates": [{ "content" : item.text || "" }] });
            }
          } 
       });
      } else {
        llmPayload.candidates = [{ "content" : event.payload.chatResponse.text || "" }];
      }
     return llmPayload;
    },
Veja um exemplo do código do handler para meta.llama-3.2-90b-vision-instruct:
    /**
    * Handler to transform the request payload
    * @param {TransformPayloadEvent} event - event object contains the following properties:
    * - payload: the request payload object
    * @param {LlmTransformationContext} context - see https://oracle.github.io/bots-node-sdk/LlmTransformationContext.html
    * @returns {object} the transformed request payload
    */

    transformRequestPayload: async (event, context) => {
      // are additional chat entries, we add these to the system prompt under the heading CONVERSATION HISTORY
      let prompt = event.payload.messages[0].content;
      let streamResVar = event.payload.streamResponse;
      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 = "meta.llama-3.2-90b-vision-instruct"
      let apiFormat = "GENERIC";
      return {
        "compartmentId": event.compartmentId,
        "servingMode": {
          "servingType": "ON_DEMAND",
          "modelId": modelId
        },

        "chatRequest": {
          "messages": [
              {
                  "role": "USER",
                  "content": [
                      {
                          "type": "TEXT",
                          "text": prompt
                      }
                  ]
              }
          ],
          "apiFormat": apiFormat,
          "maxTokens": 4000,
          "isStream": streamResVar,
          "numGenerations": 1,
          "frequencyPenalty": 0,
          "presencePenalty": 0,
          "temperature": 1,
          "topP": 1,
          "topK": 1
      }
      };
    },
 

    /**
    * Handler to transform the response payload
    * @param {TransformPayloadEvent} event - event object contains the following properties:
    * - payload: the response payload object
    * @param {LlmTransformationContext} context - see https://oracle.github.io/bots-node-sdk/LlmTransformationContext.html
    * @returns {object} the transformed response payload
    */

    transformResponsePayload: async (event, context) => {
      let llmPayload = {};
      if (event.payload.responseItems) {
        // streaming case
        llmPayload.responseItems = [];
        event.payload.responseItems.forEach(item => {

          let finshReasonVar = item.finishReason;
          if (finshReasonVar != 'stop') {
              let msgcontent = item.message.content[0];
              let text = msgcontent.text;
              if (text !== "") {
                llmPayload.responseItems.push({ "candidates": [{ "content" : text || "" }] });
              }       
          }       
        });
      } else {
          event.payload.chatResponse.choices.forEach(item => {
          let msgcontent = item.message.content[0];
          let text = msgcontent.text;
          llmPayload.candidates = [{ "content" : text || "" }];
         });
  
      }
    return llmPayload;
    },

Dica:

Para descobrir o que seu código precisa, recomendamos que você o depure localmente. Como um handler de eventos de transformação é semelhante a um componente personalizado, você pode usar a mesma técnica de depuração.