

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Semantisches Langzeitgedächtnis für Agenten LangGraph
<a name="ddb-langgraph-memory"></a>

LangGraph trennt zwei Arten von Agentenstatus. Short-term state ist der Konversations-Thread selbst, den ein Checkpointer dauerhaft speichert, sodass ein Thread fortgesetzt, wiedergegeben und wiederhergestellt werden kann (siehe). [DynamoDB als Checkpoint-Speicher für Agenten verwenden LangGraph](ddb-langgraph-checkpoint.md) Long-term Speicher ist das, was der Agent threadübergreifend kennt und es als Speicher LangGraph modelliert: eine Schlüssel-Wert-Oberfläche mit Namespace, auf die der Agent bewusst schreibt und später zurückliest.

Die `DynamoDBStore` Klasse im Paket [ langgraph-checkpoint-aws ](https://pypi.org/project/langgraph-checkpoint-aws/) ist die DynamoDB-Implementierung dieses Speichers. Sie kümmert sich um die Schlüsselwert-Seite mit hierarchischen Namespaces, Time to Live für ablaufende veraltete Erinnerungen und grundlegender Filterung. Wenn ein Vektorindex konfiguriert ist (siehe[Verwenden von Vektorindizes in DynamoDB](VectorSearch.md)), führt die `search()` Methode eine semantische Suche durch: Erinnerungen werden beim Schreiben eingebettet, asynchron indexiert und nach ihrer Bedeutung, geordnet nach Ähnlichkeit, aus derselben Tabelle abgerufen, die sie enthält. Es gibt keine separate Vektordatenbank, die bereitgestellt werden muss, und es gibt keine Pipeline, in die Daten kopiert werden.

## Voraussetzungen
<a name="langgraph-memory-prerequisites"></a>
+ Und AWS-Konto mit der Erlaubnis, DynamoDB-Tabellen zu erstellen und Amazon Bedrock-Modelle aufzurufen
+ Zugriff auf ein Einbettungsmodell in Amazon Bedrock in Ihrer Region. In diesen Beispielen wird Amazon Titan Text Embeddings V2 verwendet
+ Python 3.10 oder höher, mit `langgraph-checkpoint-aws` 1.2.2 oder höher und `boto3` 1.43.64 oder höher (frühere Versionen haben keinen Betrieb) `boto3` `SearchVectors`

Installieren Sie die Bibliotheken mit pip:

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

## Richten Sie den Laden ein
<a name="langgraph-memory-setup"></a>

Konfiguriere den Store mit einem `index` Block und rufe an`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()
```

Vier Einstellungen im `index` Block sind es wert, verstanden zu werden:
+ `embed`nimmt ein beliebiges LangChain Embeddings-Objekt oder ein einfaches Callable entgegen, das eine Liste von Zeichenketten einer Liste von Vektoren zuordnet.
+ `dims`muss der Ausgabegröße Ihres Modells entsprechen. Titan Text Embeddings V2 gibt standardmäßig 1.024 Dimensionen zurück. Wenn diese nicht übereinstimmen, gibt der Speicher einen Fehler bei der Dimensionsinkongruenz aus und benennt beide Zahlen beim ersten Schreibvorgang, anstatt Vektoren zu schreiben, die der Index nicht verwenden kann.
+ `fields`wählt aus, welche Teile des Werts eingebettet werden. Hier ist nur das `text` Feld eingebettet. In der Standardeinstellung wird der gesamte Wert in JSON serialisiert und eingebettet. Das ist praktisch, bettet aber auch Ihre Buchhaltungsattribute ein. `["$"]`
+ `distance_function`ist standardmäßig auf und akzeptiert auch `COSINE` und. `EUCLIDEAN` `DOT_PRODUCT`

`setup()`erstellt die Tabelle, falls sie nicht vorhanden ist, hängt den Vektorindex an und aktiviert Time to Live, wenn Sie ihn konfiguriert haben. Bei einer vorhandenen Tabelle wird nur das hinzugefügt, was fehlt, sodass bestehende `DynamoDBStore` Bereitstellungen die semantische Suche übernehmen können, ohne die Tabelle neu erstellen oder Elemente migrieren zu müssen. Denken Sie daran, dass der Index erst zurückgegeben wird, wenn der Index einen Bericht erstellt `ACTIVE` und `setup()` nicht mehr aufgefüllt wird: Ein Index, der Berichte meldet, `ACTIVE` während er noch mit dem Auffüllen versehen ist, lehnt Aufrufe ab. `SearchVectors` Bei einer neuen leeren Tabelle ist die Wartezeit kurz. Das Nachrüsten eines Tisches mit vorhandenen Gegenständen dauert so lange, wie das Auffüllen dauert.

## Schreiben Sie Erinnerungen auf
<a name="langgraph-memory-write"></a>

Schreiben ist normal`put()`. Die Einbettung erfolgt für Sie:

```
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",
})
```

## Erinnern Sie sich nach Sinn
<a name="langgraph-memory-recall"></a>

Der Kunde eröffnet eine neue Konversation und sagt, dass seine Verbindung nach etwa einer Minute immer wieder unterbrochen wird:

```
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"])
```

Ausgabe:

```
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
```

Der entsprechende Speicher steht an erster Stelle, und kein Schlüssel in der Abfrage stimmte mit etwas überein. `SearchItem.score`folgt der LangGraph Konvention, dass höher relevanter ist. DynamoDB gibt eine Entfernung zurück, bei der niedriger näher ist, sodass der Speicher umrechnet: denn `COSINE` die Punktzahl ist`1 - distance`, denn `EUCLIDEAN` sie ist`1 / (1 + distance)`, und die `DOT_PRODUCT` Punktzahlen werden unverändert weitergegeben. Wenn Sie anhand eines absoluten Punktewerts entscheiden, ob ein Speicher relevant genug ist, um ihn in eine Eingabeaufforderung einzufügen, kalibrieren Sie diesen Schwellenwert anhand Ihrer eigenen Daten und der von Ihnen gewählten Distanzfunktion.

## Bereichern Sie den Speicher mit dem Suchschema
<a name="langgraph-memory-scoping"></a>

Wenn der Vektorindex `DynamoDBStore` erstellt wird, deklariert er den Partitionsschlüssel der Tabelle als `HASH` Element im Index-Suchschema. Da dieses Element existiert, muss jede Suche eine Bedingung dafür erfüllen, und der Speicher stellt den Namespace bereit: Das Namespace-Tupel wird zusammengefügt, um den Partitionsschlüsselwert zu bilden, sodass jede semantische Suche an genau einen Namespace geheftet ist. Es ergeben sich drei Konsequenzen:
+ **Isolation ist struktureller Natur, kein Filter, an den man sich erinnert, ihn zu schreiben. ** Eine Suche kann keinen Speicher in einem anderen Namespace erreichen, daher hat ein Store, der viele Mandanten bedient, kein Abfrage-Shape, das die Erinnerungen eines anderen Mandanten zurückgibt. Das ist eher Abfrageumfang als Autorisierung: Ein Principal mit einer `dynamodb:SearchVectors` Berechtigung für die Tabelle kann jeden Namespace-Wert direkt durchsuchen. Die Entscheidung, welche Namespaces ein Aufrufer lesen darf, gehört also immer noch zu IAM und der Autorisierungsebene Ihrer Anwendung.
+ **Die Rückrufkosten beziehen sich auf den Arbeitsspeicher eines Benutzers, nicht auf die gesamte Tabelle. ** Die Sucharbeit hängt davon ab, wie viel dieser Namespace enthält, nicht davon, wie viele Speicher Ihr gesamtes Produkt enthält. Dadurch bleiben sowohl die Latenz als auch die Kosten für die Vektorsuche gering und stabil, wenn Sie wachsen.
+ **Bei der semantischen Suche handelt es sich um einen exakten Namespace, nicht um ein Präfix. ** Eine Suche erreicht genau den Namespace, den Sie passieren, und nichts darunter. Die Suche erreicht `("memories", "acme-corp")` nicht`("memories", "acme-corp", "user-8812")`, da es sich um unterschiedliche Partitionsschlüsselwerte handelt. Ihr Namespace ist Ihr Rückrufbereich. Wählen Sie ihn also so aus, dass er dem Bereich entspricht, den Sie bei einer einzelnen Suche sehen möchten.

In der folgenden Tabelle wird zusammengefasst, wie Sie ein Namespace-Shape auswählen.


| Namespace-Shape | Man erreicht `search()` | Wähle es wann | 
| --- | --- | --- | 
| `("memories", user_id)` | Die Erinnerungen dieses Benutzers | Single-tenant Produkt mit Rückruf pro Benutzer | 
| `("memories", tenant_id, user_id)` | Dieser Benutzer, bei diesem Mandanten | Multi-tenant, der übliche Fall | 
| `("memories", tenant_id, user_id, agent_name)` | Notizen eines Agenten zu diesem Benutzer | Mehrere spezialisierte Agenten, die die Notizen des anderen nicht lesen sollten | 
| `("account_facts", tenant_id)` | Tenant-wide Wissen | Fakten, die für jeden Benutzer eines Kontos gelten | 

Vermeiden Sie es, jeden Speicher in einen Namespace zu legen und nach Metadaten zu filtern: Filter werden angewendet, nachdem DynamoDB bereits die nächstgelegenen Treffer im gesamten Namespace ausgewählt hat, und eine einzelne Suche liefert höchstens die 100 besten Treffer. Sobald also ein ausgelasteter Mandant die Top 100 für eine häufig gestellte Abfrage ausfüllt, liefert die Suche eines ruhigeren Mandanten weniger Ergebnisse als angefordert, obwohl seine Erinnerungen vorhanden sind. Bevorzugen Sie Namespace-Scoping gegenüber Filtern für alles, was die Richtigkeit bestimmt. Es ist auch legitim, Ihre Erinnerungsgrenze zu überschreiten: Ein Agent, der sowohl einen benutzerspezifischen als auch einen kontoweiten Kontext benötigt, durchsucht beide Namespaces und führt die Ergebnisse zusammen.

## Überlegungen
<a name="langgraph-memory-considerations"></a>
+ Der Index ist letztendlich konsistent, dasselbe Modell wie ein globaler sekundärer Index. A, das unmittelbar nach einem `search()` ausgegeben wird, enthält `put()` möglicherweise noch nicht den neuen Speicher. Bei einem Agenten, der einen Speicher schreibt und ihn dann innerhalb derselben Runde wieder abruft, liest er ihn stattdessen per Schlüssel zurück.
+ Eine einzelne Suche liefert höchstens die 100 besten Treffer. Eine Anfrage, deren `limit` Plus diesen `offset` Wert überschreitet, wird mit einem eindeutigen Fehler abgelehnt, anstatt stillschweigend nichts zurückzugeben, was über die Obergrenze hinausgeht.
+ Wenn Sie Time to Live verwenden, um veraltete Erinnerungen ablaufen zu lassen und die Aktualisierung beim Lesen zu aktivieren, wird der Ablauf eines Speichers, an den sich der Agent tatsächlich erinnert, verschoben. Es sind also nicht die Erinnerungen, die aktiv verwendet werden, die leise verschwinden.
+ Bei der Vektorsuche treten Fehler auf, sodass Ihre Anwendung reagieren kann. Eine Drosselung, ein Berechtigungsproblem und ein wirklich leeres Ergebnis würden identisch aussehen, wenn der Store bei einem Fehler eine leere Liste zurückgeben würde.
+ Vektoroperationen werden in ihren eigenen Einheiten abgerechnet, die getrennt von den Lese- und Schreibanforderungseinheiten der Basistabelle gemessen werden, und beide skalieren mit der Anzahl der Dimensionen. Eine kleinere Einbettungsdimension ist bei jedem Schreib- und Suchvorgang günstiger. Verwenden Sie daher die kleinste Dimension, die Ihrer Erinnerungsqualität entspricht.
+ Erinnerungen, die ohne Text in der Konfiguration geschrieben wurden, `fields` werden ohne Einbettung gespeichert und erscheinen nicht in den semantischen Ergebnissen. Der Store protokolliert in diesem Fall eine Warnung.

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