Sessions and memory

เอนจินหน่วยความจำ QMD

QMD คือไซด์คาร์ค้นหาแบบ local-first ที่ทำงาน ควบคู่กับ OpenClaw โดยรวม BM25, การค้นหาเวกเตอร์ และการจัดอันดับซ้ำไว้ใน ไบนารีเดียว และสามารถทำดัชนีเนื้อหานอกเหนือจากไฟล์หน่วยความจำในเวิร์กสเปซของคุณได้

สิ่งที่เพิ่มจากระบบในตัว

  • การจัดอันดับซ้ำและการขยายคำค้น เพื่อให้เรียกคืนผลลัพธ์ได้ดีขึ้น
  • ทำดัชนีไดเรกทอรีเพิ่มเติม -- เอกสารโปรเจกต์, โน้ตของทีม, หรืออะไรก็ตามบนดิสก์
  • ทำดัชนีทรานสคริปต์ของเซสชัน -- เรียกคืนบทสนทนาก่อนหน้า
  • ทำงานในเครื่องทั้งหมด -- ทำงานด้วยแพ็กเกจรันไทม์ node-llama-cpp ที่เป็นทางเลือก และ ดาวน์โหลดโมเดล GGUF อัตโนมัติ
  • ** fallback อัตโนมัติ** -- หาก QMD ใช้งานไม่ได้ OpenClaw จะถอยกลับไปใช้ เอนจินในตัวได้อย่างไร้รอยต่อ

เริ่มต้นใช้งาน

ข้อกำหนดเบื้องต้น

  • ติดตั้ง QMD: npm install -g @tobilu/qmd หรือ bun install -g @tobilu/qmd
  • บิลด์ SQLite ที่อนุญาตส่วนขยาย (brew install sqlite บน macOS)
  • QMD ต้องอยู่ใน PATH ของ Gateway
  • macOS และ Linux ใช้งานได้ทันที Windows รองรับได้ดีที่สุดผ่าน WSL2

เปิดใช้งาน

{
  memory: {
    backend: "qmd",
  },
}

OpenClaw จะสร้างโฮม QMD แบบครบในตัวภายใต้ ~/.openclaw/agents/<agentId>/qmd/ และจัดการวงจรชีวิตของไซด์คาร์ โดยอัตโนมัติ -- คอลเลกชัน, การอัปเดต และการรัน embedding จะถูกจัดการให้คุณ ระบบจะเลือกใช้รูปแบบคอลเลกชันและคำค้น MCP ของ QMD ปัจจุบันก่อน แต่ยังถอยกลับไปใช้ แฟล็กรูปแบบคอลเลกชันทางเลือกและชื่อเครื่องมือ MCP รุ่นเก่าเมื่อจำเป็น การปรับให้ตรงกันตอนบูตยังสร้างคอลเลกชันที่จัดการไว้แต่ค้างเก่ากลับไปเป็น รูปแบบ canonical อีกครั้ง เมื่อยังมีคอลเลกชัน QMD รุ่นเก่าที่มีชื่อเดียวกัน อยู่

วิธีทำงานของไซด์คาร์

  • OpenClaw สร้างคอลเลกชันจากไฟล์หน่วยความจำในเวิร์กสเปซและ memory.qmd.paths ที่กำหนดค่าไว้ จากนั้นรัน qmd update เมื่อเปิดตัวจัดการ QMD และรันเป็นระยะหลังจากนั้น (ค่าเริ่มต้นทุก 5 นาที) การรีเฟรชเหล่านี้ ทำงานผ่าน subprocess ของ QMD ไม่ใช่การ crawl ระบบไฟล์ในโปรเซสเดียวกัน โหมด semantic จะรัน qmd embed ด้วย
  • คอลเลกชันเวิร์กสเปซเริ่มต้นติดตาม MEMORY.md พร้อมกับทรี memory/ ส่วน memory.md ตัวพิมพ์เล็กจะไม่ถูกทำดัชนีเป็นไฟล์หน่วยความจำราก
  • สแกนเนอร์ของ QMD เองจะละเว้นพาธที่ซ่อนอยู่และไดเรกทอรี dependency/build ทั่วไป เช่น .git, .cache, node_modules, vendor, dist และ build การเริ่ม Gateway จะไม่เริ่มต้น QMD โดยค่าเริ่มต้น ดังนั้น cold boot จะหลีกเลี่ยงการนำเข้ารันไทม์หน่วยความจำหรือสร้าง watcher อายุยาวก่อน มีการใช้หน่วยความจำครั้งแรก
  • หากยังต้องการรีเฟรชตอนเริ่ม Gateway ให้ตั้ง memory.qmd.update.startup เป็น idle หรือ immediate การรีเฟรชตอนเริ่ม แบบ opt-in จะใช้พาธ subprocess ของ QMD แบบครั้งเดียว แทนการสร้าง watcher ในโปรเซสแบบเต็มที่มีอายุยาว
  • การค้นหาใช้ searchMode ที่กำหนดค่าไว้ (ค่าเริ่มต้น: search; ยังรองรับ vsearch และ query) search เป็น BM25 เท่านั้น ดังนั้น OpenClaw จะข้าม การ probe ความพร้อมของเวกเตอร์ semantic และการบำรุงรักษา embedding ในโหมดนั้น หากโหมดใดล้มเหลว OpenClaw จะลองใหม่ด้วย qmd query
  • เมื่อใช้ QMD รุ่นที่ประกาศตัวกรองหลายคอลเลกชัน OpenClaw จะรวม คอลเลกชันแหล่งเดียวกันไว้ในการเรียกค้นหา QMD ครั้งเดียว QMD รุ่นเก่าจะ ใช้ fallback แบบต่อคอลเลกชันที่เข้ากันได้ต่อไป
  • หาก QMD ล้มเหลวทั้งหมด OpenClaw จะถอยกลับไปใช้เอนจิน SQLite ในตัว ความพยายามซ้ำในแต่ละรอบแชตจะ back off สั้น ๆ หลังเปิดล้มเหลว เพื่อไม่ให้ ไบนารีที่ขาดหายหรือ dependency ของไซด์คาร์ที่เสียสร้างพายุการลองซ้ำ; openclaw memory status และการ probe CLI แบบครั้งเดียวยังคงตรวจ QMD โดยตรงอีกครั้ง

ประสิทธิภาพและความเข้ากันได้ของการค้นหา

OpenClaw รักษาพาธการค้นหา QMD ให้เข้ากันได้กับทั้งการติดตั้ง QMD ปัจจุบันและรุ่นเก่า

เมื่อเริ่มต้น OpenClaw จะตรวจข้อความช่วยเหลือของ QMD ที่ติดตั้งไว้หนึ่งครั้งต่อ manager หาก ไบนารีประกาศว่ารองรับตัวกรองหลายคอลเลกชัน OpenClaw จะค้นหาคอลเลกชันแหล่งเดียวกันทั้งหมด ด้วยคำสั่งเดียว:

qmd search "router notes" --json -n 10 -c memory-root-main -c memory-dir-main

วิธีนี้หลีกเลี่ยงการเริ่ม subprocess ของ QMD หนึ่งตัวสำหรับทุกคอลเลกชัน durable-memory คอลเลกชันทรานสคริปต์เซสชันจะอยู่ในกลุ่มแหล่งของตัวเอง ดังนั้นการค้นหาแบบผสม memory + sessions ยังคงให้ input สำหรับตัวกระจายผลลัพธ์จากทั้งสองแหล่ง

บิลด์ QMD รุ่นเก่ารับตัวกรองคอลเลกชันได้เพียงหนึ่งรายการ เมื่อ OpenClaw ตรวจพบบิลด์ เหล่านั้น ระบบจะคงพาธความเข้ากันได้ไว้และค้นหาแต่ละคอลเลกชัน แยกกันก่อนรวมและลบผลลัพธ์ซ้ำ

หากต้องการตรวจ contract ที่ติดตั้งไว้ด้วยตนเอง ให้รัน:

qmd --help | grep -i collection

ข้อความช่วยเหลือ QMD ปัจจุบันระบุว่าตัวกรองคอลเลกชันสามารถกำหนดเป้าหมายได้หนึ่งหรือหลายคอลเลกชัน ข้อความช่วยเหลือรุ่นเก่ามักอธิบายคอลเลกชันเดียว

การ override โมเดล

ตัวแปรสภาพแวดล้อมของโมเดล QMD จะถูกส่งผ่านแบบไม่เปลี่ยนแปลงจากโปรเซส Gateway ดังนั้นคุณสามารถปรับ QMD แบบ global ได้โดยไม่ต้องเพิ่ม config ใหม่ของ OpenClaw:

export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
export QMD_RERANK_MODEL="/absolute/path/to/reranker.gguf"
export QMD_GENERATE_MODEL="/absolute/path/to/generator.gguf"

หลังจากเปลี่ยนโมเดล embedding ให้รัน embedding อีกครั้งเพื่อให้ดัชนีตรงกับ vector space ใหม่

การทำดัชนีพาธเพิ่มเติม

ชี้ QMD ไปยังไดเรกทอรีเพิ่มเติมเพื่อให้ค้นหาได้:

{
  memory: {
    backend: "qmd",
    qmd: {
      paths: [{ name: "docs", path: "~/notes", pattern: "**/*.md" }],
    },
  },
}

snippet จากพาธเพิ่มเติมจะปรากฏเป็น qmd/<collection>/<relative-path> ใน ผลลัพธ์การค้นหา memory_get เข้าใจ prefix นี้และอ่านจาก root ของคอลเลกชัน ที่ถูกต้อง

การทำดัชนีทรานสคริปต์เซสชัน

เปิดใช้งานการทำดัชนีเซสชันเพื่อเรียกคืนบทสนทนาก่อนหน้า:

{
  memory: {
    backend: "qmd",
    qmd: {
      sessions: { enabled: true },
    },
  },
}

ทรานสคริปต์จะถูกส่งออกเป็นรอบ User/Assistant ที่ sanitize แล้วไปยังคอลเลกชัน QMD เฉพาะภายใต้ ~/.openclaw/agents/<id>/qmd/sessions/

ขอบเขตการค้นหา

โดยค่าเริ่มต้น ผลลัพธ์การค้นหา QMD จะแสดงในเซสชันแบบ direct และ channel (ไม่ใช่ groups) กำหนดค่า memory.qmd.scope เพื่อเปลี่ยนสิ่งนี้:

{
  memory: {
    qmd: {
      scope: {
        default: "deny",
        rules: [{ action: "allow", match: { chatType: "direct" } }],
      },
    },
  },
}

เมื่อ scope ปฏิเสธการค้นหา OpenClaw จะบันทึกคำเตือนพร้อม channel และ ประเภทแชตที่อนุมานได้ เพื่อให้ debug ผลลัพธ์ว่างได้ง่ายขึ้น

การอ้างอิง

เมื่อ memory.citations เป็น auto หรือ on snippet การค้นหาจะมี footer Source: <path#line> ตั้ง memory.citations = "off" เพื่อละเว้น footer แต่ยังส่งพาธให้ agent ภายใน

ควรใช้เมื่อใด

เลือก QMD เมื่อคุณต้องการ:

  • การจัดอันดับซ้ำเพื่อผลลัพธ์คุณภาพสูงขึ้น
  • ค้นหาเอกสารโปรเจกต์หรือโน้ตนอกเวิร์กสเปซ
  • เรียกคืนบทสนทนาเซสชันที่ผ่านมา
  • การค้นหาในเครื่องทั้งหมดโดยไม่ต้องใช้คีย์ API

สำหรับการตั้งค่าที่เรียบง่ายกว่า เอนจินในตัว ทำงานได้ดี โดยไม่มี dependency เพิ่มเติม

การแก้ไขปัญหา

ไม่พบ QMD? ตรวจสอบให้แน่ใจว่าไบนารีอยู่ใน PATH ของ Gateway หาก OpenClaw ทำงานเป็นบริการ ให้สร้าง symlink: sudo ln -s ~/.bun/bin/qmd /usr/local/bin/qmd

หาก qmd --version ทำงานใน shell ของคุณ แต่ OpenClaw ยังรายงาน spawn qmd ENOENT โปรเซส Gateway น่าจะมี PATH แตกต่างจาก interactive shell ของคุณ ให้ pin ไบนารีอย่างชัดเจน:

{
  memory: {
    backend: "qmd",
    qmd: {
      command: "/absolute/path/to/qmd",
    },
  },
}

ใช้ command -v qmd ในสภาพแวดล้อมที่ติดตั้ง QMD แล้วตรวจซ้ำ ด้วย openclaw memory status --deep

การค้นหาครั้งแรกช้ามาก? QMD ดาวน์โหลดโมเดล GGUF เมื่อใช้งานครั้งแรก ให้ pre-warm ด้วย qmd query "test" โดยใช้ XDG dirs เดียวกับที่ OpenClaw ใช้

มี subprocess ของ QMD จำนวนมากระหว่างการค้นหา? อัปเดต QMD หากทำได้ OpenClaw ใช้ โปรเซสเดียวสำหรับการค้นหาหลายคอลเลกชันแหล่งเดียวกัน เฉพาะเมื่อ QMD ที่ติดตั้งไว้ ประกาศว่ารองรับตัวกรอง -c หลายรายการ มิฉะนั้นจะคง fallback รุ่นเก่า แบบต่อคอลเลกชันไว้เพื่อความถูกต้อง

QMD แบบ BM25 เท่านั้นยังพยายาม build llama.cpp? ตั้ง memory.qmd.searchMode = "search" OpenClaw ถือว่าโหมดนั้นเป็น lexical-only, ไม่รันการ probe สถานะเวกเตอร์ QMD หรือการบำรุงรักษา embedding และปล่อยให้ การตรวจความพร้อม semantic เป็นของการตั้งค่า vsearch หรือ query

การค้นหา timeout? เพิ่ม memory.qmd.limits.timeoutMs (ค่าเริ่มต้น: 4000ms) ตั้งเป็น 120000 สำหรับฮาร์ดแวร์ที่ช้ากว่า

ผลลัพธ์ว่างในแชตกลุ่ม? ตรวจ memory.qmd.scope -- ค่าเริ่มต้นอนุญาตเฉพาะ เซสชัน direct และ channel

การค้นหาหน่วยความจำรากกว้างเกินไปกะทันหัน? รีสตาร์ท Gateway หรือรอ การปรับให้ตรงกันตอนเริ่มครั้งถัดไป OpenClaw จะสร้างคอลเลกชันที่จัดการไว้แต่ค้างเก่า กลับไปเป็นรูปแบบ canonical MEMORY.md และ memory/ เมื่อพบความขัดแย้ง ชื่อเดียวกัน

repo ชั่วคราวที่มองเห็นได้ในเวิร์กสเปซทำให้เกิด ENAMETOOLONG หรือการทำดัชนีเสีย? ขณะนี้ traversal ของ QMD ใช้พฤติกรรมสแกนเนอร์ QMD พื้นฐาน แทนกฎ symlink ในตัวของ OpenClaw ให้เก็บ checkout monorepo ชั่วคราวไว้ภายใต้ ไดเรกทอรีที่ซ่อน เช่น .tmp/ หรือนอก root QMD ที่ทำดัชนีไว้ จนกว่า QMD จะเปิดเผย การ traversal ที่ปลอดภัยต่อ cycle หรือการควบคุมการยกเว้นที่ชัดเจน

การกำหนดค่า

สำหรับพื้นผิว config ทั้งหมด (memory.qmd.*), โหมดการค้นหา, ช่วงเวลาการอัปเดต, กฎ scope และตัวปรับอื่นทั้งหมด ดูที่ เอกสารอ้างอิงการกำหนดค่าหน่วยความจำ

ที่เกี่ยวข้อง