mem0 gegen eine custom OpenAI-kompatible Base URL betreiben.

Updated 2026-07-29

mem0s OpenAI-Provider nimmt einen Config-Key openai_base_url. Setze ihn auf https://api.apisrouter.com/v1, übergib einen Key, und das Modell, das Memories extrahiert und aktualisiert, kann jede ID im Katalog sein, Claude und DeepSeek eingeschlossen, ohne den Rest deiner Memory-Pipeline anzufassen.

Kurzantwort: ein Config-Key im llm-Block.

mem0s OpenAI-LLM-Provider löst seinen Endpoint zuerst über Config, dann über Umgebung, dann über Default auf: self.config.openai_base_url, dann die Umgebungsvariable OPENAI_BASE_URL, dann https://api.openai.com/v1. Der sauberste Override ist also ein Key im llm-Config-Dict: setze openai_base_url auf https://api.apisrouter.com/v1, setze api_key daneben (oder exportiere OPENAI_API_KEY), und jeder Memory-Extraction-Call läuft über das Gateway. Das ist Upstream-mem0-Verhalten, lesbar in mem0/llms/openai.py, kein Fork. Das TypeScript-SDK exponiert dasselbe Paar in camelCase: openaiBaseUrl und apiKey. Werte im Config-Dict überschreiben Umgebungsvariablen, die wiederum Defaults überschreiben, also gewinnt eine Config-Level-Base-URL selbst auf Rechnern, wo OPENAI_BASE_URL woandershin zeigt.

config = {
    "llm": {
        "provider": "openai",
        "config": {
            "model": "claude-sonnet-4-6",
            "openai_base_url": "https://api.apisrouter.com/v1",
            "api_key": os.environ["APISROUTER_API_KEY"],
        },
    }
}

Was mem0 mit seinem LLM tatsächlich macht.

mem0 (mem0ai auf GitHub, rund 61.000 Stars) ist eine Memory-Schicht für AI-Agents. Jeder add()-Call läuft eine Pipeline: das LLM liest die neuen Konversations-Turns, extrahiert Kandidaten-Memories, vergleicht sie mit dem bereits Gespeicherten, und entscheidet pro Memory, ob hinzugefügt, aktualisiert, gelöscht oder übersprungen wird. Das ist echte Reasoning-Arbeit, und sie passiert bei jedem Schreibvorgang, weshalb der LLM-Slot weit häufiger feuert, als die meisten erwarten, wenn sie Memory an einen Produktions-Agent anschrauben. Retrieval ist die andere Hälfte, und sie nutzt das LLM überhaupt nicht: search() bettet die Query ein und läuft Vektor-Ähnlichkeit gegen den Store. Zwei verschiedene Clients, zwei verschiedene Modelle, konfiguriert in zwei verschiedenen Blöcken (llm und embedder). Diese Trennung ist das Wichtigste, was man verstehen muss, bevor man irgendetwas umleitet, weil sie bedeutet, dass du die Extraction-Workload auf ein Multi-Vendor-Gateway verschieben kannst, während der Embedder seinen bestehenden Provider und Index unangetastet behält. Der Provider bleibt "openai" in der Config; mem0 reicht das model-Feld als reinen String über /v1/chat/completions weiter. Bedient der Endpoint hinter openai_base_url mehrere Vendoren, kann dieser String eine Claude-, GPT-, DeepSeek- oder GLM-ID sein, und das Extraction-Modell zu wechseln wird eine Einzeiler-Config-Änderung statt einer Provider-Migration.

Vollständiges Setup: Config-Dict oder Umgebungsvariable.

Der Config-Dict-Pfad ist der präzise: er bewegt nur das LLM. Bau das Dict, gib es an Memory.from_config, und nutze die Memory-API wie gewohnt. Das Feld api_key hält den Gateway-Key vollständig aus deinen Vector-Store- und Embedder-Einstellungen heraus. Der Umgebungspfad existiert auch: mem0s OpenAI-Klassen lesen OPENAI_BASE_URL, wenn der Config-Key fehlt. Das ist eine exportierte Variable und null Code-Änderungen, aber beachte den Scope: die OpenAI-Klasse des Embedders liest dieselben Variablen (sie respektiert zudem den älteren Namen OPENAI_API_BASE, den die LLM-Klasse nicht kennt). Exportierst du OPENAI_BASE_URL, hast du beide Komponenten bewegt, was nur korrekt ist, wenn der Endpoint auch dein Embedding-Modell bedient. Im Zweifel bevorzuge das Config-Dict und lass die Umgebung in Ruhe.

import os
from mem0 import Memory

config = {
    "llm": {
        "provider": "openai",
        "config": {
            "model": "claude-sonnet-4-6",   # any catalog id
            "openai_base_url": "https://api.apisrouter.com/v1",
            "api_key": os.environ["APISROUTER_API_KEY"],
            "temperature": 0.1,
        },
    },
    # embedder block unchanged: keeps its own provider and key
}

m = Memory.from_config(config)
m.add("I prefer window seats and vegetarian meals.", user_id="alice")
print(m.search("seat preference?", user_id="alice"))

Das Extraction-Modell wählen.

Der praktische Loop: halte deinen Embedder fest, lass dieselben Konversations-Fixtures durch zwei oder drei Extraction-Modelle laufen, und diffe die gespeicherten Memories. Hinter einem Endpoint ist dieser Vergleich eine Config-String-Bearbeitung pro Kandidat, und das Nutzungslog pro Key bepreist den Run jedes Kandidaten für dich.

  • Extraction-Qualität ist Memory-Qualität. Das LLM entscheidet, was es wert ist, sich zu merken, und ob neue Information Altem widerspricht; ein Modell, das ein Update übersieht, verschmutzt Retrieval für jede zukünftige Session. claude-sonnet-4-6 und gpt-5.5 sind der verlässliche Mittelweg dieses Trade-offs.
  • Volumen liegt bei jedem Schreibvorgang an. Ein Chat-Produkt, das nach jedem Austausch add() aufruft, läuft Extraction tausendfach am Tag, weshalb eine schnelle ID wie claude-haiku-4-5-20251001 oder deepseek-v4-flash verhindert, dass die Memory-Schicht die Token-Rechnung dominiert.
  • Widerspruchsreiche Domänen (sich ändernde Präferenzen, ablaufende Fakten) profitieren von einem stärkeren Modell bei add(), selbst wenn es pro Call mehr kostet, weil eine falsche Update-Entscheidung teuer zu erkennen ist.
  • Temperature gehört niedrig. Extraction ist eine strukturierte Entscheidungsaufgabe, kein kreatives Schreiben; mem0 exponiert temperature im selben Config-Block, und rund 0,1 hält Add/Update/Delete-Entscheidungen konsistent.

Nutzungsbasiert · unter offiziellem Preis

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModellOffizieller PreisUnser Preis
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
Claude Haiku 4.5 20251001$1.00 / $5.00 per M$0.80 / $4.00 per M
DeepSeek V4 Flash$0.14 / $0.28 per M$0.10 / $0.30 per M
GLM-5.2$1.14 / $4.00 per M$1.10 / $4.00 per M

Die Fehlerbilder speziell für mem0.

Eine herumliegende OPENROUTER_API_KEY kapert das Routing. mem0s OpenAI-LLM-Klasse behandelt diese Variable als Sonderfall: ist sie gesetzt, wechselt die Klasse zu OpenRouters Endpoint und ignoriert deine Absicht. Erreichen Requests nicht die von dir konfigurierte Base URL, prüf zuerst diese Variable und entferne sie. Die Umgebungsvariable bewegt mehr, als du meintest. OPENAI_BASE_URL wird sowohl vom LLM als auch vom Embedder gelesen. Bedient das Gateway dein Embedding-Modell nicht, bricht ein Env-Level-Override search(), während add() weiter funktioniert, was sich als „Memory-Schreiben klappt, aber Retrieval ist leer oder fehlerhaft" darstellt. Beschränke den Override auf den llm-Config-Block, und der Embedder merkt nichts. Config-Keys sind SDK-spezifisch. Python ist snake_case (openai_base_url, api_key); TypeScript ist camelCase (openaiBaseUrl, apiKey). Ein camelCase-Key in einem Python-Dict wird still ignoriert, und du fällst auf den Default-Endpoint zurück, was exakt wie ein „funktioniert nicht" des Overrides aussieht. Model-IDs sind exakte Strings. mem0 validiert das model-Feld nicht; es reicht ihn weiter. Ein Tippfehler zeigt sich beim ersten add() als model-not-found-Fehler vom Gateway, und die /v1/models-Liste ist die maßgebliche Schreibweise. Den Embedder zu wechseln ist eine Index-Entscheidung, keine Config-Entscheidung. Embeddings verschiedener Modelle leben in verschiedenen Vektorräumen, also invalidiert das Umleiten des Embedders die Ähnlichkeit gegen bestehende Vektoren. Das LLM zu bewegen ist kostenlos; den Embedder zu bewegen bedeutet, den Store neu einzubetten. Plane beides als separate Migrationen.

Wer mem0 über ein Gateway routet.

  • Agent-Builder, die Assistants persistentes Memory hinzufügen. Extraction läuft bei jedem Schreibvorgang, also schlägt eine einzelne Billing-Fläche mit Nutzung pro Key ein zweites, an den Stack geschraubtes Vendor-Dashboard.
  • Teams, die Claude-Qualität-Extraction hinter einer OpenAI-förmigen Config wollen. Der Provider-String bleibt "openai"; nur Base URL und Model-ID ändern sich.
  • High-Volume-Chat-Produkte, die die Unit Cost der Memory-Schicht steuern, indem sie ein Frontier-Chat-Modell mit einer schnellen Extraction-ID paaren, beide über denselben Endpoint adressierbar.
  • Entwickler, die Extraction-Modelle nebeneinander evaluieren. Jeder Kandidat ist ein Model-String gegen feste Fixtures, keine neue Provider-Integration pro Vendor.
  • Entwickler ohne Zugang zum Billing eines bestimmten Vendors. Guthabenbasierter Zugang ohne Kartenpflicht entfernt die Sign-up-Abhängigkeit pro Provider.

Endpoint verifizieren und den ersten add() debuggen.

Bestätige, dass das Gateway das konfigurierte Modell listet, bevor du die Pipeline laufen lässt; das model-Feld muss exakt zu einer bedienten ID passen. First-Run-Fehler folgen einem Muster. Ein 401 bedeutet, dass der vom LLM aufgelöste Key nicht zum aufgelösten Endpoint passt, und weil beide aus einer Config-über-Env-Kaskade kommen, gib beide effektiven Werte aus, statt anzunehmen; ein api_key aus der Config mit einer Base URL aus der Umgebung (oder umgekehrt) ist ein klassischer Mismatch. Ein model-not-found-Fehler ist ein ID-Tippfehler. Requests, die sichtbar an openrouter.ai gehen, bedeuten, dass der OPENROUTER_API_KEY-Sonderfall gefeuert hat. Und scheitert search(), während add() funktioniert, hast du den Embedder versehentlich über die Umgebung mitbewegt; beschränke die Base URL auf den llm-Block. Sobald Memories fließen, zeigt die APIsRouter-Konsole Modell, Token-Zahlen und Ausgaben pro Anfrage. Extraction-Calls sind klein, aber unaufhörlich, und die Nutzungsansicht ist, wie du siehst, was die Memory-Schicht pro tausend Schreibvorgänge tatsächlich kostet, statt es zu schätzen.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Häufige Fragen

Welcher Config-Key zeigt mem0 auf einen custom OpenAI-kompatiblen Endpoint?

openai_base_url innerhalb der llm-Provider-Config in Python (openaiBaseUrl in TypeScript). Config-Werte überschreiben die Umgebungsvariable OPENAI_BASE_URL, die wiederum den Default https://api.openai.com/v1 überschreibt, also ist das Config-Dict der deterministischste Ort dafür.

Kann mem0 Memories mit Claude- oder DeepSeek-Modellen über dieses Setup extrahieren?

Ja. Der Provider bleibt "openai", und mem0 reicht das model-Feld als reinen String über /v1/chat/completions weiter. Jede vom Endpoint hinter openai_base_url bediente ID funktioniert, einschließlich Claude-, DeepSeek- und GLM-IDs.

Beeinflusst OPENAI_BASE_URL auch den Embedder?

Ja. mem0s OpenAI-Embedder liest dieselben Umgebungsvariablen (plus den älteren Namen OPENAI_API_BASE). Willst du nur das LLM bewegen, setze openai_base_url innerhalb des llm-Config-Blocks und lass die Umgebung unangetastet.

Muss ich meinen Embedder oder Vector Store ändern, um das zu nutzen?

Nein. Die Blöcke llm und embedder sind unabhängige Clients. Das Extraction-LLM kann über das Gateway routen, während der Embedder seinen aktuellen Provider behält und deine bestehenden Vektoren gültig bleiben. Den Embedder umzuleiten ist eine separate Migration, die Neu-Embedding des Stores erfordert.

Warum gehen meine mem0-Requests an OpenRouter statt an meine Base URL?

mem0s OpenAI-LLM-Klasse behandelt die Umgebungsvariable OPENROUTER_API_KEY als Sonderfall: ist sie gesetzt, leitet sie unabhängig von deiner Base URL zu OpenRouter um. Entferne diese Variable, und die openai_base_url-Konfiguration greift.

Gilt das für die gehostete Mem0-Plattform oder das Open-Source-SDK?

Das Open-Source-SDK (Memory / Memory.from_config), wo du die LLM-Config kontrollierst. Die gehostete Mem0-Plattform verwaltet ihre eigenen Model-Calls server-seitig, also greift eine custom Base URL, wenn du die Memory-Schicht selbst hostest.