

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Memoria semantica a lungo termine per agenti LangGraph
<a name="ddb-langgraph-memory"></a>

LangGraph separa due tipi di stato dell'agente. Short-term lo stato è il thread di conversazione stesso, che un checkpointer persiste in modo che un thread possa riprenderlo, riprodurlo e ripristinarlo (vedi). [Utilizzo di DynamoDB come archivio di checkpoint per gli agenti LangGraph](ddb-langgraph-checkpoint.md) Long-term la memoria è ciò che l'agente conosce attraverso i thread e la LangGraph modella come un archivio: una superficie chiave-valore suddivisa in namespace su cui l'agente scrive deliberatamente e la legge in un secondo momento.

La `DynamoDBStore` classe, nel pacchetto [ langgraph-checkpoint-aws, è l'implementazione ](https://pypi.org/project/langgraph-checkpoint-aws/) DynamoDB di quell'archivio. Gestisce il lato chiave-valore con namespace gerarchici, Time to Live per le memorie obsolete in scadenza e filtri di base. Con un indice vettoriale configurato (vedi[Utilizzo degli indici vettoriali in DynamoDB](VectorSearch.md)), il suo `search()` metodo esegue una ricerca semantica: le memorie vengono incorporate in scrittura, indicizzate in modo asincrono e richiamate per significato, classificate per somiglianza, dalla stessa tabella che le contiene. Non esiste un database vettoriale separato da fornire e nessuna pipeline che copi i dati al suo interno.

## Prerequisiti
<a name="langgraph-memory-prerequisites"></a>
+ E Account AWS con il permesso di creare tabelle DynamoDB e richiamare modelli Amazon Bedrock
+ Accesso a un modello di incorporamento in Amazon Bedrock nella tua regione. Questi esempi utilizzano Amazon Titan Text Embeddings V2
+ Python 3.10 o successivo, con `langgraph-checkpoint-aws` 1.2.2 o successivo e `boto3` 1.43.64 o successivo (le versioni precedenti non hanno alcuna operazione) `boto3` `SearchVectors`

Installa le librerie usando pip:

```
pip install langgraph langgraph-checkpoint-aws langchain-aws
```

## Configura il negozio
<a name="langgraph-memory-setup"></a>

Configura il negozio con un `index` blocco e chiama`setup()`:

```
from langchain_aws import BedrockEmbeddings
from langgraph_checkpoint_aws import DynamoDBStore

store = DynamoDBStore(
    table_name="support-agent-memory",
    region_name="us-east-1",
    index={
        "embed": BedrockEmbeddings(model_id="amazon.titan-embed-text-v2:0"),
        "dims": 1024,
        "fields": ["text"],
        "distance_function": "COSINE",
    },
)

store.setup()
```

Vale la pena comprendere quattro impostazioni del `index` blocco:
+ `embed`accetta qualsiasi oggetto di LangChain incorporamento o un semplice callable che associa un elenco di stringhe a un elenco di vettori.
+ `dims`deve corrispondere alla dimensione di output del modello. Titan Text Embeddings V2 restituisce 1.024 dimensioni per impostazione predefinita. Se queste non sono d'accordo, l'archivio genera un errore di mancata corrispondenza delle dimensioni nominando entrambi i numeri alla prima scrittura, anziché scrivere vettori che l'indice non può utilizzare.
+ `fields`seleziona quali parti del valore vengono incorporate. Qui viene incorporato solo il `text` campo. L'impostazione predefinita`["$"]`, serializza l'intero valore in JSON e lo incorpora, il che è comodo ma incorpora anche gli attributi contabili.
+ `distance_function`il valore predefinito è e accetta anche e. `COSINE` `EUCLIDEAN` `DOT_PRODUCT`

`setup()`crea la tabella se è assente, allega l'indice vettoriale e abilita Time to Live se l'hai configurato. Su una tabella esistente, aggiunge solo ciò che manca, quindi le `DynamoDBStore` distribuzioni esistenti possono adottare la ricerca semantica senza ricreare la tabella o migrare gli elementi. Tieni presente che `setup()` non viene restituito finché l'indice non riporta `ACTIVE` e non viene più riempito: un indice che riporta `ACTIVE` mentre è ancora compilato a backfill rifiuta le chiamate. `SearchVectors` Su una nuova tabella vuota l'attesa è breve. Il retrofit su una tabella con elementi esistenti richiede il tempo necessario per il riempimento.

## Scrivi ricordi
<a name="langgraph-memory-write"></a>

Scrivere è una cosa ordinaria`put()`. L'incorporamento avviene per te:

```
namespace = ("memories", "acme-corp", "user-8812")

store.put(namespace, "mem-1", {
    "text": "Account runs a proxy that closes idle sockets after 60 seconds",
    "source": "ticket-4471",
})
store.put(namespace, "mem-2", {
    "text": "Customer prefers email, asked not to be called by phone",
    "source": "ticket-4471",
})
store.put(namespace, "mem-3", {
    "text": "Uses a custom build of the SDK pinned to version 2.14",
    "source": "ticket-4502",
})
```

## Richiama per significato
<a name="langgraph-memory-recall"></a>

Il cliente apre una nuova conversazione e afferma che la connessione continua a interrompersi dopo circa un minuto:

```
results = store.search(
    namespace,
    query="connection drops after a minute of inactivity",
    limit=3,
)

for item in results:
    print(round(item.score, 3), item.value["text"])
```

Output:

```
0.324 Account runs a proxy that closes idle sockets after 60 seconds
0.039 Customer prefers email, asked not to be called by phone
0.031 Uses a custom build of the SDK pinned to version 2.14
```

La memoria pertinente è al primo posto e nessuna chiave nella query corrisponde a nulla. `SearchItem.score`segue la LangGraph convenzione in cui più alto è più rilevante. DynamoDB restituisce una distanza, dove minore è più vicina, quindi l'archivio esegue la conversione: perché `COSINE` il punteggio è`1 - distance`, `EUCLIDEAN` perché lo è`1 / (1 + distance)`, e i `DOT_PRODUCT` punteggi rimangono invariati. Se prendi in considerazione un punteggio assoluto per decidere se una memoria è sufficientemente rilevante da poter essere inserita in un prompt, calibra tale soglia in base ai tuoi dati e alla funzione di distanza scelta.

## Ambito di memoria con lo schema di ricerca
<a name="langgraph-memory-scoping"></a>

Quando `DynamoDBStore` crea l'indice vettoriale, dichiara la chiave di partizione della tabella come `HASH` elemento nello schema di ricerca dell'indice. Poiché tale elemento esiste, ogni ricerca deve fornire una condizione e l'archivio fornisce lo spazio dei nomi: la tupla dello spazio dei nomi viene unita per formare il valore della chiave di partizione, quindi ogni ricerca semantica viene aggiunta esattamente a un namespace. Ne conseguono tre conseguenze:
+ **L'isolamento è strutturale, non è un filtro che ti ricordi di scrivere. ** Una ricerca non può raggiungere una memoria in un namespace diverso, quindi un negozio che serve molti tenant non ha una forma di query che restituisca i ricordi di un altro tenant. Si tratta dell'ambito della query piuttosto che dell'autorizzazione: un principal con `dynamodb:SearchVectors` autorizzazione sulla tabella può cercare direttamente qualsiasi valore dello spazio dei nomi, quindi decidere quali namespace può leggere un chiamante appartiene comunque a IAM e al livello di autorizzazione dell'applicazione.
+ **Il costo di richiamo tiene traccia della memoria di un utente, non dell'intera tabella. ** Il lavoro di ricerca è limitato dalla quantità di spazio dei nomi che contiene, non dal numero di memorie dell'intero prodotto, il che mantiene bassi e stabili sia la latenza che i costi della ricerca vettoriale man mano che si cresce.
+ **La ricerca semantica è un namespace esatto, non un prefisso. ** Una ricerca raggiunge esattamente lo spazio dei nomi che passi e nulla al di sotto di esso. `("memories", "acme-corp")`La ricerca non arriva`("memories", "acme-corp", "user-8812")`, perché si tratta di valori di chiave di partizione diversi. Il tuo namespace è il tuo ambito di richiamo, quindi sceglilo in modo che corrisponda all'ambito che desideri visualizzare con una singola ricerca.

La tabella seguente riassume come scegliere la forma di un namespace.


| Forma dello spazio dei nomi | Uno raggiunge `search()` | Sceglilo quando | 
| --- | --- | --- | 
| `("memories", user_id)` | I ricordi di quell'utente | Single-tenant prodotto con richiamo per utente | 
| `("memories", tenant_id, user_id)` | Quell'utente, presso quell'inquilino | Multi-tenant, il caso comune | 
| `("memories", tenant_id, user_id, agent_name)` | Le note di un agente su quell'utente | Diversi agenti specializzati che non dovrebbero leggere gli appunti degli altri | 
| `("account_facts", tenant_id)` | Tenant-wide conoscenza | Fatti che si applicano a tutti gli utenti di un account | 

Evita di inserire ogni memoria in un unico namespace e di filtrare i metadati: i filtri vengono applicati dopo che DynamoDB ha già selezionato le corrispondenze più vicine nell'intero namespace e una singola ricerca restituisce al massimo le prime 100 corrispondenze, quindi una volta che un tenant occupato riempie le prime 100 per una query comune, la ricerca di un tenant più silenzioso restituisce meno risultati di quelli richiesti anche se i suoi ricordi sono presenti. Preferisci l'ambito dello spazio dei nomi rispetto ai filtri per tutto ciò che determina la correttezza. Andare oltre il limite di richiamo è anche una buona idea: un agente che necessita di un contesto specifico per l'utente e per l'intero account esegue una ricerca in entrambi i namespace e unisce i risultati.

## Considerazioni
<a name="langgraph-memory-considerations"></a>
+ L'indice è alla fine coerente, lo stesso modello di un indice secondario globale. A `search()` emesso immediatamente dopo a `put()` potrebbe non includere ancora la nuova memoria. Per un agente che scrive una memoria e poi la richiama nello stesso turno, rileggila invece con una chiave.
+ Una singola ricerca restituisce al massimo le prime 100 corrispondenze. Una richiesta il cui `offset` valore `limit` positivo supera tale limite viene respinta con un chiaro errore anziché restituire silenziosamente nulla oltre il limite massimo.
+ Se si utilizza Time to Live per far scadere le memorie obsolete e abilitare l'aggiornamento in caso di lettura, la data di scadenza di una memoria effettivamente richiamata dall'agente viene annullata, quindi non sono le memorie in uso attivo quelle che scompaiono silenziosamente.
+ Gli errori di ricerca vettoriale si generano in modo che l'applicazione possa reagire. Un rallentamento, un problema di autorizzazioni e un risultato veramente vuoto sembrerebbero identici se il negozio restituisse un elenco vuoto in caso di errore.
+ Le operazioni vettoriali vengono fatturate in unità proprie, misurate separatamente dalle unità di richiesta di lettura e scrittura della tabella di base, ed entrambe vengono scalate in base al numero di dimensioni. Una dimensione di incorporamento più piccola è più economica per ogni scrittura e ricerca, quindi utilizza la dimensione più piccola che garantisca la qualità di richiamo.
+ Le memorie scritte senza testo nella configurazione `fields` vengono archiviate senza incorporamento e non verranno visualizzate nei risultati semantici. Il negozio registra un avviso quando ciò accade.

## Risorse aggiuntive
<a name="langgraph-memory-resources"></a>
+ [Documentazione di DynamoDBStore su GitHub ](https://github.com/langchain-ai/langchain-aws/blob/main/libs/langgraph-checkpoint-aws/langgraph_checkpoint_aws/store/dynamodb/DynamoDBStore.md)
+ [langgraph-checkpoint-aws su PyPI ](https://pypi.org/project/langgraph-checkpoint-aws/)
+ [Documentazione di LangGraph](https://langchain-ai.github.io/langgraph/)