Criar e pesquisar gráficos de memória vinculados
Os links de memória conectam registros semelhantes à memória relacionados, preservando os registros históricos. Use-os quando uma memória mais nova substituir ou refinar uma mais antiga, ou quando duas memórias suportarem, duplicarem ou se contradizerem. A vinculação automática de memória cria esses links como parte da extração automática de memória; a vinculação manual permanece disponível quando um aplicativo já conhece o relacionamento.
Este guia cria automaticamente um pequeno gráfico de preferências de pizza, mostra como gerenciar links explicitamente quando necessário e recupera o contexto do gráfico com a pesquisa.
Configurar um Cliente do Linked-Memory
Crie um cliente OracleAgentMemory normal. Na primeira execução, use SchemaPolicy.CREATE_IF_NECESSARY para que o SDK crie todos os objetos de banco de dados gerenciados, incluindo o armazenamento de relação de memória e o gráfico de propriedades.
import oracledb
from oracleagentmemory.core import (
MemoryExtractionConfig,
OracleAgentMemory,
OracleSearchResultFormatConfig,
SchemaPolicy,
)
from oracleagentmemory.core.embedders.embedder import Embedder
embedder = Embedder(model="YOUR_EMBEDDING_MODEL")
db_pool = oracledb.SessionPool(
user="YOUR DB USER",
password="YOUR DB PASSWORD",
dsn="localhost:1521/...",
)
memory_store_id = "T_GRAPH_MEMORY"
memory = OracleAgentMemory(
connection=db_pool,
embedder=embedder,
schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
memory_store_id=memory_store_id,
memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
)
user_id = "graph-demo-user"
Vincular memórias automaticamente durante a extração
Para a maioria dos aplicativos, ative a extração automática e permita que o SDK identifique links à medida que extrai novas memórias do add_messages(). O modo de link padrão, POST_EXTRACTION, extrai memórias primeiro, recupera um conjunto limitado de candidatos existentes para cada nova memória e usa uma solicitação adicional de LLM para decidir se um link digitado deve ser criado. Isso dá à resolução do link seu próprio contexto e é o modo recomendado quando a qualidade do link é importante.
Configure o modo por meio de MemoryExtractionConfig no nível do cliente ou do thread. O thread a seguir extrai após cada mensagem adicionada e resolve os links após a extração. O cliente OracleAgentMemory também deve ser configurado com um LLM de extração.
from oracleagentmemory.core import (
MemoryExtractionConfig,
MemoryLinkExtractionMode,
)
preference_thread = memory.create_thread(
thread_id="pizza-preferences",
user_id=user_id,
memory_extraction_config=MemoryExtractionConfig(
extract_memories=True,
memory_extraction_frequency=1,
memory_link_extraction_mode=MemoryLinkExtractionMode.POST_EXTRACTION,
),
)
preference_thread.add_messages(
[{"role": "user", "content": "I now prefer sourdough pizza."}]
)
Por exemplo, quando o thread já contém uma memória que o usuário prefere thin crust, o vinculador pode extrair a nova preferência sourdough e criar um link supersedes para a memória mais antiga. Os tipos de link do ciclo de vida, como supersedes, refines e duplicates, mantêm a memória antiga como histórico e a marcam como inválida; a pesquisa de gráfico ainda pode retorná-la como contexto vinculado.
DURING_EXTRACTION solicita ao LLM de extração para identificar links na mesma solicitação que extrai memórias, o que evita a solicitação adicional de resolução de links. Seus candidatos são limitados pela busca de extração. Defina memory_link_extraction_mode=MemoryLinkExtractionMode.DISABLED para desativar a vinculação automática. Nenhum dos modos automáticos tenta descobrir todos os relacionamentos possíveis na loja, portanto, use links explícitos para um relacionamento que deve ser registrado.
Criar Memórias Vinculadas Manualmente
Crie memórias normalmente e conecte-as com link_records(). Uma relação é direcionada: sua origem aponta para seu destino. supersedes, refines e duplicates tornam o destino inválido; supports e contradicts deixam ambas as memórias de ponto final válidas.
Selecione um Tipo de Link
Para a evolução da memória, a origem é normalmente a memória mais recente e o destino é a memória existente. Selecione o tipo de vínculo que descreve esse relacionamento.
| Tipo de link | Usar quando a memória fonte… | Efeito na memória de destino |
|---|---|---|
supersedes |
Substitui o alvo como a informação atual. Por exemplo, uma nova preferência substitui uma preferência anterior. | Torna-se inválido, mas permanece disponível como histórico. |
refines |
Mantém as informações do alvo ao adicionar detalhes ou precisão. Por exemplo, uma preferência de caminhada específica refina uma preferência geral. | Torna-se inválido, mas permanece disponível como histórico. |
duplicates |
Tem o mesmo significado que o alvo. A origem é a cópia preferencial. | Torna-se inválido para evitar resultados diretos duplicados. |
supports |
Fornece evidências para o alvo. Por exemplo, evitar carne e peixe suporta uma preferência vegetariana. | Permanece inalterado. |
contradicts |
Em conflito com o destino, mas o SDK não pode determinar qual memória está correta. | Permanece inalterado. |
A pesquisa de gráfico segue cada link em qualquer direção. Quando ele passa do destino para a origem, exibe o label reverso correspondente, como is_superseded_by ou is_refined_by.
thin_crust_id = memory.add_memory(
"The user's preferred pizza style is thin crust.",
memory_id="pizza-thin-crust",
memory_type="preference",
user_id=user_id,
)
sourdough_id = memory.add_memory(
"The user now prefers sourdough pizza.",
memory_id="pizza-sourdough",
memory_type="preference",
user_id=user_id,
)
neapolitan_id = memory.add_memory(
"The user's preferred pizza style is sourdough, especially Neapolitan sourdough.",
memory_id="pizza-neapolitan-sourdough",
memory_type="preference",
user_id=user_id,
)
supersedes_link_id = memory.link_records(
source_record_id=sourdough_id,
source_record_type="preference",
target_record_id=thin_crust_id,
target_record_type="preference",
relation_type="supersedes",
)
memory.link_records(
source_record_id=neapolitan_id,
source_record_type="preference",
target_record_id=sourdough_id,
target_record_type="preference",
relation_type="refines",
)
A pesquisa segue um link em qualquer direção, mantendo sua direção armazenada no resultado.
Editar e Excluir Links
Use o ID da relação retornado por link_records() para atualizar uma relação. Os campos omitidos permanecem inalterados. A atualização de um tipo de relação recalcula os status do ponto final, de modo que um link de ciclo de vida anterior não deixa mais uma memória inválida quando seu tipo de substituição não tem efeitos de ciclo de vida.
Exclua uma relação por seu ID de relação ou por sua tupla completa de ponto final direcionado: ID e tipo de origem, ID e tipo de destino e tipo de relação. A exclusão também recalcula os status do ponto final afetado.
#Changing a lifecycle link recalculates the status of both endpoint memories.
memory.update_record_link(
supersedes_link_id,
relation_type="supports",
metadata={"reviewed_by": "preference-service"},
)
#Delete by the stable relation ID.
memory.delete_record_link(relation_id=supersedes_link_id)
#Or delete by the complete directed relation triple.
memory.delete_record_link(
source_record_id=neapolitan_id,
source_record_type="preference",
target_record_id=sourdough_id,
target_record_type="preference",
relation_type="refines",
)
Pesquisar por Memórias Vinculadas
Defina num_hops para anexar contexto vinculado a cada resultado de memória direta. 0 é o padrão e retorna apenas resultados diretos; valores de 1 a 5 seguem tantos links. max_linked_results limita o total de memórias vinculadas anexadas a cada resultado direto em todos os saltos. O padrão é 100; defina-o como 0 para retornar resultados diretos sem contexto vinculado.
Os filtros de escopo, metadados, tipo de registro e expiração aplicam-se a memórias vinculadas. include_invalid_results aplica-se somente a resultados diretos de nível superior. O contexto de memória vinculada pode incluir registros históricos inválidos, independentemente dessa opção. Para valores num_hops positivos, o SDK segue links em ambas as direções e retorna o contexto vinculado como a árvore de caminho mais curto determinístico descrita na seção a seguir.
results = memory.search(
"What pizza should I recommend?",
user_id=user_id,
max_results=5,
num_hops=2,
max_linked_results=20,
include_invalid_results=False,
)
Cada resultado contém uma árvore recursiva de resultados vinculados. O SDK formata essa árvore usando o caminho disponível mais curto para cada memória vinculada. A travessia evita memórias repetidas em um caminho e seleciona um caminho mais curto determinístico quando caminhos alternativos atingem a mesma memória.
Formatar Contexto do Gráfico para um Prompt
Cada SearchResult expõe format_content() para renderizar um resultado direto e suas memórias vinculadas como texto de prompt estruturado. Por padrão, ele usa a definição include_invalid_results da pesquisa que produziu o resultado. Uma configuração de formatação fornecida substitui suas opções definidas explicitamente. Quando o conteúdo inválido é desativado, as memórias vinculadas inválidas omitem seu conteúdo. Registros inválidos que levam a uma memória vinculada válida mantêm seu status e contexto de link; ramificações somente inválidas são omitidas.
Use OracleSearchResultFormatConfig para adaptar a árvore renderizada. Este exemplo inclui conteúdo histórico inválido ao remover timestamps, funções e status para um prompt mais compacto. Você também pode incluir metadados, thread, identificadores de usuário ou agente e relevância estimada. Cada label de relação renderizada descreve a direção de pai para filho exibida, mesmo que RecordRelation mantenha sua direção armazenada.
format_config = OracleSearchResultFormatConfig(
include_invalid_results=True,
show_timestamp=False,
show_role=False,
show_status=False,
)
for result in results:
print(result.format_content(format_config))
Código Inteiro
O exemplo completo está incluído neste guia para você copiar e executar.
#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 - Create and Search Linked Memory Graphs
#-------------------------------------------------------------------------
##Create a graph memory client
import oracledb
from oracleagentmemory.core import (
MemoryExtractionConfig,
OracleAgentMemory,
OracleSearchResultFormatConfig,
SchemaPolicy,
)
from oracleagentmemory.core.embedders.embedder import Embedder
embedder = Embedder(model="YOUR_EMBEDDING_MODEL")
db_pool = oracledb.SessionPool(
user="YOUR DB USER",
password="YOUR DB PASSWORD",
dsn="localhost:1521/...",
)
memory_store_id = "T_GRAPH_MEMORY"
memory = OracleAgentMemory(
connection=db_pool,
embedder=embedder,
schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
memory_store_id=memory_store_id,
memory_extraction_config=MemoryExtractionConfig(extract_memories=False),
)
user_id = "graph-demo-user"
##Create linked memories
thin_crust_id = memory.add_memory(
"The user's preferred pizza style is thin crust.",
memory_id="pizza-thin-crust",
memory_type="preference",
user_id=user_id,
)
sourdough_id = memory.add_memory(
"The user now prefers sourdough pizza.",
memory_id="pizza-sourdough",
memory_type="preference",
user_id=user_id,
)
neapolitan_id = memory.add_memory(
"The user's preferred pizza style is sourdough, especially Neapolitan sourdough.",
memory_id="pizza-neapolitan-sourdough",
memory_type="preference",
user_id=user_id,
)
supersedes_link_id = memory.link_records(
source_record_id=sourdough_id,
source_record_type="preference",
target_record_id=thin_crust_id,
target_record_type="preference",
relation_type="supersedes",
)
memory.link_records(
source_record_id=neapolitan_id,
source_record_type="preference",
target_record_id=sourdough_id,
target_record_type="preference",
relation_type="refines",
)
##Edit and delete links
#Changing a lifecycle link recalculates the status of both endpoint memories.
memory.update_record_link(
supersedes_link_id,
relation_type="supports",
metadata={"reviewed_by": "preference-service"},
)
#Delete by the stable relation ID.
memory.delete_record_link(relation_id=supersedes_link_id)
#Or delete by the complete directed relation triple.
memory.delete_record_link(
source_record_id=neapolitan_id,
source_record_type="preference",
target_record_id=sourdough_id,
target_record_type="preference",
relation_type="refines",
)
#Recreate the example links for the search example.
memory.link_records(sourdough_id, "preference", thin_crust_id, "preference", "supersedes")
memory.link_records(neapolitan_id, "preference", sourdough_id, "preference", "refines")
##Search linked memories
results = memory.search(
"What pizza should I recommend?",
user_id=user_id,
max_results=5,
num_hops=2,
max_linked_results=20,
include_invalid_results=False,
)
##Format graph context for a prompt
format_config = OracleSearchResultFormatConfig(
include_invalid_results=True,
show_timestamp=False,
show_role=False,
show_status=False,
)
for result in results:
print(result.format_content(format_config))