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
เปิดใช้งาน
{ 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 จะ ค้นหาคอลเลกชันทั้งหมดจากแหล่งเดียวกันด้วยคำสั่งเดียว:
qmd search "router notes" --json -n 10 -c memory-root-main -c memory-dir-mainวิธีนี้หลีกเลี่ยงการเริ่มโพรเซสย่อย QMD หนึ่งรายการต่อคอลเลกชันหน่วยความจำถาวร
คอลเลกชันทรานสคริปต์เซสชันจะอยู่ในกลุ่มแหล่งข้อมูลของตนเอง ดังนั้นการค้นหาแบบผสม
memory + sessions จึงยังคงส่งข้อมูลจากทั้งสองแหล่งให้ตัวกระจาย
ความหลากหลายของผลลัพธ์
บิลด์ QMD รุ่นเก่ารับตัวกรองคอลเลกชันได้เพียงหนึ่งรายการ เมื่อ OpenClaw ตรวจพบบิลด์ เหล่านั้น ระบบจะคงเส้นทางความเข้ากันได้ไว้และค้นหาแต่ละคอลเลกชัน แยกกัน ก่อนผสานและขจัดผลลัพธ์ที่ซ้ำกัน
หากต้องการตรวจสอบสัญญาที่ติดตั้งไว้ด้วยตนเอง ให้เรียกใช้:
qmd --help | grep -i collectionความช่วยเหลือของ QMD ปัจจุบันกล่าวถึงการกำหนดเป้าหมายคอลเลกชันหนึ่งรายการขึ้นไป ส่วนความช่วยเหลือ รุ่นเก่ามักอธิบายคอลเลกชันเดียว
การแทนที่โมเดล
ตัวแปรสภาพแวดล้อมของโมเดล QMD จะถูกส่งต่อจากโพรเซส Gateway โดยไม่เปลี่ยนแปลง จึงสามารถปรับแต่ง QMD แบบส่วนกลางได้โดยไม่ต้องเพิ่มการกำหนดค่า 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"หลังเปลี่ยนโมเดลการฝัง ให้เรียกใช้การฝังอีกครั้งเพื่อให้ดัชนีตรงกับ ปริภูมิเวกเตอร์ใหม่
การจัดทำดัชนีพาธเพิ่มเติม
ชี้ QMD ไปยังไดเรกทอรีเพิ่มเติมเพื่อให้ค้นหาได้:
{ memory: { backend: "qmd", qmd: { paths: [{ name: "docs", path: "~/notes", pattern: "**/*.md" }], }, },}ส่วนย่อยจากพาธเพิ่มเติมจะปรากฏเป็น qmd/<collection>/<relative-path> ใน
ผลการค้นหา memory_get เข้าใจคำนำหน้านี้และอ่านจาก
รากคอลเลกชันที่ถูกต้อง
การจัดทำดัชนีทรานสคริปต์เซสชัน
เปิดใช้การจัดทำดัชนีเซสชันเพื่อเรียกคืนบทสนทนาก่อนหน้า QMD ต้องใช้ทั้ง
แหล่งเซสชัน memorySearch ทั่วไปและตัวส่งออกทรานสคริปต์ QMD:
{ 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 เพื่อเปลี่ยนแปลงสิ่งนี้:
{ 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 ที่แตกต่างจาก
เชลล์แบบโต้ตอบ ให้ตรึงไบนารีอย่างชัดเจน:
{ 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.*) โหมดการค้นหา ช่วงเวลาการอัปเดต
กฎขอบเขต และตัวเลือกอื่นทั้งหมด โปรดดู
ข้อมูลอ้างอิงการกำหนดค่าหน่วยความจำ