Sessions and memory

موتور حافظه QMD

QMD یک سایدکار جست‌وجوی local-first است که در کنار 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/ می‌سازد و چرخه‌ی عمر سایدکار را خودکار مدیریت می‌کند -- مجموعه‌ها، به‌روزرسانی‌ها، و اجرای embedding برای شما انجام می‌شوند. این حالت شکل‌های فعلی مجموعه‌ی QMD و پرس‌وجوی MCP را ترجیح می‌دهد، اما در صورت نیاز همچنان به flagهای الگوی مجموعه‌ی جایگزین و نام‌های قدیمی‌تر ابزار MCP برمی‌گردد. همگام‌سازی زمان راه‌اندازی همچنین وقتی مجموعه‌ی قدیمی‌تر QMD با همان نام هنوز وجود دارد، مجموعه‌های مدیریت‌شده‌ی کهنه را دوباره با الگوهای کانونی‌شان می‌سازد.

سایدکار چگونه کار می‌کند

  • OpenClaw از فایل‌های حافظه‌ی فضای کاری شما و هر memory.qmd.paths پیکربندی‌شده مجموعه می‌سازد، سپس هنگام باز شدن مدیر QMD و به‌صورت دوره‌ای پس از آن (پیش‌فرض هر ۵ دقیقه) qmd update را اجرا می‌کند. این تازه‌سازی‌ها از طریق زیرفرایندهای QMD اجرا می‌شوند، نه یک خزش فایل‌سیستمی درون‌فرایندی. حالت‌های معنایی همچنین qmd embed را اجرا می‌کنند.
  • مجموعه‌ی پیش‌فرض فضای کاری MEMORY.md به‌همراه درخت memory/ را دنبال می‌کند. memory.md با حروف کوچک به‌عنوان فایل حافظه‌ی ریشه نمایه‌سازی نمی‌شود.
  • اسکنر خود QMD مسیرهای مخفی و دایرکتوری‌های رایج وابستگی/ساخت مانند .git، .cache، node_modules، vendor، dist، و build را نادیده می‌گیرد. راه‌اندازی Gateway به‌طور پیش‌فرض QMD را مقداردهی اولیه نمی‌کند، بنابراین بوت سرد پیش از نخستین استفاده از حافظه، از import کردن runtime حافظه یا ساخت watcher بلندمدت جلوگیری می‌کند.
  • اگر با این حال می‌خواهید QMD هنگام شروع Gateway مقداردهی اولیه شود، memory.qmd.update.startup را روی idle یا immediate بگذارید. با memory.qmd.update.onBoot: true، راه‌اندازی تازه‌سازی اولیه را اجرا می‌کند. با onBoot: false، راه‌اندازی آن تازه‌سازی فوری را رد می‌کند اما وقتی بازه‌های update یا embed پیکربندی شده باشند همچنان مدیر بلندمدت را باز می‌کند، تا QMD بتواند watcher و timerهای منظم خود را مالک شود.
  • جست‌وجوها از searchMode پیکربندی‌شده استفاده می‌کنند (پیش‌فرض: search؛ همچنین از vsearch و query پشتیبانی می‌کند). search فقط BM25 است، بنابراین OpenClaw در این حالت probeهای آمادگی برداری معنایی و نگه‌داری embedding را رد می‌کند. اگر یک حالت شکست بخورد، OpenClaw با qmd query دوباره تلاش می‌کند.
  • وقتی searchMode برابر query است، memory.qmd.rerank را روی false بگذارید تا مسیر پرس‌وجوی هیبرید QMD را بدون reranker استفاده کنید. OpenClaw در مسیر مستقیم CLI QMD مقدار --no-rerank و در ابزار پرس‌وجوی MCP متعلق به QMD مقدار rerank: false را پاس می‌دهد. این گزینه به QMD 2.1 یا جدیدتر نیاز دارد.
  • با نسخه‌های QMD که فیلترهای چندمجموعه‌ای را اعلام می‌کنند، OpenClaw مجموعه‌های هم‌منبع را در یک فراخوانی جست‌وجوی QMD گروه‌بندی می‌کند. نسخه‌های قدیمی‌تر QMD مسیر جایگزین سازگار برای هر مجموعه را حفظ می‌کنند.
  • اگر QMD کاملا شکست بخورد، OpenClaw به موتور SQLite داخلی برمی‌گردد. تلاش‌های تکراری در نوبت‌های chat پس از شکست باز کردن، کوتاه عقب‌نشینی می‌کنند تا نبود باینری یا خرابی وابستگی سایدکار باعث طوفان تلاش مجدد نشود؛ openclaw memory status و probeهای یک‌باره‌ی 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 برای هر مجموعه‌ی durable-memory جلوگیری می‌کند. مجموعه‌های رونوشت نشست در گروه منبع خودشان می‌مانند، بنابراین جست‌وجوهای ترکیبی 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"

پس از تغییر مدل embedding، embeddingها را دوباره اجرا کنید تا نمایه با فضای برداری جدید منطبق شود.

نمایه‌سازی مسیرهای اضافی

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 صادر نمی‌کند.

hitهای نشست همچنان با tools.sessions.visibility فیلتر می‌شوند. visibility پیش‌فرض tree نشست‌های نامرتبط همان agent را آشکار نمی‌کند. اگر یک نشست dispatchشده توسط Gateway باید از یک نشست DM جداگانه قابل بازیابی باشد، tools.sessions.visibility: "agent" را آگاهانه تنظیم کنید.

دامنه‌ی جست‌وجو

به‌طور پیش‌فرض، نتایج جست‌وجوی QMD در نشست‌های direct و channel نمایش داده می‌شوند (نه گروه‌ها). برای تغییر این رفتار memory.qmd.scope را پیکربندی کنید:

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

وقتی scope یک جست‌وجو را رد می‌کند، OpenClaw هشداری با channel و نوع chat مشتق‌شده ثبت می‌کند تا اشکال‌زدایی نتایج خالی آسان‌تر شود.

ارجاع‌ها

وقتی memory.citations برابر auto یا on باشد، قطعه‌های جست‌وجو یک پاورقی Source: <path#line> دارند. برای حذف پاورقی در حالی که مسیر همچنان به‌صورت داخلی به agent پاس داده می‌شود، memory.citations = "off" را تنظیم کنید.

چه زمانی استفاده شود

QMD را زمانی انتخاب کنید که نیاز دارید:

  • بازرتبه‌بندی برای نتایج باکیفیت‌تر.
  • جست‌وجوی مستندات پروژه یا یادداشت‌های بیرون از فضای کاری.
  • بازیابی گفت‌وگوهای نشست‌های گذشته.
  • جست‌وجوی کاملا محلی بدون کلیدهای API.

برای راه‌اندازی‌های ساده‌تر، موتور داخلی بدون وابستگی اضافی خوب کار می‌کند.

عیب‌یابی

QMD پیدا نشد؟ مطمئن شوید باینری در PATH مربوط به Gateway قرار دارد. اگر OpenClaw به‌صورت service اجرا می‌شود، یک symlink بسازید: sudo ln -s ~/.bun/bin/qmd /usr/local/bin/qmd.

اگر qmd --version در shell شما کار می‌کند اما OpenClaw همچنان spawn qmd ENOENT گزارش می‌دهد، فرایند Gateway احتمالا PATH متفاوتی نسبت به shell تعاملی شما دارد. باینری را صریحا pin کنید:

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

در محیطی که QMD نصب شده است از command -v 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 آن حالت را فقط واژگانی در نظر می‌گیرد، probeهای وضعیت برداری QMD یا نگه‌داری embedding را اجرا نمی‌کند، و بررسی‌های آمادگی معنایی را به تنظیمات vsearch یا query واگذار می‌کند.

جست‌وجو timeout می‌شود؟ memory.qmd.limits.timeoutMs را افزایش دهید (پیش‌فرض: 4000ms). برای سخت‌افزار کندتر آن را روی 120000 بگذارید.

نتایج خالی در chatهای گروهی؟ memory.qmd.scope را بررسی کنید -- پیش‌فرض فقط نشست‌های direct و channel را مجاز می‌کند.

جست‌وجوی حافظه‌ی ریشه ناگهان خیلی گسترده شد؟ Gateway را دوباره راه‌اندازی کنید یا منتظر همگام‌سازی راه‌اندازی بعدی بمانید. OpenClaw وقتی تداخل هم‌نام را تشخیص دهد، مجموعه‌های مدیریت‌شده‌ی کهنه را به الگوهای کانونی MEMORY.md و memory/ برمی‌گرداند.

repoهای موقت قابل مشاهده در فضای کاری باعث ENAMETOOLONG یا خرابی نمایه‌سازی می‌شوند؟ پیمایش QMD در حال حاضر به‌جای قواعد symlink داخلی OpenClaw، رفتار اسکنر زیرین QMD را دنبال می‌کند. checkoutهای موقت monorepo را تا زمانی که QMD پیمایش cycle-safe یا کنترل‌های exclusion صریح ارائه کند، زیر دایرکتوری‌های مخفی مانند .tmp/ یا بیرون از ریشه‌های QMD نمایه‌شده نگه دارید.

پیکربندی

برای سطح کامل پیکربندی (memory.qmd.*)، حالت‌های جست‌وجو، بازه‌های به‌روزرسانی، قواعد scope، و همه‌ی knobهای دیگر، مرجع پیکربندی حافظه را ببینید.

مرتبط

Was this useful?
On this page

On this page