mem0 را در برابر یک base URL سفارشی سازگار با OpenAI اجرا کنید.

Updated 2026-07-29

provider OpenAI در mem0 یک کلید config به‌نام openai_base_url می‌گیرد. آن را روی https://api.apisrouter.com/v1 تنظیم کنید، یک کلید پاس دهید، و مدلی که حافظه‌ها را استخراج و به‌روزرسانی می‌کند می‌تواند هر id ای در کاتالوگ باشد، شامل Claude و DeepSeek، بدون لمس بقیه pipeline حافظه شما.

پاسخ سریع: یک کلید config داخل بلوک llm.

provider LLM OpenAI در mem0 endpoint خود را اول config، دوم محیط، سوم پیش‌فرض resolve می‌کند: self.config.openai_base_url، سپس متغیر محیطی OPENAI_BASE_URL، سپس https://api.openai.com/v1. پس تمیزترین override یک کلید در dict تنظیمات llm است: openai_base_url را روی https://api.apisrouter.com/v1 تنظیم کنید، api_key را کنار آن تنظیم کنید (یا OPENAI_API_KEY را export کنید)، و هر فراخوانی استخراج-حافظه از طریق gateway مسیردهی می‌شود. این رفتار upstream mem0 است، قابل‌خواندن در mem0/llms/openai.py، نه یک fork. SDK تایپ‌اسکریپت همان جفت را در camelCase افشا می‌کند: openaiBaseUrl و apiKey. مقادیر در dict تنظیمات بر متغیرهای محیطی غالب‌اند، که بر پیش‌فرض‌ها غالب‌اند، پس یک base URL سطح-config حتی روی ماشین‌هایی که OPENAI_BASE_URL جای دیگری اشاره می‌کند برنده می‌شود.

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

mem0 واقعاً با LLM خود چه می‌کند.

mem0 (mem0ai در GitHub، حدود ۶۱ هزار ستاره) یک لایه حافظه برای agent های AI است. هر فراخوانی add() یک pipeline اجرا می‌کند: LLM نوبت‌های جدید مکالمه را می‌خواند، حافظه‌های کاندید را استخراج می‌کند، آن‌ها را در برابر آنچه از قبل ذخیره شده مقایسه می‌کند، و به ازای هر حافظه تصمیم می‌گیرد اضافه، به‌روزرسانی، حذف، یا رد کند. آن کار استدلال واقعی است، و در هر نوشتن رخ می‌دهد، پس اسلات LLM بیشتر از آنچه بیشتر مردم انتظار دارند شلیک می‌شود وقتی حافظه را روی یک agent production پیچ می‌کنند. بازیابی نیمه دیگر است، و اصلاً از LLM استفاده نمی‌کند: search() query را embed می‌کند و شباهت vector را در برابر store اجرا می‌کند. دو client متفاوت، دو مدل متفاوت، پیکربندی‌شده در دو بلوک متفاوت (llm و embedder). این تفکیک مهم‌ترین چیزی است که باید قبل از مسیردهی مجدد هر چیزی درک کنید، چون یعنی می‌توانید workload استخراج را به یک gateway چند-vendor منتقل کنید در حالی که embedder provider و index موجودش را دست‌نخورده نگه می‌دارد. provider در config همچنان "openai" می‌ماند؛ mem0 فیلد model را به‌عنوان رشته ساده روی /v1/chat/completions فوروارد می‌کند. وقتی endpoint پشت openai_base_url چند vendor سرویس می‌دهد، آن رشته می‌تواند یک id Claude، GPT، DeepSeek، یا GLM باشد، و سوییچ مدل استخراج یک تغییر config یک‌خطی می‌شود به‌جای یک migration provider.

راه‌اندازی کامل: dict config یا متغیر محیطی.

مسیر config-dict دقیق‌ترین است: فقط LLM را جابه‌جا می‌کند. dict را بسازید، آن را به Memory.from_config بدهید، و API حافظه را عادی استفاده کنید. فیلد api_key کلید gateway را کاملاً بیرون از تنظیمات vector-store و embedder شما نگه می‌دارد. مسیر محیطی هم وجود دارد: کلاس‌های OpenAI در mem0 وقتی کلید config غایب باشد OPENAI_BASE_URL را می‌خوانند. یک متغیر export‌شده و صفر تغییر کد است، اما دامنه را توجه کنید: کلاس OpenAI embedder همان متغیرها را می‌خواند (همچنین نام قدیمی‌تر OPENAI_API_BASE را که کلاس LLM نمی‌خواند رعایت می‌کند). OPENAI_BASE_URL را export کنید و هر دو کامپوننت را جابه‌جا کرده‌اید، که فقط اگر endpoint مدل embedding شما را هم سرویس دهد درست است. وقتی مطمئن نیستید، dict config را ترجیح دهید و محیط را دست‌نزنید.

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

انتخاب مدل استخراج.

حلقه عملی: embedder خود را ثابت نگه دارید، همان fixture های مکالمه را از طریق دو یا سه مدل استخراج اجرا کنید، و حافظه‌های ذخیره‌شده را diff کنید. پشت یک endpoint آن مقایسه یک ویرایش رشته-config به ازای هر کاندید است، و usage log هر-کلید اجرای هر کاندید را برای شما قیمت‌گذاری می‌کند.

  • کیفیت استخراج کیفیت حافظه است. LLM تصمیم می‌گیرد چه چیزی ارزش به‌خاطرسپردن دارد و آیا اطلاعات جدید با قدیمی تناقض دارد؛ مدلی که یک به‌روزرسانی را از دست بدهد retrieval هر session آینده را آلوده می‌کند. claude-sonnet-4-6 و gpt-5.5 میانه قابل‌اعتماد این trade-off هستند.
  • حجم روی هر نوشتن است. یک محصول چت که add() را بعد از هر تبادل فرا می‌خواند استخراج را هزاران بار در روز اجرا می‌کند، که همان جایی است که یک id سریع مثل claude-haiku-4-5-20251001 یا deepseek-v4-flash لایه حافظه را از سلطه بر صورت‌حساب token باز می‌دارد.
  • حوزه‌های تناقض‌سنگین (ترجیحاتی که تغییر می‌کنند، حقایقی که منقضی می‌شوند) از یک مدل قوی‌تر روی add() سود می‌برند حتی اگر هر فراخوانی گران‌تر باشد، چون یک تصمیم به‌روزرسانی اشتباه بعداً کشف‌کردنش گران است.
  • temperature باید پایین باشد. استخراج یک وظیفه تصمیم-ساختاریافته است، نه نوشتن خلاقانه؛ mem0 temperature را در همان بلوک config افشا می‌کند، و حدود ۰.۱ تصمیم‌های add/update/delete را سازگار نگه می‌دارد.

پرداخت بر اساس مصرف · پایین‌تر از قیمت رسمی

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

مدلقیمت رسمیقیمت ما
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

حالت‌های شکست مختص mem0.

یک OPENROUTER_API_KEY باقی‌مانده مسیردهی را می‌ربایید. کلاس LLM OpenAI در mem0 آن متغیر را ویژه در نظر می‌گیرد: وقتی تنظیم شده، کلاس به endpoint OpenRouter سوییچ می‌کند و قصد شما را نادیده می‌گیرد. اگر درخواست‌ها به base URL ای که پیکربندی کرده‌اید نمی‌رسند، اول این متغیر را چک کنید و unset کنید. متغیر محیطی بیشتر از آنچه منظورتان بود جابه‌جا می‌کند. OPENAI_BASE_URL هم توسط LLM و هم توسط embedder خوانده می‌شود. اگر gateway مدل embedding شما را سرویس ندهد، یک override سطح-env search() را می‌شکند در حالی که add() همچنان کار می‌کند، که مثل «حافظه خوب می‌نویسد اما retrieval خالی یا خطادار است» ظاهر می‌شود. override را داخل بلوک config llm محدود کنید و embedder هرگز متوجه نمی‌شود. کلیدهای config به‌ازای-SDK هستند. Python به‌صورت snake_case است (openai_base_url، api_key)؛ تایپ‌اسکریپت camelCase است (openaiBaseUrl، apiKey). یک کلید camelCase در یک dict پایتون بی‌صدا نادیده گرفته می‌شود و شما به endpoint پیش‌فرض برمی‌گردید، که دقیقاً مثل «کارنکردن» override به‌نظر می‌رسد. id های مدل رشته‌های دقیق‌اند. mem0 فیلد model را اعتبارسنجی نمی‌کند؛ آن را فوروارد می‌کند. یک غلط‌تایپی به‌عنوان یک خطای model-not-found از gateway در اولین add() ظاهر می‌شود، و فهرست /v1/models نگارش معتبر است. تغییر embedder یک تصمیم index است، نه یک تصمیم config. embedding های مدل‌های مختلف در فضاهای vector مختلف زندگی می‌کنند، پس هدایت مجدد embedder شباهت در برابر vector های موجود را باطل می‌کند. جابه‌جایی LLM رایگان است؛ جابه‌جایی embedder یعنی re-embedding store. آن‌ها را به‌عنوان migration های جدا برنامه‌ریزی کنید.

چه کسانی mem0 را از طریق یک gateway مسیردهی می‌کنند.

  • سازندگان agent که حافظه پایدار به دستیارها اضافه می‌کنند. استخراج روی هر نوشتن اجرا می‌شود، پس یک سطح صورت‌حساب تکی با usage هر-کلید از یک dashboard vendor دوم پیچ‌شده به stack بهتر است.
  • تیم‌هایی که استخراج با کیفیت Claude پشت یک config به‌شکل OpenAI می‌خواهند. رشته provider "openai" می‌ماند؛ فقط base URL و id مدل تغییر می‌کند.
  • محصولات چت پرحجم که هزینه واحد لایه حافظه را با جفت‌کردن یک مدل چت frontier با یک id استخراج سریع کنترل می‌کنند، هرکدام از طریق همان endpoint قابل‌آدرس‌دهی.
  • توسعه‌دهندگانی که مدل‌های استخراج را کنار هم ارزیابی می‌کنند. هر کاندید یک رشته مدل در برابر fixture های ثابت است، نه یک integration provider جدید به ازای هر vendor.
  • توسعه‌دهندگان بدون دسترسی به صورت‌حساب یک vendor خاص. دسترسی مبتنی بر شارژ بدون الزام کارت وابستگی ثبت‌نام هر-provider را حذف می‌کند.

endpoint را تأیید کنید و اولین add() را عیب‌یابی کنید.

تأیید کنید gateway مدلی که پیکربندی کرده‌اید را قبل از اجرای pipeline فهرست می‌کند؛ فیلد model باید دقیقاً با یک id سرویس‌داده‌شده مطابقت داشته باشد. شکست‌های اجرای اول از یک الگو پیروی می‌کنند. یک 401 یعنی کلیدی که LLM resolve کرده برای endpoint ای که resolve کرده اشتباه است، و چون هر دو از یک آبشار config-بر-env می‌آیند، هر دو مقدار مؤثر را چاپ کنید به‌جای فرض‌کردن؛ یک api_key در config با یک base URL در env (یا برعکس) یک عدم‌تطابق کلاسیک است. یک خطای model-not-found یک غلط‌تایپی id است. درخواست‌هایی که به‌طور قابل‌مشاهده به openrouter.ai می‌روند یعنی case ویژه OPENROUTER_API_KEY شلیک شده. و اگر add() موفق شود در حالی که search() شکست بخورد، شما embedder را تصادفاً از طریق محیط جابه‌جا کرده‌اید؛ base URL را داخل بلوک llm محدود کنید. وقتی حافظه‌ها جاری شوند، کنسول APIsRouter مدل، شمارش token، و هزینه هر-درخواست را نشان می‌دهد. فراخوانی‌های استخراج کوچک اما بی‌امان‌اند، و نمای usage روشی است که می‌بینید لایه حافظه واقعاً به ازای هر هزار نوشتن چقدر هزینه دارد به‌جای تخمین آن.

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

پرسش‌های پرتکرار

کدام کلید config mem0 را به یک endpoint سفارشی سازگار با OpenAI اشاره می‌دهد؟

openai_base_url داخل config provider llm در پایتون (openaiBaseUrl در تایپ‌اسکریپت). مقادیر config بر متغیر محیطی OPENAI_BASE_URL غالب‌اند، که بر پیش‌فرض https://api.openai.com/v1 غالب است، پس dict config قطعی‌ترین جا برای تنظیم آن است.

آیا mem0 می‌تواند حافظه‌ها را با مدل‌های Claude یا DeepSeek از طریق این راه‌اندازی استخراج کند؟

بله. provider "openai" می‌ماند و mem0 فیلد model را به‌عنوان رشته ساده روی /v1/chat/completions فوروارد می‌کند. هر id ای که توسط endpoint پشت openai_base_url سرویس داده شود کار می‌کند، شامل id های Claude، DeepSeek، و GLM.

آیا تنظیم OPENAI_BASE_URL روی embedder هم اثر می‌گذارد؟

بله. embedder OpenAI در mem0 همان متغیرهای محیطی را می‌خواند (به‌علاوه نام قدیمی‌تر OPENAI_API_BASE). اگر فقط می‌خواهید LLM را جابه‌جا کنید، openai_base_url را داخل بلوک config llm تنظیم کنید و محیط را دست‌نخورده رها کنید.

آیا باید embedder یا vector store خود را برای استفاده از این تغییر دهم؟

خیر. بلوک‌های llm و embedder client های مستقل هستند. LLM استخراج می‌تواند از طریق gateway مسیردهی شود در حالی که embedder provider فعلی خود را نگه می‌دارد و vector های موجود شما معتبر می‌مانند. هدایت مجدد embedder یک migration جدا است که re-embedding store را الزامی می‌کند.

چرا درخواست‌های mem0 من به OpenRouter می‌روند به‌جای base URL من؟

کلاس LLM OpenAI در mem0 متغیر محیطی OPENROUTER_API_KEY را ویژه در نظر می‌گیرد: وقتی تنظیم شده، صرف‌نظر از base URL شما به OpenRouter هدایت مجدد می‌کند. آن متغیر را unset کنید و پیکربندی openai_base_url اثر می‌کند.

آیا این روی پلتفرم میزبانی‌شده Mem0 یا SDK متن‌باز اعمال می‌شود؟

SDK متن‌باز (Memory / Memory.from_config)، جایی که config LLM را کنترل می‌کنید. پلتفرم میزبانی‌شده Mem0 فراخوانی‌های مدل خودش را سمت-سرور مدیریت می‌کند، پس یک base URL سفارشی وقتی خودتان لایه حافظه را self-host می‌کنید اعمال می‌شود.