LLM- Transformations-Handler

Jeder Provider verfügt über ein eigenes Format für die Anforderungs-, Antwort- und Fehler-Payloads. Aus diesem Grund können der LLM-Provider und Oracle Digital Assistant nicht direkt kommunizieren. Um den Austausch zwischen dem Skill und seinen LLM-Providern zu erleichtern, müssen Sie diese Payloads in die gemeinsame LLM-Schnittstelle von Oracle Digital Assistant und wieder zurück transformieren.

Sie aktivieren diese Transformation, indem Sie einen LLM-Transformations-Handler erstellen, ein Skript, dessen transformRequestPayload-, transformResponsePayload- und transformErrorResponsePayload-Methoden die Payload-Transformationen ausführen. Diese Transformationsmethoden haben zwei Signaturen:
  • event: Die für dieses Objekt verwendeten Eigenschaften hängen vom Ereignistyp ab (transformRequestPayload, transformResponsePayload, transformErrorResponsePayload).
  • context: Verweist auf die Klasse LlmTransformationContext, die Zugriff auf Convenience-Methoden bietet, mit denen Sie die Ereignis-Handler-Logik erstellen können.

LLM-Transformations-Handler erstellen

So erstellen Sie einen LLM-Transformationsereignis-Handler:
  1. Klicken Sie in der linken Navigationsleiste auf Komponenten.
  2. Klicken Sie auf +New-Service.
  3. Füllen Sie das Dialogfeld "Service erstellen" aus:
    • Name: Geben Sie den Dienstnamen ein.
    • Servicetyp: Eingebetteter Container
    • Komponentenservicepakettyp: Neue Komponente
    • Komponententyp: LLM-Transformation
    • Komponentenname: Geben Sie einen einfach identifizierbaren Namen für den Entity-Event-Handler ein. Sie referenzieren diesen Namen, wenn Sie den LLM-Service für den Skill erstellen.
    • Vorlage: Wir stellen Vorlagen für Skills bereit, die Cohere direkt oder über den generativen KI-Service von Oracle aufrufen. Sie müssen diese Vorlagen nicht bearbeiten. Wenn Ihr Skill ein Nicht-Cohere/Oracle Generative AI-Modell aufruft, wie Azure Open AI, müssen Sie den entsprechenden Code hinzufügen.

      Die Templates für Oracle Generative AI Cohere (Textgenerierung und -zusammenfassung) und Llama (Textzusammenfassung) sind im Vorlagenlistenmenü unter Generative AI sortiert. Die Vorlage für den direkten Zugriff auf Cohere befindet sich unter Andere. Um auf die Vorlage zuzugreifen, die den Startcode für andere Modelle enthält, wählen Sie Benutzerdefiniert (die sich auch unter "Sonstige" befindet).

  4. Klicken Sie auf Erstellen, um den Event Handler-Code zu generieren.
  5. Blenden Sie nach Abschluss des Deployments den Service ein, und wählen Sie den Transformations-Handler aus, um die Eigenschaftenseite zu öffnen. Auf dieser Seite werden die drei LLM-Provider-CLMI-Transformationsmethoden (transformRequestPayload, transformResponsePayload und transformErrorResponsePayload) aufgeführt.

    Wenn Sie einen Cohere-Service oder einen Oracle Generative AI-Service erstellen, der auf demselben Mandanten wie Ihre Digital Assistant-Instanz gehostet wird, ist der Handler-Code vollständig.

  6. Wenn Sie einen Oracle Generative AI-Service erstellen, der in einem anderen OCI-Mandanten gehostet wird, klicken Sie auf Bearbeiten, um das Dialogfeld "Komponente bearbeiten" zu öffnen und die Variable event.compartmentId durch die Compartment-ID des OCI-Mandanten zu ersetzen, in dem der Generative AI-Service abonniert ist.
  7. Wenn Sie die benutzerdefinierte Vorlage verwenden, klicken Sie auf Bearbeiten, um das Dialogfeld "Komponente bearbeiten" zu öffnen, und aktualisieren Sie dann den folgenden Platzhaltercode mit dem providerspezifischen Code:
    Methode Speicherort im Editor (benutzerdefinierte Vorlage) Platzhaltercode (benutzerdefinierte Vorlage)
    transformRequestPayload Zeilen 23-25
    transformRequestPayload: async (event, context) => {
          return event.payload;
        },
    transformResponsePayload Zeilen 33-35
        transformResponsePayload: async (event, context) => {
          return event.payload;
        },
    transformErrorResponsePayload Zeilen 44-46
        transformErrorResponsePayload: async (event, context) => {
          return event.payload;
        }
  8. Prüfen Sie die Sytnax Ihrer Aktualisierungen, indem Sie auf Validieren klicken. Beheben Sie gegebenenfalls Validierungsfehler, und klicken Sie auf Speichern. Klicken Sie auf Schließen.

Beispiele für LLM-Providertransformationscode

Azure OpenAI

Methode Ereignis-Handler-Transformationscode
Anforderung
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;
},
Antwort (Nicht-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;
   }
Wenn Streaming aktiviert ist, wird der Response-Transformationsereignis-Handler in Batches mit 20 gestreamten Nachrichten aufgerufen. Dieses Batcharray mit gestreamten Antworten wird unter dem Schlüssel responseItems gespeichert.
Fehler
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)};
  }   
}

Oracle Generativer KI-Service - Cohere

Hinweis

Die Befehlsmodelle wurden eingezogen. Es wird empfohlen, zum Endpunkt /chat zu migrieren. Dabei wird ein aktuelleres Chatmodell deklariert und die befehlsspezifischen Parameter durch chatspezifische Parameter ersetzt.
Methode Event-Handler-Code
Anforderung
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"
        }
      };
}
Response
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;
 }
Fehler
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 KI - Lama

Hinweis

Die Befehlsmodelle wurden veraltet. Es wird empfohlen, dass Sie zum Endpunkt /chat migrieren. Dabei wird das Chatmodell deklariert und die befehlsspezifischen Parameter durch chat-spezifische Parameter ersetzt.
Methode Event-Handler-Code
Anforderung
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"
        }
      };
}
Response
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;
 }
Fehler
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 KI – Zusammenfassung

Hinweis

Die Befehlsmodelle wurden eingezogen. Es wird empfohlen, zum Endpunkt /chat zu migrieren. Dabei wird ein aktuelleres Chatmodell deklariert und die befehlsspezifischen Parameter durch chatspezifische Parameter ersetzt.
Methode Event-Handler-Code
Anforderung
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"
      };
}
Response
transformResponsePayload: async (event, context) => {
      let llmPayload = {};
      // non-streaming only: streaming is not supported
      llmPayload.candidates = [{"content": event.payload.summary}];
      return llmPayload;
}
Fehler
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 (Befehlsmodell) - Direkter Zugang zu Cohere

Die Handler in diesem Transformationscode unterstützen die /generate-API und das zugehörige Cohere.command-Modell, nicht die /chat-API, die für das cohere.command.R-Modell verwendet wird. Wenn Sie zum Endpunkt /chat migrieren, müssen Sie die Anforderungs- und Antwort-Payloads sowie die generierte Codevorlage manuell aktualisieren.
Methode Event-Handler-Code
Anforderung
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
      };
 }
Dieser Handler verwaltet die Unterhaltungshistorie, um den Unterhaltungskontext zu verwalten.
Response
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;
}
Fehler
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};
      }
 
}

Die gemeinsame LLM-Schnittstelle

Jeder LLM-Provider hat sein eigenes Format für seine Anforderungs- und Antwort-Payloads. Mit der Common LLM Interface (CLMI) kann die Komponente invokeLLM diese proprietären Anforderungs- und Antwort-Payloads verarbeiten.

Das CMLI besteht aus folgenden Elementen:
  • Eine Anforderungstextangabe.
  • Eine Spezifikation für den Body der Erfolgsantwort, die anwendbar ist, wenn der LLM-REST-Aufruf einen HTTP 200-Status zurückgibt.
  • Eine Spezifikation für den Fehlerantwortbody, die anwendbar ist, wenn der LLM-REST-Aufruf einen anderen HTTP-Status als 200 zurückgibt, der Aufruf des LLM-Service jedoch weiterhin erfolgreich war.
    Hinweis

    Bei nicht erfolgreichen Aufrufen verarbeitet die Komponente invokeLLM die Fehler 401 (nicht autorisiert) oder 500 (interner Serverfehler).

CLMI Anforderungsbody - Spezifikation

Der JSON CLMI-Anforderungsbody enthält die folgenden Eigenschaften:
Eigenschaft Typ Standardwert Beschreibung Erforderlich?
messages Ein Array von Nachrichtenobjekten N/V Eine Liste der Nachrichten. Die erste Nachricht ist die Eingabeaufforderung, bei der die Eigenschaft role auf system gesetzt ist. Wenn das LLM eine Multiturn-Unterhaltung unterstützt, sodass die LLM-Antwort verfeinert oder erweitert werden kann, sind die nachfolgenden Nachrichten Nachrichtenpaare aus den Rollen user und assistant. Die Benutzernachricht enthält die Nachsorgeanweisungen oder -fragen für das LLM. Die Assistentennachricht enthält die LLM-Antwort auf die Benutzernachricht (Abschluss). Wenn das LLM keine Multiturn-Unterhaltungen unterstützt, enthält das Array messages nur eine Systemnachricht mit der Eingabeaufforderung. Ja
streamResponse boolean false Bestimmt, ob die LLM-Antwort zurück an die LLM-Komponente gestreamt wird. Wenn Sie diese Eigenschaft auf true setzen, wird die Benutzererfahrung verbessert, da das Streaming es der LLM-Komponente ermöglicht, partielle Antwortnachrichten an Benutzer zurückzusenden, sodass sie nicht warten müssen, bis das LLM die Antwort abgeschlossen hat.

Setzen Sie streamResponse auf false, wenn die Antwortvalidierung verwendet wird. Da die gesamte Nachricht vor der Validierung erforderlich ist, kann die Nachricht für Benutzer mehrmals wiedergegeben werden: zuerst gestreamt, dann validiert, dann erneut gestreamt.

Nein
maxTokens Ganzzahl 1024 Das Modell generiert Token für die Wörter in den Ergebnissen. Token können als Wortteile betrachtet werden. 100 Token entsprechen etwa 75 Wörter in Englisch. Diese Eigenschaft begrenzt die Größe des vom Modell generierten Inhalts, indem die maximale Anzahl von Token festgelegt wird, die für die Antwort generiert werden. Nein
temperature Nummer 0 Das Modell verwendet Temperatur, um die Zufälligkeit - und damit die Kreativität - seiner Reaktionen zu messen. Sie legen diesen Wert zwischen 0 (vorhersehbare Ergebnisse) und 1 (zusätzlich randomisierte Ergebnisse) fest. 0 bedeutet, dass das Modell dieselben Ergebnisse an eine bestimmte Eingabeaufforderung sendet. 1 bedeutet, dass die Ergebnisse des Modells zu einer Antwort sehr unterschiedlich sein können. Verwenden Sie einen Event Handler, um einen Multiplikator anzuwenden, wenn der LLM-Provider einen anderen Bereich als 0-1 unterstützt. Nein
user Zeichenfolge N/V Eine eindeutige Kennung für Ihren Endbenutzer, die zur Überwachung und Erkennung missbräuchlicher Sprache verwendet werden kann. Nein
providerExtension Objekt N/V Aktiviert LLM-providerspezifische Konfigurationsoptionen, die nicht als Teil von CLMI definiert sind. Nein

Die Struktur des Nachrichtenobjekts

Eigenschaft Typ Beschreibung Erforderlich?
role Zeichenfolge Der Nachrichtenersteller. Die Werte lauten system, user und assistant. Ja
content Zeichenfolge Der Nachrichtencontent Ja
turn Ganzzahl Eine Zahl, die den aktuellen Verfeinerungswechsel des Chatnachrichtenaustauschs angibt. Wenn die erste Eingabeaufforderung an die LLM gesendet wird, ist die Umdrehung 1. Ja
retry boolean Kennzeichen, das angibt, ob die Nachricht an das LLM gesendet wird, um einen Fehler in der Antwort zu beheben Nein (Standard ist false)
tag Zeichenfolge Ein benutzerdefiniertes Tag, das eine bestimmte Eingabeaufforderung markiert. Wenn Sie die LLM-Antwort mit Rekursive Kritik und Verbesserung (RCI) verbessern, können Sie die benutzerdefinierte Logik im validateResponsePayload-Handler aktivieren, um den aktuellen Schritt des RCI-Prozesses zu ermitteln, indem Sie das Tag auf "criticize" oder "improve" setzen. Nein

Text der Erfolgsantwort - Spezifikation

Eigenschaft Typ Beschreibung Erforderlich?
candidates Ein Array von candidate-Objekten Eine Liste der vom LLM zurückgegebenen Kandidatennachrichten Ja

Kandidatenobjekte

Der JSON CLMI-Anforderungsbody enthält die folgenden Eigenschaften:
Eigenschaft Typ Beschreibung Erforderlich?
content Zeichenfolge Der Nachrichtencontent Ja

Spezifikation des Fehlerantwortbodys

Der JSON CLMI-Fehlerantwortbody enthält die folgenden Eigenschaften:
Eigenschaft Typ Beschreibung Erforderlich?
errorCode Zeichenfolge
  • notAuthorized: Gibt an, dass die LLM-Anforderung nicht über den richtigen Autorisierungsschlüssel verfügt.
  • modelLengthExceeded: Gibt an, dass die Kombination aus Anforderungsnachrichten (der System-Prompt zusammen mit den Verfeinerungsnachrichten des Benutzers und Assistenten) und der maximalen Anzahl von Token den Tokengrenzwert des Modells überschreitet.
  • requestFlagged: Gibt an, dass die LLM die Anforderung nicht erfüllen kann, weil sie gegen die Moderations-Policys des LLM-Providers verstößt. Beispielsweise werden Anfragen, die rassistische oder sexuell missbräuchliche Inhalte enthalten, markiert.
  • responseFlagged: Gibt an, dass die LLM-Antwort gegen Moderations-Policys des LLM-Providers verstößt. Antworten, die toxischen Inhalt enthalten, wie rassistische oder sexuell missbräuchliche Sprache, würden beispielsweise gekennzeichnet.
  • requestInvalid: Gibt an, dass die Anforderung an das LLM ungültig ist. Beispiel: Die Anforderung ist nicht gültig, weil einige der in einem Ereignis-Handler festgelegten Validierungsregeln nicht erfolgreich waren oder weil sie in einem Format vorliegt, das vom LLM nicht erkannt wird.
  • responseInvalid: Gibt an, dass die von LLM generierte Antwort ungültig ist. Beispiel: Die Antwort ist nicht gültig, weil einige der in einem Validierungsereignis-Handler definierten Validierungsregeln nicht erfolgreich waren.
  • unknown: Wenn andere Fehler auftreten.
Ja
errorMessage Zeichenfolge Die LLM-Provider-spezifische Fehlermeldung. Dies kann ein mit einer Zeichenfolge versehenes JSON-Objekt sein. Ja