Utiliser la recherche hybride de mémoire d'agent Oracle

La recherche sémantique permet de trouver des informations connexes même lorsque les requêtes utilisent des mots différents. La recherche par mot-clé permet de trouver des identificateurs, des noms et des expressions exacts que la recherche sémantique pourrait manquer.

Cet article explique comment utiliser la recherche hybride de mémoire d'agent Oracle avec Oracle Database.

La recherche hybride aide la mémoire de l'agent Oracle à rechercher des enregistrements en fonction de leur signification et du texte exact. Elle combine la recherche de texte gérée par Oracle avec un classement basé sur un vecteur, de sorte qu'une requête peut mettre en correspondance des identificateurs tels que des codes de problème, des noms de produit et des alias tout en bénéficiant d'une extraction sémantique.

Dans ce guide, vous allez :

Remarque : Utilisez la recherche hybride lorsque ni la recherche sémantique ni la recherche par mot-clé seules ne permettent une extraction fiable. La recherche hybride est plus utile lorsque les enregistrements contiennent à la fois du contenu descriptif et des termes exacts que les utilisateurs doivent trouver.

Conseil : pour la configuration des packages, reportez-vous à Introduction à la mémoire de l'agent. Si vous avez besoin d'une base de données Oracle locale pour cet exemple, suivez Exécuter Oracle AI Database localement.

Configurer un client Oracle Hybrid Search

Créez un client de mémoire d'agent Oracle avec la recherche hybride activée. Le client stocke les enregistrements dans Oracle Database et demande à Oracle d'utiliser un index vectoriel hybride géré pour la recherche.

Utilisez SchemaPolicy.CREATE_IF_NECESSARY lorsque vous activez la recherche hybride pour la première fois. Cela permet au kit SDK d'ajouter les colonnes de recherche gérée et de créer l'index hybride s'ils n'existent pas déjà.

Utilisez SearchStrategy.HYBRID lorsque vous voulez qu'Oracle combine le classement par mot-clé et par vecteur. La recherche hybride requiert une valeur OracleDBEmbedder en tant que valeur embedder principale du client, de sorte que le magasin et l'index vectoriel hybride géré par Oracle partagent le même modèle dans la base de données.

Si vous voulez que le texte corresponde uniquement, utilisez plutôt SearchStrategy.KEYWORD. La section suivante présente cette configuration.

Important : ce guide requiert oracleagentmemory 26.6.0 ou une version plus récente. Si votre schéma géré a été créé par une version antérieure, démarrez l'application une fois avec SchemaPolicy.CREATE_IF_NECESSARY. Ces mises à niveau prennent en charge les anciens schémas publiés et ajoutent les objets de recherche requis par la stratégie sélectionnée. Cette première mise à niveau peut effectuer des opérations LDD gérées et des réécritures de données. Il s'agit donc d'une étape de migration planifiée au lieu d'un démarrage normal peu coûteux. Une fois le schéma prêt, vous pouvez revenir à SchemaPolicy.REQUIRE_EXISTING pour un démarrage normal.

Les schémas de développement ou partiellement mis à jour qui revendiquent déjà la forme de version actuelle ne sont pas terminés en place ; recréez-les à la place.

Si vous utilisez SchemaPolicy.REQUIRE_EXISTING avant la mise à niveau du schéma, la création du client échoue et vous indique les objets de recherche gérés manquants.

Une fois qu'un schéma est initialisé ou mis à niveau pour une recherche par mot-clé ou hybride, ne le rouvrez pas avec SearchStrategy.VECTOR, sauf si vous recréez le schéma ou exécutez une fonction de remplissage d'intégration. Les lignes écrites par un mot-clé ou des clients hybrides peuvent ne pas contenir d'intégrations locales, de sorte que la recherche vectorielle pourrait manquer des enregistrements.

Avertissement : la création de l'index hybride pour un schéma existant peut prendre du temps. Oracle doit analyser le texte de recherche stocké existant et créer l'état de texte/vecteur d'index hybride géré à partir du modèle dans la base de données configuré. SchemaPolicy.CREATE_IF_NECESSARY attend la fin de ce DDL avant le retour du démarrage du client. Exécutez donc la première mise à niveau hybride en tant qu'opération de migration ou de maintenance planifiée pour les schémas volumineux.

Remarque : lorsque le kit SDK crée un index de vecteur hybride géré, il crée également une préférence de vecteur DBMS_VECTOR_CHAIN nommée par le schéma géré. La préférence stocke la configuration de vecteur à partir du modèle OracleDBEmbedder configuré et est censée être des métadonnées légères. Le nom de préférence généré est déterministe pour le schéma géré et suit le préfixe de nom de table configuré lorsqu'il correspond à la limite de nom de préférence d'Oracle Text. Vous pouvez inspecter les préférences à l'aide des vues Oracle Text telles que CTX_USER_PREFERENCES et CTX_USER_PREFERENCE_VALUES.

Remarque : cet exemple utilise OracleDBEmbedder. Oracle utilise le modèle intégré à la base de données de l'intégrateur lorsqu'il crée l'index hybride, de sorte que l'intégrateur principal et l'index hybride partagent un modèle de base de données.

L'exemple utilise également SearchIndexSyncMode.ON_COMMIT. Cela maintient l'index hybride à jour après chaque écriture validée, de sorte que les mémoires nouvellement ajoutées peuvent être recherchées immédiatement. Utilisez SearchIndexSyncMode.MANUAL lorsque vous prévoyez d'exécuter vous-même la synchronisation d'index de recherche ou SearchIndexSyncMode.AUTO lorsque vous voulez qu'Oracle actualise l'index hybride en arrière-plan et tolère que les résultats de recherche accusent un retard par rapport aux écritures récentes. Ce paramètre s'applique à la maintenance continue après l'existence de l'index de recherche initial ; il ne rend pas le premier build d'index asynchrone.

import oracledb

from oracleagentmemory.core import (
    MemoryExtractionConfig,
    OracleAgentMemory,
    SchemaPolicy,
    SearchIndexSyncMode,
    SearchStrategy,
)
from oracleagentmemory.core.embedders import OracleDBEmbedder


db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)

db_embedder = OracleDBEmbedder(
    connection=db_pool,
    model="YOUR_DB_EMBEDDING_MODEL",
    embedding_dimension=384,
)

memory = OracleAgentMemory(
    connection=db_pool,
    embedder=db_embedder,
    memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    search_strategy=SearchStrategy.HYBRID,
    search_index_sync=SearchIndexSyncMode.ON_COMMIT,
)
Référence d'API : OracleAgentMemory OracleDBEmbedder Stratégie de schéma Stratégie de recherche Rechercher un mode de synchronisation d'index

Utiliser la recherche par mot-clé uniquement

Utilisez SearchStrategy.KEYWORD lorsque vous voulez que la recherche corresponde aux mots stockés, aux identificateurs, aux alias, aux noms de produit ou aux expressions courtes, et que vous ne voulez pas de classement vectoriel. La recherche par mot-clé lit le même texte de recherche stocké que celui utilisé par la recherche hybride, mais elle n'utilise pas la fusion vectorielle.

La recherche par mot-clé ne nécessite pas d'intégrateur Python. Si le kit SDK doit créer des objets de recherche pour un schéma de mot-clé, il crée un index Oracle Text sur le texte de recherche stocké. SearchIndexSyncMode.ON_COMMIT et SearchIndexSyncMode.MANUAL contrôlent l'actualisation de l'index de texte du mot-clé.

keyword_memory = OracleAgentMemory(
    connection=db_pool,
    memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    search_strategy=SearchStrategy.KEYWORD,
)

Les mêmes appels add_memory() et search() présentés ci-dessous fonctionnent avec SearchStrategy.KEYWORD. La différence est le classement : la recherche par mot clé renvoie des enregistrements basés sur la correspondance de texte uniquement, tandis que la recherche hybride combine la correspondance de texte avec le classement vectoriel.

Référence d'API : OracleAgentMemory Stratégie de recherche

Utiliser les stratégies de recherche compatibles

La première fois que le kit SDK crée ou met à niveau le schéma géré, il enregistre la façon dont les données d'extraction stockées sont préparées pour la recherche. Le mode enregistré est vérifié chaque fois qu'un client de base de données démarre. Cela empêche un client d'utiliser une stratégie qui pourrait manquer silencieusement des enregistrements.

Si la stratégie demandée est compatible avec le schéma mais ne correspond pas au mode enregistré, le kit SDK émet un avertissement. Le client peut toujours commencer, mais l'avertissement vous aide à remarquer la différence et à confirmer qu'elle est intentionnelle.

Avertissement : La première création de l'index hybride sur les données existantes peut être longue car Oracle construit l'état de l'index hybride géré à partir du texte de recherche stocké. SearchIndexSyncMode contrôle la maintenance d'index en cours après l'existence de l'index. Il ne rend pas le premier build asynchrone.

Utilisez SchemaPolicy.CREATE_IF_NECESSARY lorsque vous déplacez intentionnellement un schéma d'un vecteur à un mot-clé ou hybride, ou d'un mot-clé à un hybride. Utilisez SchemaPolicy.REQUIRE_EXISTING une fois le schéma prêt et vous souhaitez que le démarrage valide le schéma sans modifier les objets de base de données.

Référence d'API : SchemaPolicy Stratégie de recherche

Stocker une mémoire recherchable

Commencez par une mémoire normale. Avec l'API OracleAgentMemory.add_memory(), Oracle utilise le contenu de mémoire lui-même comme texte recherchable. C'est le chemin le plus simple et est généralement suffisant lorsque les utilisateurs recherchent des mots ou des phrases qui apparaissent déjà dans la mémoire.

user_id = "user_123"

memory.add_memory(
    "The user calls the Milan outage the renewal blocker.",
    user_id=user_id,
)

Référence d'API : OracleAgentMemory

Identifiants de magasin que les utilisateurs peuvent rechercher

Lorsque les utilisateurs peuvent effectuer une recherche par code d'émission, numéro de facture, nom de produit ou alias exact, incluez ce texte dans la mémoire que vous stockez. La recherche hybride peut alors correspondre au texte exact et toujours utiliser le classement vectoriel pour les requêtes en langage naturel.

Gardez la mémoire lisible. Une phrase courte qui inclut l'identifiant important est souvent suffisante. Dans cet exemple, les mémoires incluent des identificateurs de problème et de demande que les utilisateurs sont susceptibles de saisir ultérieurement.

memory.add_memory(
    "The follow-up fix for the Milan outage is the edge-cluster retry patch, "
    "tracked as ORA-27102.",
    user_id=user_id,
)

memory.add_memory(
    "The renewal request INV-48291 stays attached to the Milan blocker ORA-27102.",
    user_id=user_id,
)

Référence d'API : OracleAgentMemory

Rechercher par identificateur ou phrase

Utilisez l'API search() normale. La recherche hybride s'exécute derrière la même interface de recherche de mémoire d'agent Oracle. Vous pouvez donc continuer à utiliser les portées, les limites de résultats et les filtres de type d'enregistrement comme d'habitude.

La première requête recherche un code de problème exact stocké dans le texte de la mémoire. La seconde interrogation recherche une expression en langage naturel dans le même ensemble de mémoires.

for query in ["ORA-27102", "renewal blocker"]:
    print(f"\nSearch results for {query!r}:")
    results = memory.search(
        query=query,
        user_id=user_id,
        max_results=5,
        record_types=["memory"],
    )
    print_search_results(results)

Remarque : l'ordre des résultats de recherche peut varier en fonction des données stockées, de la configuration des index hybrides et du comportement d'évaluation Oracle. Dans les tests ou les démonstrations, vérifiez que les enregistrements attendus sont renvoyés plutôt que de compter sur un classement exact.

Référence d'API : OracleAgentMemory OracleSearchResult

Conclusion

Dans ce guide, vous avez activé la recherche hybride gérée par Oracle, vu à quel moment utiliser la recherche par mot-clé uniquement, stocké une mémoire standard, inclus des identificateurs pouvant faire l'objet d'une recherche dans le texte de la mémoire et interrogé les mémoires par identificateur exact et expression en langage naturel.

Après avoir appris à activer la recherche hybride dans Oracle DB, vous pouvez maintenant passer à Magasins et schéma.

Code complet

#Copyright © 2026 Oracle and/or its affiliates.
#This software is under the Apache License 2.0
#(LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
#(UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.

#Oracle Agent Memory Code Example - Oracle Hybrid Search
#-------------------------------------------------------

##Configure an Oracle hybrid search client

import oracledb

from oracleagentmemory.core import (
    MemoryExtractionConfig,
    OracleAgentMemory,
    SchemaPolicy,
    SearchIndexSyncMode,
    SearchStrategy,
)
from oracleagentmemory.core.embedders import OracleDBEmbedder


db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)

db_embedder = OracleDBEmbedder(
    connection=db_pool,
    model="YOUR_DB_EMBEDDING_MODEL",
    embedding_dimension=384,
)

memory = OracleAgentMemory(
    connection=db_pool,
    embedder=db_embedder,
    memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    search_strategy=SearchStrategy.HYBRID,
    search_index_sync=SearchIndexSyncMode.ON_COMMIT,
)



##Configure an Oracle keyword search client

keyword_memory = OracleAgentMemory(
    connection=db_pool,
    memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    search_strategy=SearchStrategy.KEYWORD,
)


def print_search_results(results: list) -> None:
    for result in results:
        print(f"- [{result.record.record_type}] {result.content}")



##Store a basic hybrid search memory

user_id = "user_123"

memory.add_memory(
    "The user calls the Milan outage the renewal blocker.",
    user_id=user_id,
)



##Store identifiers users may search for

memory.add_memory(
    "The follow-up fix for the Milan outage is the edge-cluster retry patch, "
    "tracked as ORA-27102.",
    user_id=user_id,
)

memory.add_memory(
    "The renewal request INV-48291 stays attached to the Milan blocker ORA-27102.",
    user_id=user_id,
)



##Search hybrid records by identifier or phrase

for query in ["ORA-27102", "renewal blocker"]:
    print(f"\nSearch results for {query!r}:")
    results = memory.search(
        query=query,
        user_id=user_id,
        max_results=5,
        record_types=["memory"],
    )
    print_search_results(results)