Einfache Hybridsuche für Retrieval Augmented Generation mit Oracle Database 23ai implementieren

Einführung

Dieses Tutorial zeigt, wie Sie eine hybride Suche im Rahmen eines RAG-(Retrieval Augmented Generation-)Prozesses mit Vektor- und Stichwortsuche in Oracle 23ai implementieren.

RAG hat sich als eine Schlüsselfunktion für Unternehmen entwickelt, die Large Language Models (LLMs) verwenden, um ihre Antworten mit spezifischen Geschäfts- oder Domaininformationen zu erweitern. Wenn Sie mit einer Unternehmenswissensdatenbank nach Informationen suchen, die für die Abfrage eines Benutzers relevant sind, und dann die abgerufenen Informationen an die Anforderung an das LLM anhängen, können Antworten auf interne Daten, Policys und und szenariospezifische Informationen, wobei die spezifischen Informationen die Wahrscheinlichkeit einer Halluzination verringern und eine Antwort in natürlicher Sprache ermöglichen, die entsprechende Zitate und Verweise auf Dokumente in der Wissensdatenbank enthält.

Oracle Database umfasst mehrere leistungsstarke Funktionen zur Ausführung von RAG-Aufgaben. Im Oracle Database 23ai-Release wurde eine KI-Vektorsuchfunktion eingeführt, mit der Sie schnelle semantische Suchen für unstrukturierte Daten durchführen können. Die Verwendung von semantischer Suche mit hochwertigen Vektoreinbettungen kann fast magisch erscheinen, wobei fast jede Abfrage hochrelevante Dokumente aus einer riesigen Wissensdatenbank beschwört. Nur weil die Vektorsuche verfügbar ist und qualitativ hochwertige Ergebnisse in den meisten Szenarien liefert, bedeutet dies jedoch nicht, dass die traditionelle schlüsselwortbasierte Suche aufgegeben werden sollte. Jeder Entwickler, der viel Zeit damit verbracht hat, den Abruf zu testen, hat sicherlich einige Seltsamkeiten entdeckt, in denen Dokumente, die das spezifische Thema abdecken, nach dem gefragt wurde und die intuitiv in die Antwort aufgenommen werden würden, nicht sind, obwohl sie durch eine Stichwortsuche triv gefunden würden.

Warum also nicht beides verwenden?

Oracle Database 23ai baut auf allen leistungsstarken Funktionen auf, die der Datenbank im Laufe der Zeit hinzugefügt wurden, einschließlich Oracle Text, das Rich-Text-Abfragefunktionen bereitstellt. Dieses Tutorial soll zeigen, wie die Existenz dieser beiden Funktionen in der Datenbank es unglaublich einfach macht, eine robuste Hybridsuche zu implementieren und das Beste aus beiden Welten ohne Datenduplizierung bereitzustellen.

Hinweis: Dieses Tutorial zeigt die Implementierung der Logik für die hybride Suche in Python mit einem lokalen Einbettungsmodell. Oracle Database 23ai unterstützt die Berechnung von Texteinbettungen in der Datenbank mithilfe von ONNX-Modellen. Außerdem wird die hybride Suche mit einem ONNX-Modell in der Datenbank über ein Database Management System-(DBMS-)Package nativ unterstützt. Die Implementierung der Logik direkt in Python bietet eine viel größere Kontrolle über das Verhalten der Suche, aber das DBMS-Paket bietet eine einfache, aber leistungsstarke Reihe von Funktionen für einige Anwendungsfälle. Weitere Informationen finden Sie unter ONNX-Modelle in Oracle Database-End-to-End-Beispiel importieren und Hybride Suche.

Ziele

Voraussetzungen

Aufgabe 1: Datenbanktabelle einrichten

Die für die hybride Suche verwendete Tabelle kann mit einer Tabelle identisch sein, die für die Vektorsuche verwendet wird, da Oracle Text CLOB-Felder (Character Large Object) indexieren kann, die normalerweise zum Speichern des Dokumentinhalts verwendet werden.

Hinweis: Die SQL für das anfängliche Tabellensetup wird hier direkt angezeigt, anstatt von Python aufgerufen zu werden. Der von Ihrem RAG-Prozess verwendete Datenbankbenutzeraccount sollte nur über Berechtigungen zum Abfragen der Tabelle und nicht zum Erstellen von Tabellen und Indizes verfügen, da diese Aufgaben von einem Datenbankadministrator mit seinen bevorzugten Tools ausgeführt werden.

  1. Nachdem Sie sich bei der Datenbank angemeldet haben, erstellen Sie eine Tabelle, in der die vom RAG-Prozess verwendeten Dokumente mit der folgenden SQL gespeichert werden.

    CREATE TABLE hybridsearch 
    (id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
    text CLOB, 
    embeddings VECTOR(768, FLOAT32),
    metadata JSON);
    

    Die Größe der Vektorspalte hängt vom Einbettungsmodell ab, mit dem die Vektoren für die semantische Suche generiert werden sollen. Hier verwenden wir 768, was dem später in diesem Beispiel verwendeten Vektormodell entspricht, obwohl bei Verwendung eines alternativen Modells dieser Wert möglicherweise aktualisiert werden muss, um diese Änderung widerzuspiegeln. Eine JSON-Spalte wird zum Speichern von Dokumentmetadaten angegeben, da dies flexible Strukturen bereitstellen kann und dennoch die Filterung der Attribute des Dokuments zulässt. Obwohl sie in diesem Tutorial nicht verwendet wird, ist sie enthalten, da für jedes reale Szenario Dokumentmetadaten erforderlich sind.

  2. Um die Stichwortsuche für den Text zu aktivieren, muss ein Textindex für die Textspalte erstellt werden.

    CREATE SEARCH INDEX rag_text_index ON hybridsearch (text);
    

Aufgabe 2: Librarys installieren

Dieses Tutorial veranschaulicht die Verwendung einer Python-Laufzeit zur Implementierung der Dokumentaufnahme und der hybriden Suche. Es wird empfohlen, die Python-Laufzeit mit einer venv- oder conda-Umgebung zu konfigurieren.

Hinweis: In diesem Tutorial wird versucht, nach Bedarf Codeabschnitte einzuführen, um jedes Konzept zu demonstrieren. Außerdem ist eine Refactoring erforderlich, wenn es in eine umfassendere Lösung integriert werden soll.

  1. Installieren Sie die für dieses Tutorial erforderlichen Abhängigkeiten mit pip.

    $ pip install -U oracledb sentence-transformers git+https://github.com/LIAAD/yake
    

Aufgabe 3: Dokumente in die Datenbank aufnehmen

Nachdem die Tabelle erstellt wurde, können Dokumente als Zeilen in die Tabelle eingefügt werden. In der Regel sollte der Aufnahmeprozess vom Abfrageprozess getrennt sein und verschiedene Datenbankaccounts mit unterschiedlichen Berechtigungen verwenden (da der Abfrageprozess die Tabelle nicht ändern kann), aber für die Zwecke dieses Tutorials werden sie hier nicht unterschieden.

  1. Stellen Sie in der Python-Umgebung die Verbindung zur Datenbank her. Beispiel: Für Autonomous Transaction Processing.

    import os
    import oracledb
    import traceback
    import json 
    import re
       
    try:
        print(f'Attempting to connect to the database with user: [{os.environ["DB_USER"]}] and dsn: [{os.environ["DB_DSN"]}]')
        connection = oracledb.connect(user=os.environ["DB_USER"], password=os.environ["DB_PASSWORD"], dsn=os.environ["DB_DSN"],
                                    config_dir="/path/to/dbwallet",
                                    wallet_location="/path/to/dbwallet",
                                    wallet_password=os.environ["DB_WALLET_PASSWORD"])
        print("Connection successful!")
    except Exception as e:
        print(traceback.format_exc())
        print("Connection failed!")
    

    Die python-oracledb-Dokumentation gibt Details zum Herstellen einer Verbindung zu Nicht-ADB-Instanzen an, die keine Connection Wallets verwenden dürfen.

  2. Initialisieren Sie das Einbettungsmodell, das zur Berechnung der Einbettungsvektoren verwendet wird. Hier wird das Modell all-mpnet-base-v2 verwendet, das unter der Apache-Lizenz verfügbar ist. Obwohl dieses spezifische Einbettungsmodell nur zur Illustration verwendet wird, können andere Modelle je nach Ihren Daten eine bessere oder schlechtere Leistung erzielen. In diesem Beispiel wird die Benutzeroberfläche SentenceTransformers zur Vereinfachung verwendet. Weitere Informationen finden Sie in der SentenceTransformers-Dokumentation.

    from sentence_transformers import SentenceTransformer
       
    model = SentenceTransformer('sentence-transformers/all-mpnet-base-v2')
    
  3. Implementieren Sie eine einfache Dokumentaufnahmefunktion. Der Prozess zum Abrufen, Parsen und Chunking von Dokumenten ist für dieses Tutorial nicht relevant, und für die Zwecke dieses Tutorials wird davon ausgegangen, dass sie nur als Zeichenfolgen bereitgestellt werden. Diese Funktion berechnet die Einbettungen anhand des bereitgestellten Modells und fügt dann das Dokument und die Einbettungen in die erstellte Tabelle ein.

    def add_document_to_table(connection, table_name, model, document, **kwargs):
        """
        Adds a document to the database for use in RAG.
        @param connection An established database connection.
        @param table_name The name of the table to add the document to
        @param model A sentence transformers model, with an 'encode' function that returns embeddings
        @param document The document to add, as a string
        Keyword Arguments:
        metadata: A dict with metadata about the document which is stored as a JSON object
        """
        #Calculate the embeddings for the document
        embeddings = model.encode(document)
        insert_sql = f"""INSERT INTO {table_name} (text, embeddings, metadata) VALUES (:text, :embeddings, :metadata)"""
        metadata = kwargs.get('metadata', {})
        cursor = connection.cursor()
        try:
            cursor.execute(insert_sql, text=document, embeddings=json.dumps(embeddings.tolist()), metadata=json.dumps(metadata))
        except Exception as e:
            print(traceback.format_exc())
            print("Insert failed!")
    
  4. Fügen Sie der Datenbank einige Beispieldokumente zum Testen hinzu.

    Hinweis: Ein expliziter commit() wird aufgerufen, der die Aktualisierung des Textindexes auslöst.

    table_name = "testhybrid"
       
    # These samples are just included to provide some data to search, not to 
    # demonstrate the efficacy of key phrase versus semantic search. The benefits
    # of hybrid search typically start to emerge when using a much larger volume
    # of content.
    document_samples = [
        "Oracle Database 23ai is the next long-term support release of Oracle Database. It includes over 300 new features with a focus on artificial intelligence (AI) and developer productivity.",
        "Features such as AI Vector Search enable you to leverage a new generation of AI models to generate and store vectors of documents, images, sound, and so on;  index them and quickly look for similarity while leveraging the existing analytical capabilities of Oracle Database.",
        "New developer-focused features now make it simpler to build next-generation applications that use JSON or relational development approaches or both interchangeably.",
        "With a built-in VECTOR data type, you can run AI-powered vector similarity searches within the database instead of having to move business data to a separate vector database.",
        "Property graphs provide an intuitive way to find direct or indirect dependencies in data elements and extract insights from these relationships. The enterprise-grade manageability, security features, and performance features of Oracle Database are extended to property graphs.",
        "The ISO SQL standard has been extended to include comprehensive support for property graph queries and creating property graphs in SQL.",
        "Transactional Event Queues (TxEventQ) are queues built into the Oracle Database. TxEventQ are a high performance partitioned implementation with multiple event streams per queue.",
        "Transactional Event Queues (TxEventQ) now support the KafkaProducer and KafkaConsumer classes from Apache Kafka. Oracle Database can now be used as a source or target for applications using the Kafka APIs.",
        "Database metrics are stored in Prometheus, a time-series database and metrics tailored for developers are displayed using Grafana dashboards. A database metrics exporter aids the metrics exports from database views into Prometheus time series database."
        "The Java Database Connectivity (JDBC) API is the industry standard for database-independent connectivity between the Java programming language and a wide range of databases—SQL databases and other tabular data sources, such as spreadsheets or flat files.",
        "Java Database Connectivity (JDBC) is a Java standard that provides the interface for connecting from Java to relational databases. The JDBC standard is defined and implemented through the standard java.sql interfaces. This enables individual providers to implement and extend the standard with their own JDBC drivers.",
        "The JDBC Thin driver enables a direct connection to the database by providing an implementation of Oracle Net Services on top of Java sockets. The driver supports the TCP/IP protocol and requires a TNS listener on the TCP/IP sockets on the database server.",
        "The JDBC Thin driver is a pure Java, Type IV driver that can be used in applications. It is platform-independent and does not require any additional Oracle software on the client-side. The JDBC Thin driver communicates with the server using Oracle Net Services to access Oracle Database.",
        "The JDBC OCI driver, written in a combination of Java and C, converts JDBC invocations to calls to OCI, using native methods to call C-entry points. These calls communicate with the database using Oracle Net Services.",
        "The python-oracledb driver is a Python extension module that enables access to Oracle Database. By default, python-oracledb allows connecting directly to Oracle Database 12.1 or later. This Thin mode does not need Oracle Client libraries.",
        "Users interact with a Python application, for example by making web requests. The application program makes calls to python-oracledb functions. The connection from python-oracledb Thin mode to the Oracle Database is established directly.",
        "Python-oracledb is said to be in ‘Thick’ mode when it links with Oracle Client libraries. Depending on the version of the Oracle Client libraries, this mode of python-oracledb can connect to Oracle Database 9.2 or later.",
        "To use python-oracledb Thick mode, the Oracle Client libraries must be installed separately. The libraries can be from an installation of Oracle Instant Client, from a full Oracle Client installation (such as installed by Oracle’s GUI installer), or even from an Oracle Database installation (if Python is running on the same machine as the database).",
        "Oracle’s standard client-server version interoperability allows connection to both older and newer databases from different Oracle Client library versions."
    ]
       
    for document in document_samples:
        add_document_to_table(connection, table_name, model, document)
       
    #Call an explicit commit after adding the documents, which will trigger an async update of the text index
    connection.commit()
    

Nachdem die Dokumente geladen wurden, können Sie mit den KI-Vektorsuchfunktionen von Oracle Database 23ai eine semantische Suche basierend auf einem Vektor ausführen, den wir aus einer Abfrage ableiten.

  1. Implementieren Sie eine Helper-Funktion für die Arbeit mit den von der Datenbank zurückgegebenen CLOB-Objekten.

    def get_clob(result):
        """
        Utility function for getting the value of a LOB result from the DB.
        @param result Raw value from the database
        @returns string
        """
        clob_value = ""
        if result:
            if isinstance(result, oracledb.LOB):
                raw_data = result.read()
                if isinstance(raw_data, bytes):
                    clob_value = raw_data.decode("utf-8")
                else:
                    clob_value = raw_data
            elif isinstance(result, str):
                clob_value = result
            else:
                raise Exception("Unexpected type:", type(result))
        return clob_value
    
  2. Implementieren Sie eine Funktion zur Ausführung der semantischen Suche mit der SQL-Funktion vector_distance(). Das in diesem Tutorial verwendete all-mpnet-base-v2-Modell verwendet die COSINE-Ähnlichkeit, die hier standardmäßig vorgegeben wurde. Wenn Sie ein anderes Modell verwenden, müssen Sie möglicherweise eine alternative Entfernungsstrategie angeben.

    def retrieve_documents_by_vector_similarity(connection, table_name, model, query, num_results, **kwargs):
        """
        Retrieves the most similar documents from the database based upon semantic similarity.
        @param connection An established database connection.
        @param table_name The name of the table to query
        @param model A sentence transformers model, with an 'encode' function that returns embeddings
        @param query The string to search for semantic similarity with
        @param num_results The number of results to return
        Keyword Arguments:
        distance_strategy: The distance strategy to use for comparison One of: 'EUCLIDEAN', 'DOT', 'COSINE' - Default: COSINE
        @returns: Array<(string, string, dict)> Array of documents as a tuple of 'id', 'text', 'metadata'
        """
        # In many cases, building up the search SQL may involve adding a WHERE 
        # clause in order to search only a subset of documents, though this is
        # omitted for this simple example.
        search_sql = f"""SELECT id, text, metadata,
                        vector_distance(embeddings, :embedding, {kwargs.get('distance_strategy', 'COSINE')}) as distance
                        FROM {table_name}
                        ORDER BY distance
                        FETCH APPROX FIRST {num_results} ROWS ONLY
                        """
        query_embedding = model.encode(query)
        cursor = connection.cursor()
        try:
            cursor.execute(search_sql, embedding=json.dumps(query_embedding.tolist()))
        except Exception as e:
            print(traceback.format_exc())
            print("Retrieval failed!")
        rows = cursor.fetchall()
        documents = []
        for row in rows:
            documents.append((row[0].hex(), get_clob(row[1]), row[2]))
       
        return documents
    
  3. Validieren Sie die semantische Suchfunktion anhand des folgenden Beispiels.

    query = "I am writing a python application and want to use Apache Kafka for interacting with queues, is this supported by the Oracle database?"
       
    documents_from_vector_search = retrieve_documents_by_vector_similarity(connection, table_name, model, query, 4)
    print(documents_from_vector_search)
    

In diesem Tutorial wird Oracle Text verwendet, das leistungsstarke Textabfragetools in Oracle Database bereitstellt. Während Oracle Text eine breite Palette von Funktionen für die hybride Suche bereitstellt, ist nur eine einfache Suche nach Schlüsselwörtern oder Schlüsselphrasen erforderlich. Es gibt eine Reihe von Techniken zum Extrahieren und Suchen von Schlüsselwörtern. Diese Implementierung soll jedoch so einfach wie möglich sein. Verwenden Sie dazu Yet Another Keyword Extractor (YAKE), der auf Sprachfunktionen basiert, um die unbeaufsichtigte Extraktion von Schlüsselwörtern und Schlüsselphrasen durchzuführen.

Es gibt eine Vielzahl anderer Ansätze für die Stichwortsuche, wobei der Okapi BM25-Algorithmus beliebt ist. Die Verwendung einer nicht überwachten Keyword-Extraktion mit einem leistungsstarken Textsuchindex wie dem von Oracle Text bereitgestellten hat jedoch den Vorteil, besonders einfach zu sein, und die Robustheit wird durch die Kombination mit der semantischen Suche bereitgestellt.

  1. Implementieren Sie eine Funktion zum Extrahieren von Schlüsselwörtern.

    import yake
       
    def extract_keywords(query, num_results):
        """
        Utility function for extracting keywords from a string.
        @param query The string from which keywords should be extracted
        @param num_results The number of keywords/phrases to return
        @returns Array<(string, number)> Array of keywords/phrases as a tuple of 'keyword', 'score' (lower scores are more significant)
        """
        language = "en"
        #Max number of words to include in a key phrase
        max_ngram_size = 2
        windowSize = 1
       
        kw_extractor = yake.KeywordExtractor(lan=language, n=max_ngram_size, windowsSize=windowSize, top=num_results, features=None)
        keywords = kw_extractor.extract_keywords(query.strip().lower())
        return sorted(keywords, key=lambda kw: kw[1])
    

    Da diese Methode der Schlüsselwortextraktion auf Sprachfunktionen basiert, ist das Festlegen der entsprechenden Sprache wichtig, und die Leistung kann je nach Sprache selbst variieren.

  2. Validieren Sie die Stichwortextraktion anhand des folgenden Beispiels.

    query = "I am writing a python application and want to use Apache Kafka for interacting with queues, is this supported by the Oracle database?"
       
    keywords = extract_keywords(query, 4)
    print(keywords)
    
  3. Implementieren Sie eine Funktion zum Durchführen einer schlüsselwortbasierten Suche.

    def retrieve_documents_by_keywords(connection, table_name, query, num_results):
        """
        Retrieves the documents from the database which have the highest density of matching keywords as the query
        @param connection An established database connection.
        @param table_name The name of the table to query
        @param query The string from which to extract keywords/phrases for searching
        @param num_results The number of results to return
        @returns: Array<(string, string, dict)> Array of documents as a tuple of 'id', 'text', 'metadata'
        """
        num_keywords = 4
        keywords = extract_keywords(query, num_keywords)
        search_sql = f"""SELECT id, text, metadata, SCORE(1)
                        FROM {table_name}
                        WHERE CONTAINS (text, :query_keywords, 1) > 0
                        ORDER BY SCORE(1) DESC
                        FETCH APPROX FIRST {num_results} ROWS ONLY
                        """
        #Assemble the keyword search query, adding the stemming operator to each word
        stemmed_keywords = []
        splitter = re.compile('[^a-zA-Z0-9_\\+\\-/]')
        for keyword in keywords:
            stemmed_keyword = ""
            for single_word in splitter.split(keyword[0]):
                stemmed_keyword += "$" + single_word +" "
            stemmed_keywords.append(stemmed_keyword.strip())
        cursor = connection.cursor()
        try:
            cursor.execute(search_sql, query_keywords=",".join(stemmed_keywords))
        except Exception as e:
            print(traceback.format_exc())
            print("Retrieval failed!")
        rows = cursor.fetchall()
        documents = []
        for row in rows:
            documents.append((row[0].hex(), get_clob(row[1]), row[2]))
        return documents
    

    Eine der einfachsten Verhaltensweisen in Oracle Text ist die Durchführung von Stichwortsuchen über die Funktion CONTAINS, die eine Vielzahl zusätzlicher Operatoren unterstützt, um die Suche zu verfeinern oder zu erweitern. In diesem Tutorial wird der stemming-Operator verwendet. Erweitert eine Abfrage, um alle Begriffe mit demselben Stamm- oder Root-Wort wie der angegebene Begriff aufzunehmen. Dies wird verwendet, um Wörter unabhängig von Pluralität und Spannung zu normalisieren, damit cat beispielsweise cats entspricht. Weitere Informationen finden Sie unter Oracle Text CONTAINS Query Operators.

    Hinweis: Wenn Sie dies auf einen großen Korpus von Dokumenten anwenden, wird empfohlen, den Textindex so zu konfigurieren, dass er Wortstiele enthält, um die Performance zu verbessern. Weitere Informationen zu Basic Lexer finden Sie unter BASIC_LEXER.

  4. Validieren Sie die stichwortbasierte Suche anhand des folgenden Beispiels.

    query = "I am writing a python application and want to use Apache Kafka for interacting with queues, is this supported by the Oracle database?"
       
    documents_from_keyphrase_search = retrieve_documents_by_keywords(connection, table_name, query, 4)
    print(documents_from_keyphrase_search)
    

Ergebnisse kombinieren und verwenden

Sobald die Dokumente erhalten wurden, können sie einem LLM als zusätzlichen Kontext zur Verfügung gestellt werden, mit dem sie auf Anfragen oder Anweisungen antworten können. In einigen Szenarien kann es sinnvoll sein, einfach alle abgerufenen Dokumente in die Eingabeaufforderung des LLM aufzunehmen. In anderen Fällen ist das Fehlen relevanter Dokumente ein wichtiger Kontext für sich und daher kann es wichtig sein, ihre Relevanz zu bestimmen. Dies kann auf einer bestimmten Gewichtung basieren, die auf jeder Art von Suche platziert wird, oder die Relevanz jedes Dokuments kann unabhängig davon beurteilt werden, wie es mit einem Re-Ranking-Modell zurückgegeben wurde.

In jedem dieser Anwendungsfälle ist die Deduplizierung der Ergebnisse ein wichtiger Schritt. Jede Funktion hat die Dokumentkennung beibehalten, die eine eindeutige Kennung bereitstellt, die zu diesem Zweck verwendet werden kann. Beispiel:

def deduplicate_documents(*args):
    """
    Combines lists of documents returning a union of the lists, with duplicates removed (based upon an 'id' match)
    Arguments:
        Any number of arrays of documents as a tuple of 'id', 'text', 'metadata'
    @returns: Array<(string, string, dict)> Single array of documents containing no duplicates
    """
    #Definitely not the most efficient de-duplication, but in this case, lists are typically <10 items
    documents = []
    for document_list in args:
        for document in document_list:
            if document[0] not in map(lambda doc: doc[0], documents):
                documents.append(document)
    return documents

Diese beiden Methoden ermöglichen die Extraktion relevanter Dokumente aus derselben Datenbanktabelle, wobei zwei verschiedene Mechanismen zur Bestimmung der Ähnlichkeit verwendet werden. Beide Methoden sind sehr schnell auszuführen, so dass es über den Textindex hinaus nur minimalen Overhead gibt, um beide Techniken anzuwenden, um relevante Dokumente abzurufen. Die semantische Suche ermöglicht das Abrufen von Dokumenten unabhängig von der Verwendung von Synonymen oder gelegentlichem Tippfehler, während die Suche nach Schlüsselwörtern Szenarien erfassen kann, in denen der Benutzer sehr spezifisch nach einem bestimmten Thema fragt, z. B. nach einem Produkt- oder Funktionsnamen. Die kombinierten Ergebnisse können sich ergänzen, um dem gesamten RAG-Prozess Robustheit zu verleihen.

Danksagungen

Weitere Lernressourcen

Sehen Sie sich andere Übungen zu docs.oracle.com/learn an, oder greifen Sie im Oracle Learning YouTube-Channel auf weitere kostenlose Lerninhalte zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.