Erstellung eines Wissensagenten mit semantischem Recall unter Verwendung von Mastra und Elasticsearch
Lernen Sie, wie Sie einen Wissensagenten mit semantischer Erinnerung unter Verwendung von Mastra und Elasticsearch als Vektorspeicher für Gedächtnis und Informationsabruf erstellen.
Kontextentwicklung gewinnt zunehmend an Bedeutung beim Aufbau zuverlässiger KI-Agenten und -Architekturen. Je besser die Modelle werden, desto weniger hängen ihre Effektivität und Zuverlässigkeit von den Trainingsdaten ab, sondern vielmehr davon, wie gut sie im richtigen Kontext verankert sind. Agenten, die die relevantesten Informationen zum richtigen Zeitpunkt abrufen und anwenden können, liefern mit viel höherer Wahrscheinlichkeit genaue und verlässliche Ergebnisse.
In diesem Blogbeitrag verwenden wir Mastra , um einen Wissensagenten zu entwickeln, der sich merkt, was Benutzer sagen, und relevante Informationen später abrufen kann. Als Speicher- und Abruf-Backend nutzen wir Elasticsearch. Dieses Konzept lässt sich problemlos auf reale Anwendungsfälle übertragen. Man denke beispielsweise an Supportmitarbeiter, die sich an frühere Gespräche und Lösungen erinnern können, sodass sie ihre Antworten auf bestimmte Benutzer zuschneiden oder Lösungen schneller auf Basis des vorherigen Kontextes präsentieren können.
Folgen Sie dieser Anleitung, um zu sehen, wie Sie es Schritt für Schritt bauen können. Falls Sie nicht weiterkommen oder einfach nur ein fertiges Beispiel ausführen möchten, schauen Sie sich das Repository hier an.
Was ist Mastra?
Mastra ist ein Open-Source-TypeScript-Framework zum Erstellen von KI-Agenten mit austauschbaren Teilen für Schlussfolgerungen, Speicher und Werkzeuge. Die semantische Abruffunktion ermöglicht es Agenten, vergangene Interaktionen zu erinnern und abzurufen, indem Nachrichten als Einbettungen in einer Vektordatenbank gespeichert werden. Dies ermöglicht es den Agenten, den Gesprächskontext und die Kontinuität langfristig aufrechtzuerhalten. Elasticsearch ist ein hervorragender Vektorspeicher, um diese Funktion zu ermöglichen, da er eine effiziente dichte Vektorsuche unterstützt. Wenn der semantische Abruf ausgelöst wird, ruft der Agent relevante vergangene Nachrichten in das Kontextfenster des Modells ab, sodass das Modell diesen abgerufenen Kontext als Grundlage für seine Schlussfolgerungen und Antworten nutzen kann.
Was Sie für den Einstieg benötigen
Node v18+
Elasticsearch (Version 8.15 oder neuer)
Elasticsearch API-Schlüssel
Hinweis: Sie benötigen dies, da die Demo den OpenAI-Provider verwendet. Mastra unterstützt jedoch auch andere KI-SDKs und Community-Modell-Provider, sodass Sie ihn je nach Ihrer Konfiguration problemlos austauschen können.
Aufbau eines Mastra-Projekts
Wir werden die integrierte CLI von Mastra verwenden, um das Grundgerüst für unser Projekt bereitzustellen. Führen Sie folgenden Befehl aus:
npm create mastra@latestSie erhalten eine Reihe von Eingabeaufforderungen, beginnend mit:
1. Gib deinem Projekt einen Namen.

2. Wir können diese Standardeinstellung beibehalten; Sie können dieses Feld gerne leer lassen.

3. Für dieses Projekt verwenden wir ein von OpenAI bereitgestelltes Modell.

4. Wählen Sie die Option „Jetzt überspringen“, da wir alle unsere Umgebungsvariablen in einer `.env`-Datei speichern, die wir in einem späteren Schritt konfigurieren werden.

5. Diese Option können wir auch überspringen.

Überspringen der Installation des MCP-Servers von Mastra
Sobald dieser Initialisierungsprozess abgeschlossen ist, können wir zum nächsten Schritt übergehen.
Abhängigkeiten installieren
Als Nächstes müssen wir einige Abhängigkeiten installieren:
npm install ai @ai-sdk/openai @elastic/elasticsearch dotenvai- Core AI SDK-Paket, das Werkzeuge zur Verwaltung von KI-Modellen, Eingabeaufforderungen und Arbeitsabläufen in JavaScript/TypeScript bereitstellt. Mastra basiert auf dem AI SDK von Vercel, daher benötigen wir diese Abhängigkeit, um Modellinteraktionen mit Ihrem Agenten zu ermöglichen.@ai-sdk/openai- Plugin, das das AI SDK mit OpenAI-Modellen (wie GPT-4, GPT-4o usw.) verbindet und API-Aufrufe mit Ihrem OpenAI-API-Schlüssel ermöglicht.@elastic/elasticsearch- Offizieller Elasticsearch-Client für Node.js, Wird verwendet, um eine Verbindung zu Ihrer Elastic Cloud oder Ihrem lokalen Cluster für Indizierungs-, Such- und Vektoroperationen herzustellen.dotenvLädt Umgebungsvariablen aus einer .env-Datei Datei in process.env, ermöglicht das sichere Einfügen von Anmeldeinformationen wie API-Schlüsseln und Elasticsearch-Endpunkten.
Konfiguration von Umgebungsvariablen
Erstellen Sie eine .env -Datei in Ihrem Projektstammverzeichnis, falls dort noch keine vorhanden ist. Alternativ können Sie das von mir im Repository bereitgestellte Beispiel .env kopieren und umbenennen. In dieser Datei können wir die folgenden Variablen hinzufügen:
ELASTICSEARCH_ENDPOINT="your-endpoint-here"
ELASTICSEARCH_API_KEY="your-key-here"
OPENAI_API_KEY="your-key-here"Damit ist die grundlegende Einrichtung abgeschlossen. Von hier aus können Sie bereits mit dem Erstellen und Orchestrieren von Agenten beginnen. Wir gehen noch einen Schritt weiter und fügen Elasticsearch als Speicher- und Vektorsuchschicht hinzu.
Elasticsearch als Vektorspeicher hinzufügen
Erstellen Sie einen neuen Ordner namens stores und fügen Sie darin diese Datei ein. Bevor Mastra und Elastic eine offizielle Elasticsearch-Vektorspeicherintegration veröffentlichten, teilte Abhi Aiyer(CTO von Mastra) diese frühe Prototypklasse mit dem Namen ElasticVector. Vereinfacht gesagt verbindet es die Speicherabstraktion von Mastra mit den dichten Vektorfunktionen von Elasticsearch, sodass Entwickler Elasticsearch als Vektordatenbank für ihre Agenten verwenden können.
Werfen wir einen genaueren Blick auf die wichtigen Aspekte der Integration:
Aufnahme des Elasticsearch-Clients
Dieser Abschnitt definiert die Klasse ElasticVector und richtet die Elasticsearch-Clientverbindung mit Unterstützung für Standard- und serverlose Bereitstellungen ein.
export interface ElasticVectorConfig extends ClientOptions {
/**
* Explicitly specify if connecting to Elasticsearch Serverless.
* If not provided, will be auto-detected on first use.
*/
isServerless?: boolean;
/**
* Maximum documents to count accurately when describing indices.
* Higher values provide accurate counts but may impact performance on large indices.
*
* @default 10000
*/
maxCountAccuracy?: number;
}
export class ElasticVector extends MastraVector {
private client: Client;
private isServerless: boolean | undefined;
private deploymentChecked: boolean = false;
private readonly maxCountAccuracy: number;
constructor(config: ElasticVectorConfig) {
super();
this.client = new Client(config);
this.isServerless = config.isServerless;
this.maxCountAccuracy = config.maxCountAccuracy ?? 10000;
}
}ElasticVectorConfig extends ClientOptionsDadurch wird eine neue Konfigurationsschnittstelle erstellt, die alle Elasticsearch-Clientoptionen (wienode,auth,requestTimeout) erbt und unsere benutzerdefinierten Eigenschaften hinzufügt. Das bedeutet, dass Benutzer jede gültige Elasticsearch-Konfiguration zusammen mit unseren serverlosen Optionen übergeben können.extends MastraVectorDies ermöglicht esElasticVectorvon Mastras BasisklasseMastraVectorzu erben, die eine gemeinsame Schnittstelle darstellt, der alle Vektorspeicherintegrationen entsprechen. Dadurch wird sichergestellt, dass sich Elasticsearch aus Sicht des Agenten wie jedes andere Mastra-Vektor-Backend verhält.private client: ClientDies ist eine private Eigenschaft, die eine Instanz des Elasticsearch JavaScript-Clients enthält. Dadurch kann die Klasse direkt mit Ihrem Cluster kommunizieren.isServerlessunddeploymentChecked: Diese Eigenschaften arbeiten zusammen, um zu erkennen und zwischenzuspeichern, ob wir mit einer serverlosen oder einer Standard-Elasticsearch-Bereitstellung verbunden sind. Diese Erkennung erfolgt automatisch bei der ersten Nutzung oder kann explizit konfiguriert werden.constructor(config: ClientOptions)Dieser Konstruktor nimmt ein Konfigurationsobjekt entgegen (das Ihre Elasticsearch-Zugangsdaten und optionale Serverless-Einstellungen enthält) und verwendet es, um den Client in der Zeilethis.client = new Client(config)zu initialisieren.super(): Dadurch wird der Basiskonstruktor von Mastra aufgerufen, sodass Logging, Validierungshilfsmechanismen und andere interne Hooks geerbt werden.
Zu diesem Zeitpunkt weiß Mastra, dass es einen neuen Vektor-Shop namens gibt. ElasticVector
Erkennung des Bereitstellungstyps
Vor dem Erstellen von Indizes erkennt der Adapter automatisch, ob Sie Elasticsearch Standard oder Elasticsearch Serverless verwenden. Dies ist wichtig, da serverlose Bereitstellungen keine manuelle Shard-Konfiguration zulassen.
private async detectServerless(): Promise<boolean> {
// Return cached result if already detected
if (this.deploymentChecked) {
return this.isServerless ?? false;
}
// Use explicit configuration if provided
if (this.isServerless !== undefined) {
this.deploymentChecked = true;
this.logger?.info(
`Using explicit deployment type: ${this.isServerless ? 'Serverless' : 'Standard'}`
);
return this.isServerless;
}
try {
const info = await this.client.info();
// Primary detection: build flavor (most reliable)
const isBuildFlavorServerless = info.version?.build_flavor === 'serverless';
// Secondary detection: tagline (fallback)
const isTaglineServerless = info.tagline?.toLowerCase().includes('serverless') ?? false;
this.isServerless = isBuildFlavorServerless || isTaglineServerless;
this.deploymentChecked = true;
this.logger?.info(
`Auto-detected ${this.isServerless ? 'Serverless' : 'Standard'} Elasticsearch deployment`,
{
buildFlavor: info.version?.build_flavor,
version: info.version?.number,
detectionMethod: isBuildFlavorServerless ? 'build_flavor' : 'tagline'
}
);
return this.isServerless;
} catch (error) {
this.logger?.warn(
'Could not auto-detect deployment type, assuming Standard Elasticsearch. ' +
'Set isServerless: true explicitly in config if using Serverless.',
{ error: error instanceof Error ? error.message : String(error) }
);
this.isServerless = false;
this.deploymentChecked = true;
return false;
}
}Was passiert:
Zuerst wird geprüft, ob Sie
isServerlessexplizit in der Konfiguration festgelegt haben (überspringt die automatische Erkennung).Ruft die
info()-API von Elasticsearch auf, um Clusterinformationen zu erhalten.Prüft den Wert
build_flavor field(serverlose Bereitstellungen gebenserverlesszurück)Falls die Build-Variante nicht verfügbar ist, wird auf die Überprüfung des Slogans zurückgegriffen.
Speichert das Ergebnis im Cache, um wiederholte API-Aufrufe zu vermeiden.
Wird standardmäßig die Bereitstellung durchgeführt, wenn die Erkennung fehlschlägt.
Anwendungsbeispiel:
// Option 1: Auto-detect (recommended)
const vector = new ElasticVector({
node: 'https://your-cluster.es.cloud',
auth: { apiKey: 'your-api-key' }
});
// Detection happens automatically on first index operation
// Option 2: Explicit configuration (faster startup)
const vector = new ElasticVector({
node: 'https://your-serverless.es.cloud',
auth: { apiKey: 'your-api-key' },
isServerless: true // Skips auto-detection
});Erstellen des „Speichers“ in Elasticsearch
Die folgende Funktion richtet einen Elasticsearch-Index zum Speichern von Einbettungen ein. Es wird geprüft, ob der Index bereits existiert. Andernfalls wird eine solche mit der unten stehenden Zuordnung erstellt, die ein dense_vector -Feld zum Speichern von Einbettungen und benutzerdefinierten Ähnlichkeitsmetriken enthält.
Einige Dinge sind zu beachten:
Der Parameter
dimensiongibt die Länge des jeweiligen Einbettungsvektors an und hängt davon ab, welches Einbettungsmodell Sie verwenden. In unserem Fall generieren wir Einbettungen mithilfe destext-embedding-3-small-Modells von OpenAI, das Vektoren der Größe1536ausgibt. Dies werden wir als Standardwert verwenden.Die in der folgenden Zuordnung verwendete Variable
similaritywird durch die Hilfsfunktion const similarity = this.mapMetricToSimilarity(metric)definiert, welche den Wert für den Parametermetricentgegennimmt und ihn in ein Elasticsearch-kompatibles Schlüsselwort für die gewählte Distanzmetrik umwandelt.Zum Beispiel: Mastra verwendet allgemeine Begriffe für Vektorähnlichkeit wie
cosine,euclidean, unddotproduct. Würden wir die Metrikeuclideandirekt in das Elasticsearch-Mapping einfügen, würde dies einen Fehler auslösen, da Elasticsearch erwartet, dass das Schlüsselwortl2_normdie euklidische Distanz repräsentiert.
Serverless-Kompatibilität: Der Code lässt Shard- und Replikateinstellungen für serverlose Bereitstellungen automatisch aus, da diese von Elasticsearch Serverless automatisch verwaltet werden.
async createIndex(params: CreateIndexParams): Promise<void> {
const { indexName, dimension = 1536, metric = 'cosine' } = params;
try {
const exists = await this.client.indices.exists({ index: indexName });
if (exists) {
try {
await this.validateExistingIndex(indexName, dimension, metric);
this.logger?.info(`Index "${indexName}" already exists and is valid`);
return;
} catch (validationError) {
throw new Error(
`Index "${indexName}" exists but does not match the required configuration: ${
validationError instanceof Error ? validationError.message : String(validationError)
}`
);
}
}
const isServerless = await this.detectServerless();
const similarity = this.mapMetricToSimilarity(metric);
const indexConfig: any = {
index: indexName,
mappings: {
properties: {
vector: {
type: 'dense_vector',
dims: dimension,
index: true,
similarity: similarity,
},
metadata: {
type: 'object',
enabled: true,
dynamic: true, // Allows flexible metadata structures
},
},
},
};
// Only configure shards/replicas for non-serverless deployments
// Serverless manages infrastructure automatically
if (!isServerless) {
indexConfig.settings = {
number_of_shards: 1,
number_of_replicas: 0, // Increase for production HA deployments
};
}
await this.client.indices.create(indexConfig);
this.logger?.info(
`Created ${isServerless ? 'Serverless' : 'Standard'} Elasticsearch index "${indexName}"`,
{ dimension, metric, similarity }
);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger?.error(`Failed to create index "${indexName}": ${errorMessage}`);
throw new Error(`Failed to create index "${indexName}": ${errorMessage}`);
}
}Speichern einer neuen Erinnerung oder Notiz nach einer Interaktion
Diese Funktion nimmt die nach jeder Interaktion neu generierten Einbettungen zusammen mit den Metadaten entgegen und fügt sie anschließend mithilfe der bulk -API von Elastic in den Index ein oder aktualisiert sie. Die bulk API bündelt mehrere Schreibvorgänge in einer einzigen Anfrage; diese Verbesserung unserer Indexierungsleistung stellt sicher, dass Aktualisierungen effizient bleiben, während der Speicher unseres Agenten immer größer wird.
async upsert(params: UpsertVectorParams): Promise<string[]> {
const { indexName, vectors, metadata = [], ids } = params;
try {
// Generate unique IDs if not provided
const vectorIds = ids || vectors.map((_, i) =>
`vec_${Date.now()}_${i}_${Math.random().toString(36).substr(2, 9)}`
);
const operations = vectors.flatMap((vec, index) => [
{ index: { _index: indexName, _id: vectorIds[index] } },
{
vector: vec,
metadata: metadata[index] || {},
},
]);
const response = await this.client.bulk({
refresh: true,
operations,
});
if (response.errors) {
const erroredItems = response.items.filter((item: any) => item.index?.error);
const erroredIds = erroredItems.map((item: any) => item.index?._id);
const errorDetails = erroredItems.slice(0, 3).map((item: any) => ({
id: item.index?._id,
error: item.index?.error?.reason || item.index?.error,
type: item.index?.error?.type
}));
const errorMessage = `Failed to upsert ${erroredIds.length}/${vectors.length} vectors`;
console.error(`${errorMessage}. Sample errors:`, JSON.stringify(errorDetails, null, 2));
this.logger?.error(errorMessage, {
failedCount: erroredIds.length,
totalCount: vectors.length,
sampleErrors: errorDetails
});
// Still return successfully inserted IDs
const successfulIds = vectorIds.filter((id, idx) =>
!erroredIds.includes(id)
);
if (successfulIds.length === 0) {
throw new Error(`${errorMessage}. All operations failed. See logs for details.`);
}
return successfulIds;
}
this.logger?.info(`Successfully upserted ${vectors.length} vectors to "${indexName}"`);
return vectorIds;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger?.error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
throw new Error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
}
}Abfrage ähnlicher Vektoren für semantische Wiedererkennung
Diese Funktion ist der Kern des semantischen Recall-Features. Der Agent verwendet eine Vektorsuche, um ähnliche gespeicherte Einbettungen in unserem Index zu finden.
async query(params: QueryVectorParams<any>): Promise<QueryResult[]> {
const { indexName, queryVector, topK = 10, filter, includeVector = false } = params;
try {
const knnQuery: any = {
field: 'vector',
query_vector: queryVector,
k: topK,
num_candidates: Math.max(topK * 10, 100), // Search more candidates for better recall
};
// Apply metadata filters if provided
if (filter) {
knnQuery.filter = this.buildElasticFilter(filter);
}
const sourceFields = ['metadata'];
if (includeVector) {
sourceFields.push('vector');
}
const response = await this.client.search({
index: indexName,
knn: knnQuery,
size: topK,
_source: sourceFields,
});
const results = response.hits.hits.map((hit: any) => ({
id: hit._id,
score: hit._score || 0,
metadata: hit._source?.metadata || {},
vector: includeVector ? hit._source?.vector : undefined,
}));
this.logger?.debug(`Query returned ${results.length} results from "${indexName}"`);
return results;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger?.error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
throw new Error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
}
}Unter der Haube:
Führt eine kNN- Abfrage (k-nächste Nachbarn) mit Hilfe der
knn-API in Elasticsearch aus.Gibt die K ähnlichsten Vektoren zum Eingabeabfragevektor zurück.
Optional können Metadatenfilter angewendet werden, um die Ergebnisse einzugrenzen (z. B. nur innerhalb einer bestimmten Kategorie oder eines bestimmten Zeitraums zu suchen).
Gibt strukturierte Ergebnisse zurück, einschließlich der Dokument-ID, des Ähnlichkeitswerts und der gespeicherten Metadaten.
Erstellung des Wissensagenten
Nachdem wir nun die Verbindung zwischen Mastra und Elasticsearch durch die ElasticVector -Integration kennengelernt haben, erstellen wir den Knowledge Agent selbst.
Erstellen Sie im Ordner agents eine Datei namens knowledge-agent.ts. Wir können damit beginnen, unsere Umgebungsvariablen zu verbinden und den Elasticsearch-Client zu initialisieren.
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { openai } from '@ai-sdk/openai';
import { Client } from '@elastic/elasticsearch';
import { ElasticVector } from '../stores/elastic-store';
import dotenv from "dotenv";
dotenv.config();
const ELASTICSEARCH_ENDPOINT = process.env.ELASTICSEARCH_ENDPOINT;
const ELASTICSEARCH_API_KEY = process.env.ELASTICSEARCH_API_KEY;
//Error check for undefined credentials
if (!ELASTICSEARCH_ENDPOINT || !ELASTICSEARCH_API_KEY) {
throw new Error('Missing Elasticsearch credentials');
}
//Check to see if a connection can be established
const testClient = new Client({
node: ELASTICSEARCH_ENDPOINT,
auth: {
apiKey: ELASTICSEARCH_API_KEY
},
});
try {
await testClient.ping();
console.log('Connected to Elasticsearch successfully');
} catch (error: unknown) {
if (error instanceof Error) {
console.error('Failed to connect to Elasticsearch:', error.message);
} else {
console.error('Failed to connect to Elasticsearch:', error);
}
process.exit(1);
}
//Initialize the Elasticsearch vector store
const vectorStore = new ElasticVector({
node: ELASTICSEARCH_ENDPOINT,
auth: {
apiKey: ELASTICSEARCH_API_KEY,
},
//Optional: Explicitly set to true if using Elasticsearch Serverless to skip auto-detection and improve startup time
//isServerless: true,
});Hier, wir:
Verwenden Sie
dotenvum unsere Variablen aus unserer.env-Datei zu laden.Prüfen Sie, ob die Elasticsearch-Zugangsdaten korrekt eingefügt werden, dann können wir eine erfolgreiche Verbindung zum Client herstellen.
Übergeben Sie den Elasticsearch-Endpunkt und den API-Schlüssel an den
ElasticVector-Konstruktor, um eine Instanz unseres zuvor definierten Vektorspeichers zu erstellen.Optional können Sie
isServerless: trueangeben, wenn Sie Elasticsearch Serverless verwenden. Dadurch wird der automatische Erkennungsschritt übersprungen und die Startzeit verkürzt. Wird dieser Parameter weggelassen, erkennt der Adapter Ihren Bereitstellungstyp bei der ersten Verwendung automatisch.
Als nächstes können wir den Agenten mithilfe der Klasse Agent von Mastra definieren.
export const knowledgeAgent = new Agent({
name: 'KnowledgeAgent',
instructions: 'You are a helpful knowledge assistant.',
model: openai('gpt-4o'),
memory: new Memory({
vector: vectorStore,
//embedder used to create embeddings for each message
embedder: 'openai/text-embedding-3-small',
//set semantic recall options
options: {
semanticRecall: {
topK: 3, // retrieve 3 similar messages
messageRange: 2, // include 2 messages before/after each match
scope: 'resource',
},
},
}),
});Folgende Felder können wir definieren:
nameundinstructions: Gib ihr eine Identität und eine primäre Funktion.modelWir verwenden OpenAIsgpt-4oüber das@ai-sdk/openai-Paket.memory:vector: Verweist auf unseren Elasticsearch-Speicher, sodass Einbettungen dort gespeichert und abgerufen werden.embedderWelches Modell soll zur Generierung von Einbettungen verwendet werden?semanticRecallDie Optionen bestimmen, wie der Rückruf funktioniert:topK: Wie viele semantisch ähnliche Nachrichten sollen abgerufen werden?messageRange: Wie viel vom Gespräch soll bei jedem Spielzug einbezogen werden?scope: Definiert die Speichergrenze.
Fast fertig. Wir müssen diesen neu erstellten Agenten lediglich zu unserer Mastra-Konfiguration hinzufügen. Importieren Sie in der Datei mit dem Namen index.ts den Wissensagenten und fügen Sie ihn in das Feld agents ein.
export const mastra = new Mastra({
agents: { knowledgeAgent },
storage: new LibSQLStore({
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
url: ":memory:",
}),
logger: new PinoLogger({
name: 'Mastra',
level: 'info',
}),
telemetry: {
// Telemetry is deprecated and will be removed in the Nov 4th release
enabled: false,
},
observability: {
// Enables DefaultExporter and CloudExporter for AI tracing
default: { enabled: true },
},
});Zu den weiteren Bereichen gehören:
storageDies ist Mastras interner Datenspeicher für Laufzeitverlauf, Observability-Metriken, Scores und Caches. Weitere Informationen zu Mastra-Speicherlösungen finden Sie hier.loggerMastra verwendet Pino, einen leichtgewichtigen, strukturierten JSON-Logger. Es erfasst Ereignisse wie Agentenstart und -stopp, Toolaufrufe und -ergebnisse, Fehler und LLM-Reaktionszeiten.observability: Steuert die KI-Verfolgung und die Sichtbarkeit der Ausführung von Agenten. Es verfolgt:Beginn/Ende jedes Denkschritts.
Welches Modell oder Werkzeug wurde verwendet?
Ein- und Ausgänge.
Bewertungen und Beurteilungen
Testen des Agenten mit Mastra Studio
Glückwunsch! Wenn Sie es bis hierher geschafft haben, sind Sie bereit, diesen Agenten auszuführen und seine semantischen Erinnerungsfähigkeiten zu testen. Zum Glück bietet Mastra eine integrierte Chat-Benutzeroberfläche, sodass wir keine eigene entwickeln müssen.
Um den Mastra-Entwicklungsserver zu starten, öffnen Sie ein Terminal und führen Sie folgenden Befehl aus:
npm run devNach der ersten Bündelung und dem Start des Servers sollte Ihnen eine Adresse für den Playground bereitgestellt werden.

Fügen Sie diese Adresse in Ihren Browser ein, und Sie gelangen zum Mastra Studio.

Wählen Sie die Option für knowledgeAgent und legen Sie los.
Um schnell zu prüfen, ob alles richtig verkabelt ist, geben Sie ihm beispielsweise folgende Information: „Das Team gab bekannt, dass die Umsatzentwicklung im Oktober um 12 % gestiegen ist, hauptsächlich aufgrund von Vertragsverlängerungen im Unternehmensbereich.“ Der nächste Schritt besteht darin, die Kundenansprache auf mittelständische Unternehmen auszuweiten.“ Starten Sie anschließend einen neuen Chat und stellen Sie eine Frage wie: „Auf welches Kundensegment sollten wir uns als Nächstes konzentrieren?“ Der Wissensagent sollte in der Lage sein, die Informationen aus dem ersten Chat abzurufen. Sie sollten eine Antwort wie diese sehen:

Eine solche Antwort bedeutet, dass der Agent unsere vorherige Nachricht erfolgreich als Einbettungen in Elasticsearch gespeichert und später mithilfe der Vektorsuche abgerufen hat.
Überprüfung des Langzeitspeichers des Agenten
Wechseln Sie im Mastra Studio zur Registerkarte memory in der Konfiguration Ihres Agenten. So können Sie sehen, was Ihr Agent im Laufe der Zeit gelernt hat. Jede Nachricht, Antwort und Interaktion, die in Elasticsearch eingebettet und gespeichert wird, wird Teil dieses Langzeitgedächtnisses. Sie können vergangene Interaktionen semantisch durchsuchen, um schnell erinnerte Informationen oder Kontexte wiederzufinden, die der Agent zuvor gelernt hat. Dies ist im Wesentlichen derselbe Mechanismus, den der Agent beim semantischen Abruf verwendet, aber hier können Sie ihn direkt untersuchen. In unserem unten stehenden Beispiel suchen wir nach dem Begriff „Vertrieb“ und erhalten jede Interaktion zurück, die etwas mit Vertrieb zu tun hat.

Fazit
Durch die Verbindung von Mastra und Elasticsearch können wir unseren Agenten Speicher zur Verfügung stellen, was eine wichtige Ebene im Kontext-Engineering darstellt. Mithilfe des semantischen Abrufs können Agenten im Laufe der Zeit Kontext aufbauen und ihre Antworten auf dem basieren, was sie gelernt haben. Das bedeutet genauere, zuverlässigere und natürlichere Interaktionen.
Diese frühe Integration ist nur der Ausgangspunkt. Das gleiche Prinzip kann hier Support-Mitarbeitern ermöglichen, die sich an frühere Tickets erinnern, internen Bots, die relevante Dokumente abrufen, oder KI-Assistenten, die sich mitten im Gespräch an Kundendetails erinnern können. Wir arbeiten außerdem an einer offiziellen Mastra-Integration, wodurch diese Verbindung in naher Zukunft noch nahtloser wird.
Wir sind gespannt, was Sie als Nächstes entwickeln werden. Probieren Sie es aus, erkunden Sie Mastra und seine Speicherfunktionen und teilen Sie Ihre Entdeckungen gerne mit der Community.




