Lojas e Esquema

Esta página apresenta as abstrações do armazenamento principal e os controles de esquema usados pelo SDK de Memória do Oracle Agent.

API da loja

Semântica de Gravação da Loja

As gravações de armazenamento mantêm uma separação clara entre o texto que um aplicativo armazena e o payload que o armazenamento usa para recuperação. A maioria dos aplicativos pode usar as APIs no nível da memória e do thread e permitir que o armazenamento prepare as linhas de pesquisa necessárias para recuperação de vetores, palavras-chave ou híbrida. As APIs de armazenamento de nível inferior expõem index_texts, index_text, embeddings e embedding para integrações avançadas que já sabem qual texto ou vetores devem ser usados para recuperação.

Pense em cada escrita como duas partes relacionadas:

Se nenhuma substituição de pesquisa ou incorporação explícita for fornecida, o armazenamento usará o texto armazenado resolvido como o texto de recuperação. O texto não vazio é dividido pela loja quando a divisão em blocos é configurada. O texto vazio armazena o texto do registro, mas não fornece texto de recuperação.

A tabela abaixo descreve como o texto de recuperação é escolhido antes que os payloads vetoriais explícitos sejam considerados.

Payloads de recuperação no nível da loja

Entrada add() update()
index_texts ou index_text omitido Cada registro usa seu valor contents resolvido para recuperação. Um valor text de substituição é usado para recuperação. Se text também for omitido, as atualizações somente incorporação reutilizarão as linhas de texto de recuperação existentes do registro.
String index_texts entrada ou string index_text A string substitui o texto de recuperação desse registro. O armazenamento pode separá-lo antes de gravar linhas de recuperação. A string substitui o texto de recuperação desse registro. O armazenamento pode separá-lo antes de gravar linhas de recuperação.
Entrada list[str] index_texts ou list[str] index_text A lista é tratada como chunks de propriedade do chamador. Cada string não vazia é gravada como uma linha de recuperação e o armazenamento não a divide novamente. A lista é tratada como chunks de propriedade do chamador. Cada string não vazia é gravada como uma linha de recuperação e o armazenamento não a divide novamente.
Entrada None index_texts ou index_text=None None na lista externa index_texts significa "usar o conteúdo armazenado para este registro". index_text=None limpa as linhas de recuperação ao deixar o texto armazenado inalterado, a menos que text também seja fornecido.
String vazia ou lista de partes vazia Armazena o texto do registro e não fornece nenhum texto de recuperação para esse registro. Atualiza o texto do registro quando o text é fornecido e limpa o texto de recuperação desse registro.

As incorporações explícitas são opcionais. Quando eles são omitidos, o armazenamento deriva vetores locais do texto de recuperação quando o armazenamento vetorial local é configurado; os armazenamentos de palavras-chave ou híbridos também podem usar linhas de recuperação somente texto. Quando valores embeddings ou embedding explícitos são fornecidos, o armazenamento grava esses vetores diretamente e não chama seu incorporador para esses vetores.

No add(), embeddings=None se comporta como omitir embeddings. No update(), embedding=None é explícito: o armazenamento mantém ou reescreve o texto de recuperação de acordo com text e index_text, mas armazena essas linhas sem vetores locais. Se text e index_text forem omitidos, isso limpará os vetores das linhas de recuperação existentes.

A forma do vetor informa à loja a quantidade de propriedade de chunk que o chamador está tomando:

Algumas combinações são rejeitadas, portanto, o texto armazenado, o texto de recuperação e os vetores não se afastam. A aprovação de text=None limpa linhas de texto e recuperação armazenadas, de modo que não pode ser combinada com valores index_text ou embedding não nulos; os registros de perfil do ator não suportam text=None. Passar index_text=None em update() significa "limpar linhas de recuperação", portanto, incorporações explícitas não vazias não são permitidas na mesma chamada. Vários vetores explícitos exigem texto em bloco explícito, a menos que a atualização seja somente incorporação e as linhas de recuperação existentes já forneçam o texto em bloco.

classe oracleagentmemory.core.OracleMemoryStore

Bases: IMemoryStore

Interface de armazenamento comum usada pelo OracleAgentMemory.

Uma implementação de loja é responsável por persistir registros de texto e executar uma pesquisa de similaridade sobre eles. Os pontos de entrada síncronos e assíncronos são definidos para que as APIs de nível superior possam expor superfícies síncronas/assíncronas correspondentes sem duplicar a lógica específica da loja.

método add

Adicionar registros à loja.

Observações

Use add_batches() quando o chamador já tiver um ou mais objetos PendingRecordBatch.

method add_agent (abstract)

Adicionar um registro de perfil do agente.

método add_async (assíncrono)

Adicione registros orientados por linha de forma assíncrona à loja.

Aceita os mesmos argumentos e retorna os mesmos identificadores que add().

método add_batches

Adicione lotes lógicos preparados pelo chamador à loja.

Exemplos de

store.add_batches(
    [
        PendingRecordBatch(
            texts=["pizza batch"],
            record_type="memory",
            record_ids="mem-batch-docs",
        )
    ]
)
['mem-batch-docs']

método add_batches_async (assíncrono)

Adicione lotes lógicos preparados pelo chamador de forma assíncrona ao armazenamento.

Aceita os mesmos argumentos e retorna os mesmos identificadores que add_batches().

method add_user (abstract)

Adicionar um registro de perfil de usuário.

method delete (abstract)

Excluir um registro armazenado por identificador.

method delete_thread (abstract)

Exclua um thread e seus dados armazenados associados.

Observações

Esta é a operação no nível do armazenamento para remover um thread e os registros no escopo do thread gerenciados pelo armazenamento. Prefira a exclusão de thread quando os requisitos de retenção exigirem a exclusão de mensagens de origem e de dados de memória com escopo de thread derivado, porque as exclusões no nível da mensagem não implicam que registros derivados persistidos separadamente sejam removidos.

method get (abstract)

Recuperar um registro armazenado por tipo e identificador.

method list (abstract)

Listar registros armazenados para um tipo de registro.

method list_thread_messages (abstract)

Liste o histórico de mensagens armazenado para um tópico.

method search (abstract)

Pesquisar registros por similaridade.

Exemplos de

store.add(
    ["Searchable abstract memory"],
    record_type="memory",
    record_ids="mem-search-abstract-docs",
)
['mem-search-abstract-docs']
store.search("Searchable", 1, record_types={"memory"})[0][0].id
'mem-search-abstract-docs'

Filtrar em um valor de metadados escalar:

store.add(
    ["pizza release"],
    record_type="memory",
    record_ids="mem-search-meta-source-docs",
    metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
    record.id == "mem-search-meta-source-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"source": "slack"},
    )
)
True

Filtrar em metadados aninhados:

store.add(
    ["pizza review"],
    record_type="memory",
    record_ids="mem-search-meta-review-docs",
    metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
    record.id == "mem-search-meta-review-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"review": {"status": "open"}},
    )
)
True

Corresponder exatamente um valor de lista, incluindo a ordem:

store.add(
    ["pizza tags"],
    record_type="memory",
    record_ids="mem-search-meta-tags-docs",
    metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": ["prod", "urgent"]},
    )
)
True

Filtre quando um array de metadados contiver um valor:

any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": {"$array_contains": "prod"}},
    )
)
True

Combine várias condições de metadados. Um registro deve atender a todas as chaves:

store.add(
    ["pizza rollout"],
    record_type="memory",
    record_ids="mem-search-meta-combined-docs",
    metadata={
        "source": "slack",
        "review": {"status": "open"},
        "tags": ["prod", "urgent"],
    },
)
['mem-search-meta-combined-docs']
any(
    record.id == "mem-search-meta-combined-docs"
    for record, _ in store.search(
        "pizza",
        k=5,
        metadata_filter={
            "source": "slack",
            "review": {"status": "open"},
            "tags": ["prod", "urgent"],
        },
    )
)
True

método search_async (assíncrono)

Pesquise registros de forma assíncrona por similaridade semântica.

method update (abstract)

Atualize o conteúdo do registro armazenado, incorporando dados, metadados, timestamp ou expiração.

Armazenamento do Oracle DB

classe oracleagentmemory.core.OracleDBMemoryStore

Bases: OracleMemoryStore

Persistência baseada em banco de dados para mensagens, memórias e perfis de atores.

Crie um armazenamento do Oracle DB.

Advertência: SchemaPolicy.CREATE_IF_NECESSARY pode ser mais caro do que a inicialização normal do armazenamento porque pode aplicar DDL de esquema gerenciado e regravações de dados de melhor esforço antes que a inicialização seja bem-sucedida. Planeje a primeira abertura de um esquema gerenciado mais antigo como uma operação de migração ou manutenção quando esse esquema pode conter muitas linhas.

Se a configuração do esquema precisar criar o job de expurgação de registro expirado gerenciado, mas o usuário do banco de dados não tiver o privilégio scheduler-job, a inicialização avisará e continuará. As mensagens e memórias expiradas permanecem ocultas de leituras e pesquisas, mas elas não são expurgadas fisicamente até que o job seja criado por um usuário com o privilégio CREATE JOB ou um scheduler equivalente.

Quando o SchemaPolicy.CREATE_IF_NECESSARY cria pela primeira vez um índice híbrido gerenciado em um esquema existente, o sistema Oracle verifica o texto de pesquisa armazenado e cria o estado de índice híbrido gerenciado com base no modelo configurado no banco de dados. Como a inicialização do armazenamento aguarda a conclusão desse DDL, planeje o primeiro upgrade híbrido como uma operação de migração ou manutenção para grandes esquemas. SearchIndexSyncMode controla a manutenção contínua após a existência do índice; ele não torna a primeira criação de índice assíncrona.

A criação desse índice híbrido gerenciado também cria uma preferência do vetorizador DBMS_VECTOR_CHAIN nomeada pelo esquema gerenciado. A preferência armazena metadados de configuração do vetorizador leves do modelo OracleDBEmbedder configurado. Ele pode ser inspecionado com as exibições de preferência do Oracle Text, como CTX_USER_PREFERENCES e CTX_USER_PREFERENCE_VALUES.

método add

Adicione registros ao armazenamento do Oracle DB.

Exemplos de

store.add(
    ["Index this stored text"],
    record_type="memory",
    record_ids="mem-db-add-docs",
)
['mem-db-add-docs']
store.add(
    ["Stored text"],
    record_type="memory",
    index_texts=["Search this text"],
    record_ids="mem-db-index-text-docs",
)
['mem-db-index-text-docs']
store.add(
    ["Short-lived event"],
    record_type="memory",
    record_ids="mem-db-ttl-docs",
    timestamps="2026-01-01T12:00:00+00:00",
    ttl_days=7,
    ttl_anchor=TimeToLiveAnchor.TIMESTAMP,
)
['mem-db-ttl-docs']

método add_agent

Adicionar um registro de perfil do agente.

Observações

Os registros de perfil do agente não têm escopo. O identificador de registro público inserido é o mesmo valor informado como agent_id.

Exemplos de

store.add_agent("a-docs-agent", "Support assistant")
'a-docs-agent'

método add_async (assíncrono)

Adicione registros orientados por linha de forma assíncrona à loja.

Aceita os mesmos argumentos e retorna os mesmos identificadores que add().

método add_batches

Adicione lotes lógicos preparados pelo chamador à loja.

Exemplos de

store.add_batches(
    [
        PendingRecordBatch(
            texts=["pizza batch"],
            record_type="memory",
            record_ids="mem-batch-docs",
        )
    ]
)
['mem-batch-docs']

método add_batches_async (assíncrono)

Adicione lotes lógicos preparados pelo chamador de forma assíncrona ao armazenamento.

Aceita os mesmos argumentos e retorna os mesmos identificadores que add_batches().

método add_user

Adicionar um registro de perfil de usuário.

Observações

Os registros de perfil do usuário não têm escopo. O identificador de registro público inserido é o mesmo valor informado como user_id.

Exemplos de

store.add_user("u-docs-profile", "Prefers concise answers.")
'u-docs-profile'

método delete

Excluir uma linha gerenciada e suas linhas de bloco por identificador.

Observações

A operação é executada dentro de uma transação. Quando cascade está ativado para um destino de nível superior suportado, a exclusão do perfil e todas as exclusões filho com escopo são submetidas a commit ou submetidas a rollback juntas.

Exemplos de

store.add(["Delete me"], record_type="memory", record_ids="mem-delete-docs")
['mem-delete-docs']
store.delete("memory", "mem-delete-docs")
1

método delete_thread

Excluir um thread e suas linhas armazenadas associadas.

Observações

Use esta operação quando precisar de limpeza em cascata com escopo de thread. No armazenamento suportado pelo BD, a exclusão do thread remove a linha do thread gerenciado juntamente com as linhas de mensagem e memória associadas, além dos dados de pesquisa mantidos para recuperação. Isso é mais amplo do que uma exclusão no nível da mensagem, o que remove apenas a linha da mensagem bruta. A exclusão do thread remove as linhas dependentes de mensagem e memória junto com seus dados de recuperação associados na mesma transação.

Exemplos de

store.delete_thread("c1")
0

método get

Recuperar um registro armazenado por identificador.

Exemplos de

store.add(["Remember this"], record_type="memory", record_ids="mem-get-docs")
['mem-get-docs']
store.get("memory", "mem-get-docs").id
'mem-get-docs'

método list

Enumerar registros persistidos para um tipo de registro.

Observações

"user_profile" e "agent_profile" são tipos de registro sem escopo. Para esses tipos de registro, thread_id, user_id e agent_id são ignorados e a identidade do ator permanece na record.id.

Exemplos de

store.add(
    ["First listed", "Second listed"],
    record_type="memory",
    record_ids=["mem-list-docs-1", "mem-list-docs-2"],
)
['mem-list-docs-1', 'mem-list-docs-2']
[record.id for record in store.list("memory", limit=2)]
['mem-list-docs-1', 'mem-list-docs-2']
store.add_user("u-list-docs", "Prefers concise answers.")
'u-list-docs'
any(
    record.id == "u-list-docs"
    for record in store.list("user_profile", user_id=None, limit=10)
)
True

método list_thread_messages

Retornar mensagens persistidas para um tópico.

Exemplos de

store.list_thread_messages("c1")
[]

Pesquisar registros por similaridade.

O backend de pesquisa ativo depende do SearchStrategy configurado do armazenamento. SearchStrategy.VECTOR classifica o vetor de consulta em relação aos vetores de registro armazenados. SearchStrategy.HYBRID consulta o índice híbrido gerenciado da Oracle pelo texto de pesquisa armazenado e seu estado de índice gerenciado. SearchStrategy.KEYWORD classifica apenas por texto correspondente ao texto de pesquisa armazenado.

Exemplos de

store.add(
    ["pizza preference"],
    record_type="memory",
    record_ids="mem-search-docs",
    thread_ids="c-search-docs",
)
['mem-search-docs']
results = store.search(
    "pizza",
    1,
    thread_id="c-search-docs",
    exact_thread_match=True,
    record_types={"memory"},
)
results[0][0].id
'mem-search-docs'

Filtrar em um valor de metadados escalar:

store.add(
    ["pizza release"],
    record_type="memory",
    record_ids="mem-search-meta-source-docs",
    metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
    record.id == "mem-search-meta-source-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"source": "slack"},
    )
)
True

Filtrar em metadados aninhados:

store.add(
    ["pizza review"],
    record_type="memory",
    record_ids="mem-search-meta-review-docs",
    metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
    record.id == "mem-search-meta-review-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"review": {"status": "open"}},
    )
)
True

Corresponder exatamente um valor de lista, incluindo a ordem:

store.add(
    ["pizza tags"],
    record_type="memory",
    record_ids="mem-search-meta-tags-docs",
    metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": ["prod", "urgent"]},
    )
)
True

Filtre quando um array de metadados contiver um valor:

any(
    record.id == "mem-search-meta-tags-docs"
    for record, _ in store.search(
        "pizza",
        k=3,
        metadata_filter={"tags": {"$array_contains": "prod"}},
    )
)
True

Combine várias condições de metadados. Um registro deve atender a todas as chaves:

store.add(
    ["pizza rollout"],
    record_type="memory",
    record_ids="mem-search-meta-combined-docs",
    metadata={
        "source": "slack",
        "review": {"status": "open"},
        "tags": ["prod", "urgent"],
    },
)
['mem-search-meta-combined-docs']
any(
    record.id == "mem-search-meta-combined-docs"
    for record, _ in store.search(
        "pizza",
        k=5,
        metadata_filter={
            "source": "slack",
            "review": {"status": "open"},
            "tags": ["prod", "urgent"],
        },
    )
)
True

método search_async (assíncrono)

Pesquise registros de forma assíncrona por similaridade semântica.

método update

Atualize o conteúdo do registro armazenado, o estado da pesquisa, os metadados e os valores de timestamp.

Exemplos de

store.add(["Original note"], record_type="memory", record_ids="mem-update-docs")
['mem-update-docs']
store.update("memory", "mem-update-docs", text="Updated note")
1
store.get("memory", "mem-update-docs").content
'Updated note'

Estratégia de Pesquisa

classe oracleagentmemory.core.dbsearch.SearchStrategy

Bases: Enum

Comportamento de pesquisa para armazenamentos do Oracle DB.

A inicialização do armazenamento do BD usa a estratégia selecionada para escolher o recurso de pesquisa de esquema gerenciado. A pesquisa VECTOR armazena incorporações locais. A pesquisa KEYWORD armazena texto pesquisável e um índice de texto. A pesquisa HYBRID armazena texto pesquisável mais o estado de índice vetorial híbrido gerenciado pela Oracle. O armazenamento do BD valida esse recurso de esquema na inicialização para que uma estratégia incompatível não retorne resultados incompletos silenciosamente.

VECTOR
Pesquisar apenas por similaridade vetorial. O armazenamento incorpora a consulta ao incorporador configurado ou usa um query_vector fornecido pelo chamador e classifica os registros pela distância dos vetores armazenados. Use isso com um esquema de banco de dados configurado para pesquisa de vetor.
HYBRID
Pesquise com o índice híbrido gerenciado da Oracle. A Oracle combina correspondência de texto em relação ao texto de pesquisa armazenado com classificação vetorial do índice híbrido no banco de dados. Use-o quando os usuários puderem pesquisar por linguagem natural, bem como identificadores exatos, aliases ou nomes de produtos. Essa estratégia requer que o principal incorporador da loja seja um OracleDBEmbedder para que o índice gerenciado e o armazenamento compartilhem um modelo no banco de dados.
KEYWORD
Pesquise somente por palavra-chave/texto correspondente ao texto de pesquisa armazenado. Esse modo não cria incorporações de consulta local e não precisa de um incorporador do Oracle DB. Quando aberto em um esquema híbrido existente, ele pode usar a ramificação de texto desse índice híbrido sem criar um novo índice híbrido. Use isso quando identificadores exatos, aliases, nomes de produtos ou frases curtas devem gerar recuperação sem fusão vetorial.

HÍBRIDO = 'híbrido'

KEYWORD = 'palavra-chave'

VECTOR = 'vetor'

Modo de sincronização de índice de pesquisa

classe oracleagentmemory.core.dbsearch.SearchIndexSyncMode

Bases: Enum

Comportamento de atualização para índices de pesquisa do BD gerenciado.

Essa definição controla quando o sistema Oracle torna o texto de pesquisa novo ou alterado visível para pesquisa com reconhecimento de texto suportada pelo BD. O SearchStrategy.HYBRID usa o índice vetorial híbrido gerenciado da Oracle. SearchStrategy.KEYWORD usa um índice do Oracle Text. SearchStrategy.VECTOR não usa essa definição.

ON_COMMIT
Atualize o índice quando a transação de gravação for confirmada. Esta é a opção padrão e mais simples para a maioria dos aplicativos porque os registros são pesquisáveis imediatamente após uma gravação bem-sucedida. Ele pode adicionar trabalho para gravar transações porque o índice é mantido atualizado imediatamente.
MANUAL
Não atualize o índice automaticamente. Registros novos ou atualizados podem não aparecer na pesquisa por palavra-chave ou híbrida até que você mesmo execute a operação de sincronização de índice do banco de dados. Isso é útil para cargas em massa ou janelas de manutenção nas quais você deseja controlar ao atualizar execuções de trabalho.
AUTO
Permitir que a Oracle atualize o índice híbrido gerenciado de forma assíncrona. As gravações podem evitar o custo de atualização imediato, mas os resultados da pesquisa podem ficar atrás das gravações recentes até que a Oracle conclua a atualização em segundo plano. Este modo é suportado somente com SearchStrategy.HYBRID.

Aviso: Esta configuração controla a manutenção contínua após a existência do índice de pesquisa gerenciado. Ele não torna a primeira compilação de índice assíncrona. A criação de um índice híbrido gerenciado sobre o texto de pesquisa armazenado existente pode ser de longa execução porque a Oracle cria o estado de índice híbrido gerenciado com base nesse texto.

AUTO = 'AUTO'

MANUAL = 'MANUAL'

ON_COMMIT = 'ON_COMMIT'

Tempo de Vida Útil

classe oracleagentmemory.core.retention.MemoryRetentionConfig

Bases: object

Definições de retenção no nível do esquema para registros com suporte do Oracle DB.

classe oracleagentmemory.apis.ttl.TimeToLiveAnchor

Bases: Enum

Âncora usada para calcular um timestamp de expiração de uma duração de tempo de vida.

CREATED_AT
Expiração de computação do timestamp de criação do banco de dados do registro. Este é o padrão quando os chamadores omitem ttl_anchor.
TIMESTAMP
Calcular expiração do timestamp de evento armazenado do registro. Use esta opção quando uma mensagem ou memória representar um evento mais antigo e deve expirar em relação a esse horário de evento em vez de inserir o tempo.

CREATED_AT = 'criated_at'

TIMESTAMP = 'TIMESTAMP'

Política de Esquema

classe oracleagentmemory.core.SchemaPolicy

Bases: str, Enum

Política de criação de esquema para armazenamentos do Oracle DB.

REQUER_EXISTENTE

Valide se o esquema gerenciado completo já existe e está atualizado. Não crie ou modifique objetos do BD.

CRIAR_SE_VAZIO

Se não houver objetos gerenciados, o esquema de bootstrap. Se já existirem objetos, exija um esquema gerenciado completo e atualizado.

CRIAR_IF_NECESSÁRIO

Crie objetos gerenciados ausentes e aplique upgrades de esquema gerenciado suportados.

RECRIAR

Elimine e recrie todos os objetos de esquema gerenciados. Isso é destrutivo.