รัน mem0 บน custom OpenAI-compatible base URL

Updated 2026-07-29

OpenAI provider ของ mem0 รับ config key ชื่อ openai_base_url ตั้งค่าเป็น https://api.apisrouter.com/v1 ส่ง key เดียว แล้วโมเดลที่ดึงและ update ความจำก็เป็น id ใดก็ได้ในแคตตาล็อก รวมถึง Claude และ DeepSeek โดยไม่ต้องแตะ pipeline ความจำส่วนที่เหลือของคุณ

คำตอบสั้น ๆ: config key เดียวข้างใน block llm

OpenAI LLM provider ของ mem0 resolve endpoint ของมันเป็น config ก่อน environment รอง: self.config.openai_base_url แล้วตามด้วย environment variable OPENAI_BASE_URL แล้วตามด้วย https://api.openai.com/v1 ดังนั้นวิธี override ที่สะอาดที่สุดคือ key เดียวใน llm config dict: ตั้ง openai_base_url เป็น https://api.apisrouter.com/v1 ตั้ง api_key ควบคู่กัน (หรือ export OPENAI_API_KEY) แล้วทุกการเรียก memory-extraction จะ route ผ่าน gateway นี่คือพฤติกรรมของ mem0 ต้นทาง อ่านได้ใน mem0/llms/openai.py ไม่ใช่ fork TypeScript SDK เปิดคู่เดียวกันแบบ camelCase: openaiBaseUrl และ apiKey ค่าใน config dict ชนะ environment variable ซึ่งชนะค่าเริ่มต้นอีกที ดังนั้น 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 มีดาวประมาณ 61K) คือชั้นความจำสำหรับ AI agent ทุกการเรียก add() รัน pipeline: LLM อ่านเทิร์นบทสนทนาใหม่ ดึงความจำที่เป็นตัวเลือก เทียบมันกับสิ่งที่เก็บไว้แล้ว และตัดสินใจต่อความจำว่าจะ add, update, delete หรือ skip นั่นคือ reasoning จริง และมันเกิดขึ้นทุกครั้งที่เขียน ดังนั้นช่อง LLM ทำงานถี่กว่าที่คนส่วนใหญ่คาดเมื่อพวกเขาต่อ memory เข้ากับ agent ใน production Retrieval คืออีกครึ่งหนึ่ง และมันไม่ใช้ LLM เลย: search() embed คำถามแล้วรัน vector similarity เทียบกับ store client สองตัวที่ต่างกัน โมเดลสองตัวที่ต่างกัน ตั้งค่าใน block สองอันที่ต่างกัน (llm และ embedder) การแยกนี้คือสิ่งสำคัญที่สุดที่ต้องเข้าใจก่อนจะย้ายอะไรก็ตาม เพราะมันหมายความว่าคุณย้าย workload ของการดึงความจำไปที่ gateway หลาย vendor ได้ ในขณะที่ embedder ยังคง provider และ index เดิมไว้โดยไม่ถูกแตะ provider ยังคงเป็น "openai" ใน config; mem0 ส่งฟิลด์ model ผ่านเป็นสตริงธรรมดาผ่าน /v1/chat/completions เมื่อ endpoint หลัง openai_base_url เสิร์ฟหลาย vendor สตริงนั้นสามารถเป็น id ของ Claude, GPT, DeepSeek หรือ GLM และการสลับโมเดลที่ใช้ดึงความจำก็กลายเป็นการแก้ config หนึ่งบรรทัดแทนที่จะเป็นการย้าย provider

ตั้งค่าแบบเต็ม: config dict หรือ environment variable

เส้นทาง config-dict คือเส้นทางที่แม่นยำ: มันย้ายแค่ LLM สร้าง dict ส่งให้ Memory.from_config แล้วใช้ memory API ตามปกติ ฟิลด์ api_key เก็บ gateway key ไว้ไม่ให้ปนกับการตั้งค่า vector-store และ embedder เลย เส้นทาง environment ก็มีอยู่เช่นกัน: คลาส OpenAI ของ mem0 อ่าน OPENAI_BASE_URL เมื่อไม่มี config key เป็น environment variable ที่ export ตัวเดียวและไม่ต้องแก้โค้ดเลย แต่สังเกตขอบเขต: คลาส embedder ของ OpenAI อ่านตัวแปร environment เดียวกัน (มันยังรับชื่อเก่ากว่า OPENAI_API_BASE ด้วย ซึ่งคลาส LLM ไม่รับ) export OPENAI_BASE_URL แล้วคุณย้ายทั้งสองส่วน ซึ่งถูกต้องก็ต่อเมื่อ endpoint เสิร์ฟ embedding model ของคุณด้วย เมื่อไม่แน่ใจ ให้เลือก config dict แล้วปล่อย environment ไว้เฉย ๆ

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

เลือกโมเดลสำหรับการดึงความจำ

loop ที่ใช้จริง: ตรึง embedder ของคุณไว้ รันชุดบทสนทนาทดสอบเดียวกันผ่านโมเดล extraction สองหรือสามตัว แล้ว diff ความจำที่เก็บไว้ อยู่หลัง endpoint เดียว การเปรียบเทียบนั้นก็แค่แก้ไข config string ต่อผู้เข้าแข่งขัน และ usage log ต่อ key ตั้งราคาการรันของแต่ละผู้เข้าแข่งขันให้คุณ

  • คุณภาพการดึงความจำคือคุณภาพความจำ LLM ตัดสินว่าอะไรควรจำและข้อมูลใหม่ขัดแย้งกับข้อมูลเก่าไหม โมเดลที่พลาด update จะทำให้ retrieval เสียหายในทุก session ในอนาคต claude-sonnet-4-6 และ gpt-5.5 คือจุดกึ่งกลางที่เชื่อถือได้ของการแลกเปลี่ยนนี้
  • ปริมาณเกิดขึ้นในทุกการเขียน ผลิตภัณฑ์แชทที่เรียก add() หลังทุกการสนทนาจะรัน extraction หลายพันครั้งต่อวัน ซึ่งเป็นจุดที่ id เร็วอย่าง claude-haiku-4-5-20251001 หรือ deepseek-v4-flash ช่วยไม่ให้ชั้นความจำครองบิล token
  • domain ที่ขัดแย้งกันมาก (สิ่งที่ชอบเปลี่ยนไป ข้อเท็จจริงที่หมดอายุ) ได้ประโยชน์จากโมเดลที่แข็งแกร่งกว่าบน add() แม้จะแพงกว่าต่อการเรียก เพราะการตัดสินใจ update ที่ผิดมีค่าใช้จ่ายสูงในการตรวจพบทีหลัง
  • temperature ควรต่ำ Extraction เป็นงานตัดสินใจแบบมีโครงสร้าง ไม่ใช่งานเขียนเชิงสร้างสรรค์ mem0 เปิด temperature ใน config block เดียวกัน และประมาณ 0.1 ทำให้การตัดสินใจ 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 ที่หลงเหลืออยู่จะแย่งการ routing คลาส OpenAI LLM ของ mem0 มี special case สำหรับตัวแปรนั้น: เมื่อมันถูกตั้งค่า คลาสจะสลับไปที่ endpoint ของ OpenRouter และเมิน intent ของคุณ ถ้า request ไม่ไปถึง base URL ที่คุณตั้งค่าไว้ เช็กตัวแปรนี้ก่อนแล้ว unset มัน environment variable ย้ายมากกว่าที่คุณตั้งใจ OPENAI_BASE_URL ถูกอ่านทั้งโดย LLM และ embedder ถ้า gateway ไม่เสิร์ฟ embedding model ของคุณ การ override ระดับ env จะทำให้ search() พังในขณะที่ add() ยังทำงานได้ ซึ่งแสดงออกเป็น "memory เขียนได้ดี แต่ retrieval ว่างเปล่าหรือ error" ขอบเขต override ไว้แค่ block config llm แล้ว embedder จะไม่รู้เรื่องเลย config key เป็นแบบต่อ SDK Python เป็น snake_case (openai_base_url, api_key); TypeScript เป็น camelCase (openaiBaseUrl, apiKey) camelCase key ใน Python dict จะถูกเมินอย่างเงียบ ๆ และคุณจะตกไปที่ endpoint เริ่มต้น ซึ่งดูเหมือน override "ไม่ทำงาน" เป๊ะ model id เป็นสตริงที่ต้องเป๊ะ mem0 ไม่ตรวจสอบฟิลด์ model มันแค่ส่งผ่าน การพิมพ์ผิดปรากฏเป็น error model-not-found จาก gateway ตอน add() ครั้งแรก และรายการ /v1/models คือการสะกดที่เชื่อถือได้ การเปลี่ยน embedder คือการตัดสินใจเรื่อง index ไม่ใช่การตัดสินใจเรื่อง config Embedding จากโมเดลต่างกันอยู่ใน vector space ต่างกัน ดังนั้นการเปลี่ยน embedder ทำให้ similarity เทียบกับ vector เดิมใช้ไม่ได้ การย้าย LLM ไม่มีค่าใช้จ่าย การย้าย embedder หมายความว่าต้อง re-embed store วางแผนให้เป็นการย้ายระบบแยกกัน

ใครที่ route mem0 ผ่าน gateway

  • builder ของ agent ที่เพิ่มความจำถาวรให้ assistant Extraction รันทุกครั้งที่เขียน ดังนั้นพื้นผิวเก็บเงินเดียวพร้อม usage ต่อ key ชนะ dashboard vendor ที่สองที่ต่อเข้ากับ stack
  • ทีมที่ต้องการ extraction คุณภาพ Claude เบื้องหลัง config ทรง OpenAI provider string ยังเป็น "openai"; มีแค่ base URL และ model id ที่เปลี่ยน
  • ผลิตภัณฑ์แชทปริมาณสูงที่ควบคุมต้นทุนต่อหน่วยของชั้นความจำ โดยจับคู่ chat model ระดับ frontier กับ id extraction ที่เร็ว แต่ละตัวเข้าถึงได้ผ่าน endpoint เดียวกัน
  • นักพัฒนาที่ประเมินโมเดล extraction เทียบกัน ผู้เข้าแข่งขันแต่ละรายเป็นแค่ model string เดียวเทียบกับ fixture คงที่ ไม่ใช่การเชื่อมต่อ provider ใหม่ต่อ vendor
  • นักพัฒนาที่ไม่มีสิทธิ์เข้าถึงระบบเก็บเงินของ vendor รายหนึ่ง การเข้าถึงแบบเติมเงินโดยไม่ต้องใช้บัตรตัดการพึ่งพาการสมัครต่อ provider ออกไป

ตรวจสอบ endpoint และ debug add() แรก

ยืนยันว่า gateway ลิสต์โมเดลที่คุณตั้งค่าไว้ก่อนรัน pipeline; ฟิลด์ model ต้องตรงกับ id ที่เสิร์ฟจริงเป๊ะ ความล้มเหลวในการรันครั้งแรกมีรูปแบบ 401 หมายความว่า key ที่ LLM resolve ได้ผิดสำหรับ endpoint ที่มัน resolve ได้ และเพราะทั้งคู่มาจาก cascade config-over-env ให้ print ค่าที่มีผลจริงทั้งสองแทนที่จะสมมติ; api_key ใน config กับ base URL ใน env (หรือกลับกัน) คือความไม่ตรงกันแบบคลาสสิก error model-not-found คือการพิมพ์ id ผิด request ที่ไปที่ openrouter.ai อย่างเห็นได้ชัดหมายความว่า special case ของ OPENROUTER_API_KEY ทำงาน และถ้า add() สำเร็จในขณะที่ search() ล้มเหลว คุณย้าย embedder ไปโดยไม่ตั้งใจผ่าน environment; ขอบเขต base URL ไว้ที่ block llm เมื่อความจำไหลลื่นแล้ว console ของ APIsRouter แสดงโมเดลต่อ request, จำนวน token และค่าใช้จ่าย การเรียก extraction มีขนาดเล็กแต่ไม่หยุดหย่อน และมุมมอง usage คือวิธีที่คุณเห็นว่าชั้นความจำมีค่าใช้จ่ายจริงเท่าไหร่ต่อการเขียนหนึ่งพันครั้ง แทนที่จะประมาณเอา

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

คำถามที่พบบ่อย

config key ตัวไหนชี้ mem0 ไปที่ custom OpenAI-compatible endpoint?

openai_base_url ข้างใน config ของ llm provider ใน Python (openaiBaseUrl ใน TypeScript) ค่าใน config ชนะ environment variable OPENAI_BASE_URL ซึ่งชนะค่าเริ่มต้น https://api.openai.com/v1 ดังนั้น config dict คือที่ที่ตั้งค่าได้แน่นอนที่สุด

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 อ่านตัวแปร environment เดียวกัน (บวกชื่อเก่ากว่า OPENAI_API_BASE) ถ้าคุณต้องการย้ายแค่ LLM ให้ตั้ง openai_base_url ข้างใน block config llm แล้วปล่อย environment ไว้เฉย ๆ

ต้องเปลี่ยน embedder หรือ vector store เพื่อใช้สิ่งนี้ไหม?

ไม่ต้อง block llm และ embedder เป็น client อิสระจากกัน LLM extraction สามารถ route ผ่าน gateway ในขณะที่ embedder ยังคง provider เดิมและ vector ที่มีอยู่ยังใช้ได้ การเปลี่ยน embedder เป็นการย้ายระบบแยกที่ต้อง re-embed store

ทำไม request ของ mem0 ไปที่ OpenRouter แทนที่จะเป็น base URL ของฉัน?

คลาส OpenAI LLM ของ mem0 มี special case สำหรับ environment variable OPENROUTER_API_KEY: เมื่อตั้งค่าไว้ มันจะ reroute ไปที่ OpenRouter โดยไม่สนใจ base URL ของคุณ unset ตัวแปรนั้นแล้วการตั้งค่า openai_base_url จะมีผล

สิ่งนี้ใช้กับ Mem0 platform ที่ hosted หรือ SDK แบบ open-source?

SDK แบบ open-source (Memory / Memory.from_config) ที่คุณควบคุม LLM config Mem0 platform ที่ hosted จัดการการเรียกโมเดลของตัวเองฝั่ง server ดังนั้น custom base URL ใช้ได้เมื่อคุณ self-host ชั้นความจำเอง