Handler di trasformazione LLM

Ogni provider ha il proprio formato per i payload di richiesta, risposta ed errore. Per questo motivo, il provider LLM e Oracle Digital Assistant non possono comunicare direttamente, quindi per facilitare lo scambio tra la competenza e i suoi provider LLM, è necessario trasformare questi payload nell'interfaccia LLM comune di Oracle Digital Assistant e di nuovo.

Per abilitare questa trasformazione, creare un handler di trasformazione LLM, uno script i cui metodi transformRequestPayload, transformResponsePayload e transformErrorResponsePayload eseguono le trasformazioni del payload. Questi metodi di trasformazione dispongono di due firme:
  • event: le proprietà utilizzate per questo oggetto dipendono dal tipo di evento (transformRequestPayload, transformResponsePayload, transformErrorResponsePayload).
  • context: fa riferimento alla classe LlmTransformationContext, che fornisce l'accesso ai metodi convenienti che è possibile utilizzare per creare la logica del gestore di eventi.

Crea un handler di trasformazione LLM

Per creare un handler di eventi di trasformazione LLM:
  1. Fare clic su Componenti nella barra di navigazione a sinistra.
  2. Fare clic su +New Servizio.
  3. Completare la finestra di dialogo Crea servizio:
    • Nome: immettere il nome del servizio.
    • Tipo di servizio: Contenitore incorporato
    • Tipo pacchetto servizio componente: Nuovo componente
    • Tipo di componente: Trasformazione LLM
    • Nome componente: immettere un nome facilmente identificabile per l'handler di eventi entità. Quando si crea il servizio LLM per lo skill, verrà fatto riferimento a questo nome.
    • Modello: forniamo modelli per le competenze che chiamano Cohere direttamente o tramite il servizio Oracle Generative AI. Non è necessario modificare questi modelli. Se la tua abilità chiama un modello di intelligenza artificiale generativa non Cohere/Oracle, come Azure Open AI, dovrai aggiungere il codice appropriato.

      I modelli per Oracle Generative AI Cohere (generazione di testo e riepilogo) e Llama (riepilogazione di testo) vengono ordinati in AI generativa nel menu dell'elenco dei modelli. Il modello per accedere direttamente a Cohere si trova sotto Altro. Per accedere al modello che contiene il codice iniziale per altri modelli, scegliere Personalizzato (che si trova anche in Altro).

  4. Fare clic su Crea per generare il codice del gestore di eventi.
  5. Al termine della distribuzione, espandere il servizio e selezionare l'handler di trasformazione per aprire la relativa pagina delle proprietà, in cui sono elencati i tre metodi di trasformazione LLM provider-CLMI (transformRequestPayload, transformResponsePayload e transformErrorResponsePayload).

    Se si sta creando un servizio Cohere o un servizio AI generativa Oracle ospitato nella stessa tenancy dell'istanza di Digital Assistant, il codice dell'handler è completo.

  6. Se si sta creando un servizio Oracle Generative AI ospitato in una tenancy OCI diversa, fare clic su Modifica per aprire la finestra di dialogo Modifica componente e sostituire la variabile event.compartmentId con l'ID compartimento della tenancy OCI in cui è sottoscritto il servizio Generative AI.
  7. Se si utilizza il modello personalizzato, fare clic su Modifica per aprire la finestra di dialogo Modifica componente, quindi aggiornare il codice segnaposto seguente con il codice specifico del provider:
    Metodo Posizione nell'editor (modello personalizzato) Codice segnaposto (modello personalizzato)
    transformRequestPayload Righe 23-25
    transformRequestPayload: async (event, context) => {
          return event.payload;
        },
    transformResponsePayload Righe 33-35
        transformResponsePayload: async (event, context) => {
          return event.payload;
        },
    transformErrorResponsePayload Righe 44-46
        transformErrorResponsePayload: async (event, context) => {
          return event.payload;
        }
  8. Verificare la sintassi degli aggiornamenti facendo clic su Convalida. Correggere gli eventuali errori di convalida, quindi fare clic su Salva. Quindi fare clic su Chiudi.

Campioni codice trasformazione fornitore LLM

Azure OpenAI

Metodo Codice trasformazione gestore eventi
Richiedi
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;
},
Risposta (non streaming)
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;
   }
Quando lo streaming è abilitato, l'handler di eventi di trasformazione delle risposte viene chiamato in batch di 20 messaggi in streaming. Questo array in batch di risposte in streaming viene memorizzato sotto la chiave responseItems.
Errore
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)};
  }   
}

Servizio Oracle Generative AI - Cohere

Nota

I modelli di comando sono stati ritirati. Si consiglia di eseguire la migrazione all'endpoint /chat, il che comporta la dichiarazione di un modello di chat più recente e la sostituzione dei parametri specifici del comando con parametri specifici della chat.
Metodo Codice gestore eventi
Richiedi
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"
        }
      };
}
Risposta
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;
 }
Errore
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};
      }
}

Oracle Generative AI - Llama

Nota

I modelli di comando sono stati ritirati. Si consiglia di eseguire la migrazione all'endpoint /chat, che prevede la dichiarazione del modello di chat e la sostituzione dei parametri specifici del comando con parametri specifici della chat.
Metodo Codice gestore eventi
Richiedi
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"
        }
      };
}
Risposta
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;
 }
Errore
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};
      }
}

Oracle Generative AI - Riepilogo

Nota

I modelli di comando sono stati ritirati. Si consiglia di eseguire la migrazione all'endpoint /chat, il che comporta la dichiarazione di un modello di chat più recente e la sostituzione dei parametri specifici del comando con parametri specifici della chat.
Metodo Codice gestore eventi
Richiedi
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"
      };
}
Risposta
transformResponsePayload: async (event, context) => {
      let llmPayload = {};
      // non-streaming only: streaming is not supported
      llmPayload.candidates = [{"content": event.payload.summary}];
      return llmPayload;
}
Errore
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 (Modello di comando) - Accesso diretto a Cohere

Gli handler in questo codice di trasformazione supportano l'API /generate e il modello Cohere.command associato, non l'API /chat utilizzata per il modello cohere.command.R. Se si esegue la migrazione all'endpoint /chat, sarà necessario aggiornare manualmente i payload di richiesta e risposta e il modello di codice generato.
Metodo Codice gestore eventi
Richiedi
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
      };
 }
Questo handler gestisce la cronologia delle conversazioni per gestire il contesto della conversazione.
Risposta
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;
}
Errore
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};
      }
 
}

Interfaccia LLM comune

Ogni provider LLM ha il proprio formato per i payload di richiesta e risposta. L'interfaccia LLM comune, o CLMI, consente al componente invokeLLM di gestire questi payload proprietari di richieste e risposte.

Il CMLI è costituito dai seguenti elementi:
  • Specifica del corpo della richiesta.
  • Specifica del corpo della risposta riuscita, applicabile quando la chiamata REST LLM restituisce uno stato HTTP 200.
  • Specifica del corpo della risposta di errore, applicabile quando la chiamata REST LLM restituisce uno stato HTTP diverso da 200, ma il richiamo del servizio LLM è ancora riuscito.
    Nota

    Per i richiami non riusciti, il componente invokeLLM gestisce gli errori 401 (non autorizzato) o 500 (errore del server interno).

Specifica corpo richiesta CLMI

Il corpo della richiesta CLMI JSON contiene le proprietà riportate di seguito.
Proprietà Digita Valore predefinito descrizione; Richiesto?
messages Un array di oggetti messaggio N/A Un elenco di messaggi. Il primo messaggio è il prompt con la proprietà role impostata su system. Se l'LLM supporta una conversazione multi-turn in modo che la risposta LLM possa essere perfezionata o migliorata, i messaggi successivi saranno coppie di messaggi dai ruoli user e assistant. Il messaggio utente contiene le istruzioni di follow-up o la domanda per l'LLM. Il messaggio dell'assistente contiene la risposta LLM al messaggio utente (il completamento). Se l'LLM non supporta conversazioni a più turni, l'array messages conterrà un solo messaggio di sistema contenente il prompt.
streamResponse boolean false Determina se la risposta dell'LLM verrà trasmessa nuovamente al componente LLM. L'impostazione di questa proprietà su true migliora l'esperienza utente, poiché lo streaming consente al componente LLM di inviare messaggi di risposta parziali agli utenti in modo che non debbano attendere che l'LLM completi la risposta.

Impostare streamResponse su false quando si utilizza la convalida della risposta. Poiché l'intero messaggio è necessario prima che la convalida possa avere luogo, il messaggio può essere visualizzato per gli utenti più volte: prima in streaming, quindi convalidato, quindi di nuovo in streaming.

No
maxTokens Intero 1024 Il modello genera token per le parole nei risultati. I token possono essere considerati come pezzi di parole. Ad esempio, 100 token equivalgono a circa 75 parole in inglese. Questa proprietà limita le dimensioni del contenuto generato dal modello impostando il numero massimo di token generati per la risposta. No
temperature numerica 0 Il modello utilizza la temperatura per misurare la casualità - e quindi la creatività - delle sue risposte. Impostare questo valore come valore compreso tra 0 (risultati prevedibili) e 1 (risultati più randomizzati). 0 indica che il modello invierà gli stessi risultati a un determinato prompt. 1 indica che i risultati del modello a una determinata risposta possono variare notevolmente. Utilizzare un gestore di eventi per applicare un moltiplicatore se il provider LLM supporta un intervallo diverso da 0-1. No
user stringa N/A Identificativo univoco che rappresenta l'utente finale, che può essere utilizzato per monitorare e rilevare un linguaggio abusivo. No
providerExtension oggetto N/A Abilita le opzioni di configurazione specifiche del provider LLM non definite come parte di CLMI. No

Struttura oggetto messaggio

Proprietà Digita descrizione; Richiesto?
role stringa Il creatore del messaggio. I valori sono system, user e assistant.
content stringa Il contenuto del messaggio
turn Intero Numero che indica il turno di perfezionamento corrente dello scambio di messaggi di chat. Quando il primo prompt viene inviato al LLM, il turno è 1.
retry boolean Flag che indica se il messaggio viene inviato all'LLM per correggere un errore nella risposta No (l'impostazione predefinita è false)
tag stringa Tag personalizzato che contrassegna un prompt specifico. Se si sta migliorando la risposta LLM utilizzando Recursive Criticism and Improvement (RCI), è possibile abilitare la logica personalizzata nell'handler validateResponsePayload per rilevare il passo corrente del processo RCI impostando il tag su "criticize" o "improve". No

Specifica corpo risposta riuscita

Proprietà Digita descrizione; Richiesto?
candidates Un array di oggetti candidate Elenco di messaggi dei candidati restituiti da LLM

Oggetti candidati

Il corpo della richiesta CLMI JSON contiene le proprietà riportate di seguito.
Proprietà Digita descrizione; Richiesto?
content stringa Il contenuto del messaggio

Specifica corpo risposta errore

Il corpo della risposta agli errori CLMI JSON contiene le proprietà riportate di seguito.
Proprietà Digita descrizione; Richiesto?
errorCode Stringa
  • notAuthorized: indica che la richiesta LLM non dispone della chiave di autorizzazione appropriata.
  • modelLengthExceeded: indica che la combinazione di messaggi di richiesta (il prompt di sistema insieme ai messaggi di perfezionamento dell'utente e dell'assistente) e il numero massimo di token supera il limite di token del modello.
  • requestFlagged: indica che l'LLM non può soddisfare la richiesta perché viola i criteri di moderazione del provider LLM. Ad esempio, le richieste che contengono contenuti razzisti o sessualmente abusivi verranno segnalate.
  • responseFlagged: indica che la risposta LLM viola i criteri di moderazione del provider LLM. Ad esempio, le risposte che contengono contenuti tossici, come il linguaggio razzista o sessualmente abusivo, verranno contrassegnate.
  • requestInvalid: indica che la richiesta all'LLM non è valida. Ad esempio, la richiesta non è valida perché non ha superato alcune delle regole di convalida impostate in un gestore di eventi oppure è in un formato non riconosciuto dall'LLM.
  • responseInvalid: indica che la risposta generata da LLM non è valida. Ad esempio, la risposta non è valida perché non ha superato alcune delle regole di convalida definite in un handler di eventi di convalida.
  • unknown: quando si verificano altri errori.
errorMessage Stringa Messaggio di errore specifico del provider LLM. Potrebbe trattarsi di un oggetto JSON con stringa.