Faites tourner mem0 contre une base URL personnalisée compatible OpenAI.

Updated 2026-07-29

Le fournisseur OpenAI de mem0 prend une clé de config openai_base_url. Réglez-la sur https://api.apisrouter.com/v1, passez une seule clé, et le modèle qui extrait et met à jour les mémoires peut être n'importe quel id du catalogue, Claude et DeepSeek inclus, sans toucher au reste de votre pipeline de mémoire.

Réponse rapide : une clé de config à l'intérieur du bloc llm.

Le fournisseur LLM OpenAI de mem0 résout son endpoint d'abord par la config, ensuite par l'environnement, enfin par le défaut : self.config.openai_base_url, puis la variable d'environnement OPENAI_BASE_URL, puis https://api.openai.com/v1. Donc la surcharge la plus propre est une seule clé dans le dict de config llm : réglez openai_base_url sur https://api.apisrouter.com/v1, réglez api_key à côté (ou exportez OPENAI_API_KEY), et chaque appel d'extraction de mémoire achemine via la passerelle. C'est un comportement du mem0 officiel, lisible dans mem0/llms/openai.py, pas un fork. Le SDK TypeScript expose la même paire en camelCase : openaiBaseUrl et apiKey. Les valeurs du dict de config l'emportent sur les variables d'environnement, qui l'emportent sur les défauts, donc une base URL au niveau de la config gagne même sur des machines où OPENAI_BASE_URL pointe ailleurs.

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"],
        },
    }
}

Ce que mem0 fait réellement avec son LLM.

mem0 (mem0ai sur GitHub, environ 61 000 étoiles) est une couche de mémoire pour agents IA. Chaque appel add() fait tourner un pipeline : le LLM lit les nouveaux échanges de conversation, extrait des mémoires candidates, les compare à ce qui est déjà stocké, et décide par mémoire s'il faut ajouter, mettre à jour, supprimer ou ignorer. C'est du vrai travail de raisonnement, et cela se produit à chaque écriture, donc l'emplacement LLM se déclenche bien plus souvent que la plupart des gens ne s'y attendent quand ils boulonnent de la mémoire sur un agent de production. La récupération est l'autre moitié, et elle n'utilise pas du tout le LLM : search() embarque la requête et lance une similarité vectorielle contre le store. Deux clients différents, deux modèles différents, configurés dans deux blocs différents (llm et embedder). Cette séparation est la chose la plus importante à comprendre avant de rerouter quoi que ce soit, parce qu'elle signifie que vous pouvez déplacer la charge d'extraction vers une passerelle multi-fournisseurs tandis que l'embedder garde son fournisseur et son index existants intacts. Le provider reste « openai » dans la config ; mem0 transmet le champ model tel quel comme simple chaîne via /v1/chat/completions. Quand l'endpoint derrière openai_base_url sert plusieurs fournisseurs, cette chaîne peut être un id Claude, GPT, DeepSeek ou GLM, et changer le modèle d'extraction devient une modification de config sur une ligne plutôt qu'une migration de fournisseur.

Configuration complète : dict de config ou variable d'environnement.

Le chemin du dict de config est le plus précis : il ne déplace que le LLM. Construisez le dict, passez-le à Memory.from_config, et utilisez l'API de mémoire normalement. Le champ api_key garde la clé de passerelle complètement en dehors de vos réglages de vector-store et d'embedder. Le chemin d'environnement existe aussi : les classes OpenAI de mem0 lisent OPENAI_BASE_URL quand la clé de config est absente. C'est une variable exportée et zéro changement de code, mais notez la portée : la classe OpenAI de l'embedder lit les mêmes variables (elle honore aussi l'ancien nom OPENAI_API_BASE, que la classe LLM n'honore pas). Exportez OPENAI_BASE_URL et vous avez déplacé les deux composants, ce qui n'est correct que si l'endpoint sert aussi votre modèle d'embedding. Dans le doute, préférez le dict de config et laissez l'environnement tranquille.

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

Choisir le modèle d'extraction.

La boucle pratique : gardez votre embedder fixe, faites passer les mêmes fixtures de conversation à travers deux ou trois modèles d'extraction, et comparez les mémoires stockées. Derrière un seul endpoint, cette comparaison est une édition de chaîne de config par candidat, et le journal d'usage par clé chiffre l'exécution de chaque candidat pour vous.

  • La qualité d'extraction est la qualité de mémoire. Le LLM décide ce qui vaut la peine d'être retenu et si une nouvelle information contredit l'ancienne ; un modèle qui rate une mise à jour pollue la récupération pour chaque session future. claude-sonnet-4-6 et gpt-5.5 sont le juste milieu fiable de ce compromis.
  • Le volume est présent à chaque écriture. Un produit de chat qui appelle add() après chaque échange fait tourner l'extraction des milliers de fois par jour, et c'est là qu'un id rapide comme claude-haiku-4-5-20251001 ou deepseek-v4-flash empêche la couche mémoire de dominer la facture de tokens.
  • Les domaines riches en contradictions (préférences qui changent, faits qui expirent) bénéficient d'un modèle plus puissant sur add() même s'il coûte plus par appel, parce qu'une mauvaise décision de mise à jour est coûteuse à détecter plus tard.
  • La temperature doit rester basse. L'extraction est une tâche de décision structurée, pas de l'écriture créative ; mem0 expose temperature dans le même bloc de config, et autour de 0,1 garde les décisions add/update/delete cohérentes.

Paiement à l'usage · en dessous du tarif officiel

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

ModèlePrix officielNotre prix
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

Les modes d'échec spécifiques à mem0.

Une OPENROUTER_API_KEY traînante détourne le routage. La classe LLM OpenAI de mem0 traite cette variable comme un cas spécial : quand elle est réglée, la classe bascule vers l'endpoint d'OpenRouter et ignore votre intention. Si les requêtes n'atteignent pas la base URL que vous avez configurée, vérifiez d'abord cette variable et déréglez-la. La variable d'environnement déplace plus que ce que vous vouliez. OPENAI_BASE_URL est lue à la fois par le LLM et par l'embedder. Si la passerelle ne sert pas votre modèle d'embedding, une surcharge au niveau de l'environnement casse search() tandis qu'add() continue de fonctionner, ce qui se présente comme « la mémoire s'écrit bien mais la récupération est vide ou en erreur ». Cantonnez la surcharge au bloc de config llm et l'embedder ne s'en aperçoit jamais. Les clés de config sont par SDK. Python est en snake_case (openai_base_url, api_key) ; TypeScript est en camelCase (openaiBaseUrl, apiKey). Une clé en camelCase dans un dict Python est ignorée silencieusement et vous retombez sur l'endpoint par défaut, ce qui ressemble exactement à une surcharge qui « ne fonctionne pas ». Les ids de modèles sont des chaînes exactes. mem0 ne valide pas le champ model ; il le transmet. Une faute de frappe apparaît comme une erreur model-not-found de la passerelle au premier add(), et le listing /v1/models fait foi pour l'orthographe. Changer d'embedder est une décision d'index, pas une décision de config. Les embeddings de différents modèles vivent dans des espaces vectoriels différents, donc repointer l'embedder invalide la similarité contre les vecteurs existants. Déplacer le LLM est gratuit ; déplacer l'embedder signifie ré-embarquer le store. Planifiez-les comme des migrations séparées.

Qui route mem0 via une passerelle.

  • Les créateurs d'agents qui ajoutent de la mémoire persistante à des assistants. L'extraction tourne à chaque écriture, donc une seule surface de facturation avec un usage par clé bat un second tableau de bord fournisseur boulonné sur la pile.
  • Les équipes qui veulent une extraction de qualité Claude derrière une config à la forme OpenAI. La chaîne provider reste « openai » ; seuls la base URL et l'id de modèle changent.
  • Les produits de chat à haut volume qui contrôlent le coût unitaire de la couche mémoire en associant un chat model frontier à un id d'extraction rapide, chacun adressable via le même endpoint.
  • Les développeurs qui évaluent des modèles d'extraction côte à côte. Chaque candidat est une chaîne de modèle contre des fixtures fixes, pas une nouvelle intégration de fournisseur par vendeur.
  • Les développeurs sans accès à la facturation d'un fournisseur donné. Un accès basé sur la recharge, sans exigence de carte, supprime la dépendance à une inscription par fournisseur.

Vérifiez l'endpoint et déboguez le premier add().

Confirmez que la passerelle liste le modèle que vous avez configuré avant de lancer le pipeline ; le champ model doit correspondre exactement à un id servi. Les échecs au premier lancement suivent un motif. Un 401 signifie que la clé résolue par le LLM est incorrecte pour l'endpoint qu'il a résolu, et comme les deux viennent d'une cascade config-sur-environnement, affichez les deux valeurs effectives plutôt que de supposer ; un api_key de config avec une base URL d'environnement (ou l'inverse) est un décalage classique. Une erreur model-not-found est une faute de frappe d'id. Des requêtes visiblement envoyées vers openrouter.ai signifient que le cas spécial OPENROUTER_API_KEY s'est déclenché. Et si add() réussit tandis que search() échoue, vous avez déplacé l'embedder par accident via l'environnement ; cantonnez la base URL dans le bloc llm. Une fois les mémoires en circulation, la console APIsRouter affiche le modèle par requête, le nombre de tokens et la dépense. Les appels d'extraction sont petits mais incessants, et la vue d'usage est la façon de voir ce que la couche mémoire coûte réellement par millier d'écritures plutôt que de l'estimer.

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

Questions fréquentes

Quelle clé de config pointe mem0 vers un endpoint compatible OpenAI personnalisé ?

openai_base_url à l'intérieur de la config du provider llm en Python (openaiBaseUrl en TypeScript). Les valeurs de config l'emportent sur la variable d'environnement OPENAI_BASE_URL, qui l'emporte sur le défaut https://api.openai.com/v1, donc le dict de config est l'endroit le plus déterministe pour la régler.

mem0 peut-il extraire des mémoires avec des modèles Claude ou DeepSeek via cette configuration ?

Oui. Le provider reste « openai » et mem0 transmet le champ model comme simple chaîne via /v1/chat/completions. Tout id servi par l'endpoint derrière openai_base_url fonctionne, y compris les ids Claude, DeepSeek et GLM.

Régler OPENAI_BASE_URL affecte-t-il aussi l'embedder ?

Oui. L'embedder OpenAI de mem0 lit les mêmes variables d'environnement (plus l'ancien nom OPENAI_API_BASE). Si vous voulez seulement déplacer le LLM, réglez openai_base_url à l'intérieur du bloc de config llm et laissez l'environnement intact.

Dois-je changer mon embedder ou mon vector store pour utiliser cela ?

Non. Les blocs llm et embedder sont des clients indépendants. Le LLM d'extraction peut router via la passerelle tandis que l'embedder garde son fournisseur actuel et vos vecteurs existants restent valides. Repointer l'embedder est une migration séparée qui exige de ré-embarquer le store.

Pourquoi mes requêtes mem0 vont-elles vers OpenRouter au lieu de ma base URL ?

La classe LLM OpenAI de mem0 traite la variable d'environnement OPENROUTER_API_KEY comme un cas spécial : quand elle est réglée, elle reroute vers OpenRouter quelle que soit votre base URL. Déréglez cette variable et la configuration openai_base_url prend effet.

Cela s'applique-t-il à la plateforme Mem0 hébergée ou au SDK open source ?

Le SDK open source (Memory / Memory.from_config), où vous contrôlez la config LLM. La plateforme Mem0 hébergée gère ses propres appels de modèle côté serveur, donc une base URL personnalisée s'applique quand vous auto-hébergez la couche mémoire.