Sessions and memory

กลไกหน่วยความจำ QMD

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

สิ่งที่เพิ่มขึ้นจากเอนจินในตัว

  • การจัดอันดับซ้ำและการขยายคำค้น เพื่อเพิ่มความครอบคลุมในการค้นคืน
  • จัดทำดัชนีไดเรกทอรีเพิ่มเติม - เอกสารโครงการ บันทึกของทีม หรือสิ่งใดก็ตามบนดิสก์
  • จัดทำดัชนีทรานสคริปต์เซสชัน - เรียกคืนบทสนทนาก่อนหน้า
  • ทำงานภายในเครื่องทั้งหมด - ทำงานร่วมกับ Plugin ผู้ให้บริการ llama.cpp อย่างเป็นทางการและ ดาวน์โหลดโมเดล GGUF โดยอัตโนมัติ
  • การย้อนกลับอัตโนมัติ - หาก 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

เปิดใช้งาน

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

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

วิธีทำงานของโปรแกรมเสริม

  • OpenClaw สร้างคอลเลกชันจากไฟล์หน่วยความจำในพื้นที่ทำงานและ memory.qmd.paths ที่กำหนดค่าไว้ จากนั้นเรียกใช้ qmd update เมื่อผู้จัดการ QMD เปิดขึ้น และเรียกใช้เป็นระยะหลังจากนั้น (memory.qmd.update.interval ค่าเริ่มต้นคือ 5m) การรีเฟรชทำงานผ่านโพรเซสย่อยของ QMD ไม่ใช่การสำรวจระบบไฟล์ ภายในโพรเซส โหมดการค้นหาเชิงความหมายยังเรียกใช้ qmd embed (memory.qmd.update.embedInterval ค่าเริ่มต้นคือ 60m)
  • QMD ยังคงเป็นเจ้าของ index.sqlite การกำหนดค่าคอลเลกชัน YAML และการดาวน์โหลด โมเดลภายใต้โฮม QMD ประจำเอเจนต์ สิ่งเหล่านี้เป็นอาร์ติแฟกต์ของเครื่องมือภายนอก ไม่ใช่ตารางสถานะของ OpenClaw การประสานงานที่ OpenClaw เป็นเจ้าของอยู่ใน SQLite เท่านั้น: สัญญาเช่าที่ใช้ร่วมกันหนึ่งรายการจำกัดงานการฝังระหว่างเอเจนต์ ขณะที่สัญญาเช่าหนึ่งรายการใน ฐานข้อมูลของแต่ละเอเจนต์จัดลำดับการเขียนคอลเลกชัน การอัปเดต และการฝังของเอเจนต์นั้น ไม่ให้ทำพร้อมกัน ขณะรัน ระบบจะไม่สร้างไฟล์เสริมล็อกของ QMD อีกต่อไป openclaw doctor --fix จะลบไฟล์เสริมที่เลิกใช้แล้วเฉพาะหลังจากพิสูจน์ว่าเจ้าของโพรเซสเดิมล้าสมัยแล้ว การอัปเกรดเป็นการเปลี่ยนผ่านแบบตัดขาดอย่างชัดเจน: หยุดและเริ่มโพรเซส OpenClaw ทุกตัวที่ ใช้ไดเรกทอรีสถานะร่วมกันใหม่ก่อนใช้เวอร์ชันใหม่ ไม่รองรับตัวเขียน QMD รุ่นเก่าและรุ่นใหม่ที่ทำงานร่วมกัน ขณะรัน ระบบตั้งใจไม่ล็อกทั้งไฟล์เสริมที่เลิกใช้แล้ว ควบคู่กัน
  • คอลเลกชันพื้นที่ทำงานเริ่มต้นติดตาม MEMORY.md รวมถึงโครงสร้าง memory/ memory.md ที่เป็นตัวพิมพ์เล็กจะไม่ถูกจัดทำดัชนีเป็นไฟล์หน่วยความจำระดับราก
  • ตัวสแกนของ QMD จะละเว้นพาธที่ซ่อนอยู่และไดเรกทอรีการขึ้นต่อกัน/บิลด์ ที่พบบ่อย เช่น .git, .cache, node_modules, vendor, dist และ build โดยค่าเริ่มต้น การเริ่มต้น Gateway จะไม่เตรียมใช้งาน QMD (memory.qmd.update.startup มีค่าเริ่มต้นเป็น off) ดังนั้นการบูตแบบเย็นจึงหลีกเลี่ยง การนำเข้ารันไทม์หน่วยความจำหรือการสร้างตัวเฝ้าดูระยะยาวก่อนมีการใช้ หน่วยความจำครั้งแรก
  • ตั้งค่า memory.qmd.update.startup เป็น idle หรือ immediate เพื่อเตรียมใช้งาน QMD เมื่อ Gateway เริ่มต้นอยู่ดี memory.qmd.update.onBoot มีค่าเริ่มต้นเป็น true และ เรียกใช้การรีเฟรชครั้งแรกเมื่อเริ่มต้น ตั้งค่าเป็น false เพื่อข้าม การรีเฟรชทันทีนั้น (ผู้จัดการระยะยาวยังคงเปิดขึ้นเมื่อกำหนดค่าช่วงเวลาการอัปเดตหรือการฝัง ดังนั้น QMD จึงยังคงเป็นเจ้าของตัวเฝ้าดู/ตัวจับเวลาตามปกติ)
  • การค้นหาใช้ searchMode ที่กำหนดค่าไว้ (ค่าเริ่มต้น: search; รองรับ vsearch และ query ด้วย) search ใช้เฉพาะ BM25 ดังนั้น OpenClaw จึงข้ามการตรวจสอบ ความพร้อมของเวกเตอร์เชิงความหมายและการบำรุงรักษาการฝังในโหมดนั้น หากโหมดหนึ่ง ล้มเหลว OpenClaw จะลองอีกครั้งด้วย qmd query
  • เมื่อ searchMode เป็น query ให้ตั้งค่า memory.qmd.rerank เป็น false เพื่อใช้ เส้นทางคำค้นแบบไฮบริดของ QMD โดยไม่มีตัวจัดอันดับซ้ำ (ต้องใช้ QMD 2.1 หรือใหม่กว่า) OpenClaw ส่ง --no-rerank ไปยังเส้นทาง CLI ของ QMD โดยตรง และส่ง rerank: false ไปยังเครื่องมือคำค้น MCP ของ QMD
  • สำหรับ QMD รุ่นที่ประกาศรองรับตัวกรองหลายคอลเลกชัน OpenClaw จะจัดกลุ่ม คอลเลกชันจากแหล่งเดียวกันไว้ในการเรียกค้น QMD ครั้งเดียว QMD รุ่นเก่า จะยังคงใช้การย้อนกลับที่เข้ากันได้โดยค้นทีละคอลเลกชัน
  • หาก QMD ล้มเหลวทั้งหมด OpenClaw จะย้อนกลับไปใช้เอนจิน SQLite ในตัว ความพยายามซ้ำในเทิร์นแชตจะเว้นช่วงสั้น ๆ หลังการเปิดล้มเหลว เพื่อให้ ไบนารีที่หายไปหรือการขึ้นต่อกันของโปรแกรมเสริมที่เสียไม่ก่อให้เกิดพายุการลองใหม่ openclaw memory status และการตรวจสอบ CLI แบบครั้งเดียวยังคงตรวจสอบ QMD โดยตรงอีกครั้ง

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

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

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

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

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

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

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

bash
qmd --help | grep -i collection

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

การแทนที่โมเดล

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

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

หลังเปลี่ยนโมเดลการฝัง ให้เรียกใช้การฝังอีกครั้งเพื่อให้ดัชนีตรงกับ ปริภูมิเวกเตอร์ใหม่

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

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

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

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

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

เปิดใช้การจัดทำดัชนีเซสชันเพื่อเรียกคืนบทสนทนาก่อนหน้า QMD ต้องใช้ทั้ง แหล่งเซสชัน memorySearch ทั่วไปและตัวส่งออกทรานสคริปต์ QMD:

json5
{  agents: {    defaults: {      memorySearch: {        experimental: { sessionMemory: true },        sources: ["memory", "sessions"],      },    },  },  memory: {    backend: "qmd",    qmd: {      sessions: { enabled: true },    },  },}

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

ผลลัพธ์จากเซสชันยังคงถูกกรองด้วย tools.sessions.visibility การมองเห็น tree เริ่มต้นรวมถึงเซสชันปัจจุบัน เซสชันที่เซสชันนี้สร้างขึ้น และเซสชันกลุ่มของเอเจนต์เดียวกันที่เฝ้าดูผ่านการรับรู้กลุ่มโดยรอบ เมื่อใช้ session.dmScope: "main" ผู้ใช้ในการตั้งค่า DM แบบหลายผู้ใช้จะแชร์เซสชันหลัก และสามารถเรียกคืนเนื้อหาจากกลุ่มที่เซสชันนั้นเฝ้าดู ใช้ dmScope แบบแยกตามคู่สนทนาเพื่อแยก DM หรือตั้งค่าการมองเห็นเป็น "self" เพื่อไม่ใช้การอ่าน เซสชันที่เฝ้าดูโดยรอบ เซสชันอื่นที่ไม่เกี่ยวข้องของเอเจนต์เดียวกันยังคงต้องใช้ การมองเห็น "agent"

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

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

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

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

การอ้างอิง

เมื่อ memory.citations เป็น auto หรือ on ส่วนย่อยการค้นหาจะได้รับ ส่วนท้าย Source: <path>#L<line> (หรือ #L<start>-L<end>) ในโหมด auto ส่วนท้ายจะถูกเพิ่มเฉพาะสำหรับเซสชันแชตโดยตรง ตั้งค่า memory.citations = "off" เพื่อละเว้นส่วนท้ายโดยยังคงส่งพาธให้ เอเจนต์ภายใน

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

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

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

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

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

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

หาก qmd --version ทำงานในเชลล์ แต่ OpenClaw ยังคงรายงาน spawn qmd ENOENT โพรเซส Gateway อาจมี PATH ที่แตกต่างจาก เชลล์แบบโต้ตอบ ให้ตรึงไบนารีอย่างชัดเจน:

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

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

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

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

QMD แบบ BM25 เท่านั้นยังคงพยายามบิลด์ llama.cpp ใช่หรือไม่ ตั้งค่า memory.qmd.searchMode = "search" OpenClaw จะถือว่าโหมดนั้นเป็น โหมดคำศัพท์เท่านั้น ข้ามการตรวจสอบสถานะเวกเตอร์ QMD และการบำรุงรักษาการฝัง และ ปล่อยให้การตั้งค่า vsearch หรือ query จัดการการตรวจสอบความพร้อมเชิงความหมาย

การค้นหาหมดเวลาใช่หรือไม่ เพิ่ม memory.qmd.limits.timeoutMs (ค่าเริ่มต้น: 4000ms) ตั้งค่าให้สูงขึ้น เช่น 120000 สำหรับฮาร์ดแวร์ที่ช้ากว่า ขีดจำกัดนี้ใช้กับ คำสั่งค้นหาของ QMD เองระหว่างการเรียก memory_search ของเอเจนต์ ส่วนการตั้งค่า การซิงค์ การย้อนกลับไปใช้เอนจินในตัว และงานคลังข้อมูลเสริมจะยังคงใช้เส้นตายที่สั้นกว่าของตนเอง

ผลลัพธ์ว่างในแชตกลุ่มหรือแชตช่องทางใช่หรือไม่ กรณีนี้เป็นพฤติกรรมที่คาดไว้สำหรับ memory.qmd.scope เริ่มต้น ซึ่งอนุญาตเฉพาะเซสชันโดยตรง เพิ่มกฎ allow สำหรับประเภทแชต group หรือ channel หากต้องการผลลัพธ์ QMD ในที่ดังกล่าว

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

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

การกำหนดค่า

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

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

Was this useful?
On this page

On this page