Community translations by veiseule.ai — Help improve them on Crowdin
Skip to main content

หน่วยความจำ

OpenClaw memory is plain Markdown in the agent workspace. หน่วยความจำของOpenClawคือMarkdownธรรมดาในเวิร์กสเปซของเอเจนต์ไฟล์เหล่านี้คือแหล่งอ้างอิงความจริงเพียงหนึ่งเดียวโมเดลจะ“จำ”ได้เฉพาะสิ่งที่ถูกเขียนลงดิสก์เท่านั้น

เครื่องมือค้นหาหน่วยความจำถูกจัดเตรียมโดยปลั๊กอินหน่วยความจำที่เปิดใช้งานอยู่(ค่าเริ่มต้น: memory-core)ปิดใช้งานปลั๊กอินหน่วยความจำได้ด้วยplugins.slots.memory = "none". Disable memory plugins with plugins.slots.memory = "none".

ไฟล์หน่วยความจำ(Markdown)

เลย์เอาต์เวิร์กสเปซค่าเริ่มต้นใช้หน่วยความจำสองชั้น:

  • memory/YYYY-MM-DD.md
  • บันทึกรายวัน(เพิ่มต่อท้ายเท่านั้น)
  • อ่านของวันนี้+เมื่อวานตอนเริ่มเซสชัน
  • MEMORY.md(ไม่บังคับ)
  • หน่วยความจำระยะยาวที่คัดสรรแล้ว
  • โหลดเฉพาะในเซสชันหลักแบบส่วนตัวเท่านั้น(ไม่โหลดในบริบทกลุ่ม)

ไฟล์เหล่านี้อยู่ใต้เวิร์กสเปซ(agents.defaults.workspace, ค่าเริ่มต้น~/.openclaw/workspace)ดูAgent workspaceสำหรับโครงร่างทั้งหมด See Agent workspace for the full layout.

ควรเขียนหน่วยความจำเมื่อใด

  • การตัดสินใจ ความชอบ และข้อเท็จจริงที่คงทนให้เขียนลงMEMORY.md.
  • บันทึกประจำวันและบริบทที่กำลังดำเนินอยู่ให้เขียนลงmemory/YYYY-MM-DD.md.
  • หากมีคนพูดว่า“จำสิ่งนี้ไว้”ให้เขียนลงไป(อย่าเก็บไว้ในRAM)
  • This area is still evolving. ส่วนนี้ยังพัฒนาอยู่การเตือนโมเดลให้จัดเก็บหน่วยความจำจะช่วยได้มันจะรู้ว่าควรทำอย่างไร
  • หากต้องการให้สิ่งใดคงอยู่ขอให้บอตเขียนลงหน่วยความจำ

การล้างหน่วยความจำอัตโนมัติ(pre-compaction ping)

เมื่อเซสชันใกล้ถึงการคอมแพ็กชันอัตโนมัติOpenClawจะทริกเกอร์รอบการทำงานเงียบแบบเอเจนต์เพื่อเตือนโมเดลให้เขียนหน่วยความจำที่คงทนก่อนที่บริบทจะถูกคอมแพ็กต์พรอมป์ต์ค่าเริ่มต้นระบุชัดว่าโมเดล_อาจตอบกลับ_แต่โดยทั่วไปNO_REPLYคือคำตอบที่ถูกต้องเพื่อไม่ให้ผู้ใช้เห็นรอบนี้ The default prompts explicitly say the model may reply, but usually NO_REPLY is the correct response so the user never sees this turn.

การควบคุมทำผ่านagents.defaults.compaction.memoryFlush:

{
  agents: {
    defaults: {
      compaction: {
        reserveTokensFloor: 20000,
        memoryFlush: {
          enabled: true,
          softThresholdTokens: 4000,
          systemPrompt: "Session nearing compaction. Store durable memories now.",
          prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",
        },
      },
    },
  },
}

รายละเอียด:

  • เกณฑ์อ่อน: การล้างจะทริกเกอร์เมื่อการประมาณโทเคนของเซสชันข้ามcontextWindow - reserveTokensFloor - softThresholdTokens.
  • เงียบเป็นค่าเริ่มต้น: พรอมป์ต์มีNO_REPLYจึงไม่มีการส่งถึงผู้ใช้
  • สองพรอมป์ต์: พรอมป์ต์ผู้ใช้และพรอมป์ต์ระบบจะต่อท้ายการเตือน
  • หนึ่งการล้างต่อรอบคอมแพ็กชัน(ติดตามในsessions.json)
  • เวิร์กสเปซต้องเขียนได้: หากเซสชันรันแบบsandboxด้วยworkspaceAccess: "ro"หรือ"none"การล้างจะถูกข้าม

ดูวงจรคอมแพ็กชันทั้งหมดได้ที่ Session management + compaction.

การค้นหาหน่วยความจำแบบเวกเตอร์

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

ค่าเริ่มต้น:

  • เปิดใช้งานเป็นค่าเริ่มต้น
  • เฝ้าดูไฟล์หน่วยความจำเพื่อการเปลี่ยนแปลง(debounced)
  • Uses remote embeddings by default. ใช้การฝังแบบรีโมตเป็นค่าเริ่มต้นหากไม่ตั้งค่าmemorySearch.providerOpenClawจะเลือกอัตโนมัติ: 1. localหากมีการตั้งค่าmemorySearch.local.modelPathและไฟล์มีอยู่ 2. openaiหากสามารถแก้ไขคีย์OpenAIได้ 3. geminiหากสามารถแก้ไขคีย์Geminiได้ 4. voyageหากสามารถแก้ไขคีย์Voyageได้ 5. มิฉะนั้นการค้นหาหน่วยความจำจะยังคงปิดจนกว่าจะตั้งค่า
  • โหมดโลคัลใช้node-llama-cppและอาจต้องการpnpm approve-builds.
  • ใช้sqlite-vec(เมื่อมี)เพื่อเร่งการค้นหาเวกเตอร์ภายในSQLite

Remote embeddings require an API key for the embedding provider. OpenClaw resolves keys from auth profiles, models.providers.*.apiKey, or environment variables. Codex OAuth only covers chat/completions and does not satisfy embeddings for memory search. For Gemini, use GEMINI_API_KEY or models.providers.google.apiKey. For Voyage, use VOYAGE_API_KEY or models.providers.voyage.apiKey. When using a custom OpenAI-compatible endpoint, set memorySearch.remote.apiKey (and optional memorySearch.remote.headers).

แบ็กเอนด์QMD(ทดลอง)

ตั้งค่าmemory.backend = "qmd"เพื่อสลับตัวทำดัชนีSQLiteในตัวเป็น QMD:ไซด์คาร์ค้นหาแบบโลคัลเฟิร์สต์ที่ผสานBM25+เวกเตอร์+การจัดอันดับซ้ำMarkdownยังคงเป็นแหล่งอ้างอิงความจริงOpenClawจะเรียกใช้QMDเพื่อการดึงข้อมูลประเด็นสำคัญ: Markdown stays the source of truth; OpenClaw shells out to QMD for retrieval. Key points:

ข้อกำหนดก่อนเริ่มต้น

  • Disabled by default. ปิดใช้งานเป็นค่าเริ่มต้นเลือกใช้ต่อคอนฟิก(memory.backend = "qmd")
  • ติดตั้งQMD CLIแยกต่างหาก(bun install -g https://github.com/tobi/qmdหรือดาวน์โหลดรีลีส)และตรวจสอบว่าไบนารีqmdอยู่ในPATHของเกตเวย์
  • QMDต้องการบิลด์SQLiteที่อนุญาตส่วนขยาย(brew install sqliteบนmacOS)
  • QMDรันแบบโลคัลทั้งหมดผ่านBun+node-llama-cppและดาวน์โหลดโมเดลGGUFจากHuggingFaceอัตโนมัติเมื่อใช้งานครั้งแรก(ไม่ต้องมีดีมอนOllamaแยก)
  • เกตเวย์รันQMDในXDG homeแบบแยกส่วนภายใต้~/.openclaw/agents/<agentId>/qmd/โดยตั้งค่าXDG_CONFIG_HOMEและXDG_CACHE_HOME.
  • รองรับระบบปฏิบัติการ: macOSและLinuxใช้งานได้ทันทีเมื่อมีBun+SQLiteติดตั้งWindowsแนะนำผ่านWSL2 Windows is best supported via WSL2.

วิธีการรันไซด์คาร์

  • เกตเวย์เขียนQMD homeแบบแยกส่วนภายใต้~/.openclaw/agents/<agentId>/qmd/(คอนฟิก+แคช+sqlite DB)
  • คอลเลกชันถูกสร้างผ่านqmd collection addจากmemory.qmd.paths(รวมไฟล์หน่วยความจำเวิร์กสเปซค่าเริ่มต้น)จากนั้นqmd update+qmd embedจะรันตอนบูตและตามช่วงเวลาที่กำหนดได้(memory.qmd.update.interval, ค่าเริ่มต้น5 นาที)
  • การรีเฟรชตอนบูตจะรันเบื้องหลังเป็นค่าเริ่มต้นเพื่อไม่ให้การเริ่มแชตถูกบล็อกตั้งค่าmemory.qmd.update.waitForBootSync = trueเพื่อคงพฤติกรรมบล็อกเดิม
  • Searches run via qmd query --json. การค้นหารันผ่านqmd query --jsonหากQMDล้มเหลวหรือไม่มีไบนารีOpenClawจะถอยกลับไปใช้ตัวจัดการSQLiteในตัวโดยอัตโนมัติเพื่อให้เครื่องมือหน่วยความจำยังทำงาน
  • OpenClawยังไม่เปิดเผยการปรับbatch-sizeของการฝังQMDวันนี้พฤติกรรมแบตช์ถูกควบคุมโดยQMDเอง
  • การค้นหาครั้งแรกอาจช้า:QMDอาจดาวน์โหลดโมเดลGGUFแบบโลคัล(การจัดอันดับซ้ำ/การขยายคำค้น)ในการรันqmd queryครั้งแรก
  • OpenClawตั้งค่าXDG_CONFIG_HOME/XDG_CACHE_HOMEอัตโนมัติเมื่อรันQMD
  • หากต้องการพรีดาวน์โหลดโมเดลด้วยตนเอง(และอุ่นดัชนีเดียวกับที่OpenClawใช้)ให้รันคิวรีครั้งเดียวด้วยไดเรกทอรีXDGของเอเจนต์

    OpenClaw’s QMD state lives under your state dir (defaults to ~/.openclaw). สถานะQMDของOpenClawอยู่ใต้ไดเรกทอรีสถานะของคุณ(ค่าเริ่มต้น~/.openclaw)คุณสามารถชี้qmdไปยังดัชนีเดียวกันได้โดยเอ็กซ์พอร์ตตัวแปรXDGเดียวกับที่OpenClawใช้:

    ```bash

    Pick the same state dir OpenClaw uses

    STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" if [ -d "$HOME/.moltbot" ] && [ ! -d "$HOME/.openclaw" ] \ && [ -z "${OPENCLAW_STATE_DIR:-}" ]; then STATE_DIR="$HOME/.moltbot" fi

    export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config" export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"

    (Optional) force an index refresh + embeddings

    qmd update qmd embed

    Warm up / trigger first-time model downloads

    qmd query "test" -c memory-root --json >/dev/null 2>&1 ```

พื้นผิวคอนฟิก(memory.qmd.*)

  • command(ค่าเริ่มต้นqmd):แทนที่พาธไฟล์ปฏิบัติการ
  • includeDefaultMemory(ค่าเริ่มต้นtrue):ทำดัชนีอัตโนมัติMEMORY.md+memory/**/*.md
  • paths[]:เพิ่มไดเรกทอรี/ไฟล์เพิ่มเติม(path, ไม่บังคับpattern, ไม่บังคับ stable name)
  • sessions:เลือกใช้การทำดัชนีJSONLของเซสชัน(enabled, retentionDays, exportDir)
  • update:ควบคุมรอบการรีเฟรชและการรันบำรุงรักษา: (interval, debounceMs, onBoot, waitForBootSync, embedInterval, commandTimeoutMs, updateTimeoutMs, embedTimeoutMs)
  • limits:จำกัดเพย์โหลดการเรียกคืน(maxResults, maxSnippetChars, maxInjectedChars, timeoutMs)
  • scope: same schema as session.sendPolicy. scope:สคีมาเดียวกับsession.sendPolicy ค่าเริ่มต้นคือDMเท่านั้น(denyทั้งหมด,allowแชตตรง)ผ่อนคลายเพื่อแสดงผลQMDในกลุ่ม/ช่องทาง
  • เมื่อ scope ปฏิเสธการค้นหา OpenClaw จะบันทึกคำเตือนพร้อมค่า channel/chatType ที่คำนวณได้ เพื่อให้การดีบักผลลัพธ์ว่างทำได้ง่ายขึ้น
  • สแนิปเพ็ตที่มาจากนอกเวิร์กสเปซจะแสดงเป็นqmd/<collection>/<relative-path>ในผลลัพธ์memory_search;memory_getเข้าใจพรีฟิกซ์นั้นและอ่านจากรูทคอลเลกชันQMDที่ตั้งค่าไว้
  • เมื่อmemory.qmd.sessions.enabled = true,OpenClawจะส่งออกทรานสคริปต์เซสชันที่ผ่านการทำความสะอาด(รอบผู้ใช้/ผู้ช่วย)ไปยังคอลเลกชันQMDเฉพาะภายใต้~/.openclaw/agents/<id>/qmd/sessions/,เพื่อให้memory_searchสามารถเรียกคืนบทสนทนาล่าสุดได้โดยไม่แตะดัชนีSQLiteในตัว
  • สแนิปเพ็ตmemory_searchจะมีฟุตเตอร์Source: <path#line>เมื่อmemory.citationsเป็นauto/on;ตั้งค่าmemory.citations = "off"เพื่อเก็บเมทาดาทาพาธไว้ภายใน(เอเจนต์ยังคงได้รับพาธสำหรับmemory_getแต่ข้อความสแนิปเพ็ตจะละฟุตเตอร์และพรอมป์ต์ระบบจะเตือนเอเจนต์ไม่ให้อ้างอิง)

ตัวอย่าง

memory: {
  backend: "qmd",
  citations: "auto",
  qmd: {
    includeDefaultMemory: true,
    update: { interval: "5m", debounceMs: 15000 },
    limits: { maxResults: 6, timeoutMs: 4000 },
    scope: {
      default: "deny",
      rules: [{ action: "allow", match: { chatType: "direct" } }]
    },
    paths: [
      { name: "docs", path: "~/notes", pattern: "**/*.md" }
    ]
  }
}

การอ้างอิงและการถอยกลับ

  • memory.citationsมีผลไม่ว่าจะแบ็กเอนด์ใด(auto/on/off)
  • When qmd runs, we tag status().backend = "qmd" so diagnostics show which engine served the results. เมื่อqmdรันเราจะติดแท็กstatus().backend = "qmd"เพื่อให้ไดแอกนอสติกแสดงว่าเอนจินใดให้ผลลัพธ์หากซับโปรเซสQMDออกหรือเอาต์พุตJSONแยกวิเคราะห์ไม่ได้ตัวจัดการการค้นหาจะบันทึกคำเตือนและคืนผู้ให้บริการในตัว(การฝังMarkdownที่มีอยู่)จนกว่าQMDจะกู้คืน

พาธหน่วยความจำเพิ่มเติม

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

agents: {
  defaults: {
    memorySearch: {
      extraPaths: ["../team-docs", "/srv/shared-notes/overview.md"]
    }
  }
}

หมายเหตุ:

  • พาธอาจเป็นแบบสัมบูรณ์หรือสัมพันธ์กับเวิร์กสเปซ
  • ไดเรกทอรีจะถูกสแกนแบบรีเคอร์ซีฟสำหรับไฟล์.md
  • ทำดัชนีเฉพาะไฟล์Markdownเท่านั้น
  • ไม่สนใจซิมลิงก์(ไฟล์หรือไดเรกทอรี)

การฝังGemini(เนทีฟ)

ตั้งค่าผู้ให้บริการเป็นgeminiเพื่อใช้Gemini embeddings APIโดยตรง:

agents: {
  defaults: {
    memorySearch: {
      provider: "gemini",
      model: "gemini-embedding-001",
      remote: {
        apiKey: "YOUR_GEMINI_API_KEY"
      }
    }
  }
}

หมายเหตุ:

  • remote.baseUrlไม่บังคับ(ค่าเริ่มต้นคือฐานURLของGemini API)
  • remote.headersช่วยให้เพิ่มเฮดเดอร์เพิ่มเติมได้หากจำเป็น
  • โมเดลค่าเริ่มต้น:gemini-embedding-001

หากต้องการใช้เอนด์พอยต์ที่เข้ากันได้กับOpenAIแบบกำหนดเอง(OpenRouter, vLLMหรือพร็อกซี) สามารถใช้คอนฟิกremoteกับผู้ให้บริการOpenAIได้:

agents: {
  defaults: {
    memorySearch: {
      provider: "openai",
      model: "text-embedding-3-small",
      remote: {
        baseUrl: "https://api.example.com/v1/",
        apiKey: "YOUR_OPENAI_COMPAT_API_KEY",
        headers: { "X-Custom-Header": "value" }
      }
    }
  }
}

หากไม่ต้องการตั้งค่าคีย์APIให้ใช้memorySearch.provider = "local"หรือกำหนดmemorySearch.fallback = "none".

การถอยกลับ:

  • memorySearch.fallbackสามารถเป็นopenai,gemini,localหรือnone.
  • ผู้ให้บริการถอยกลับจะถูกใช้เฉพาะเมื่อผู้ให้บริการการฝังหลักล้มเหลว

การทำดัชนีแบบแบตช์(OpenAI+Gemini):

  • Enabled by default for OpenAI and Gemini embeddings. เปิดใช้งานเป็นค่าเริ่มต้นสำหรับการฝังOpenAIและGeminiตั้งค่าagents.defaults.memorySearch.remote.batch.enabled = falseเพื่อปิด
  • พฤติกรรมค่าเริ่มต้นจะรอให้แบตช์เสร็จสิ้นปรับremote.batch.wait,remote.batch.pollIntervalMsและremote.batch.timeoutMinutesหากจำเป็น
  • ตั้งค่าremote.batch.concurrencyเพื่อควบคุมจำนวนงานแบตช์ที่ส่งพร้อมกัน(ค่าเริ่มต้น:2)
  • โหมดแบตช์ใช้เมื่อmemorySearch.provider = "openai"หรือ"gemini"และใช้คีย์APIที่สอดคล้องกัน
  • งานแบตช์Geminiใช้เอนด์พอยต์แบตช์การฝังแบบอะซิงก์และต้องมีความพร้อมของGemini Batch API

เหตุใดแบตช์OpenAIจึงเร็วและถูก:

  • สำหรับการเติมข้อมูลย้อนกลับขนาดใหญ่OpenAIมักเป็นตัวเลือกที่เร็วที่สุดที่เรารองรับเพราะสามารถส่งคำขอการฝังจำนวนมากในงานแบตช์เดียวและปล่อยให้OpenAIประมวลผลแบบอะซิงก์
  • OpenAIมีราคาลดสำหรับงานBatch APIดังนั้นการทำดัชนีขนาดใหญ่จึงมักถูกกว่าส่งคำขอเดียวกันแบบซิงก์
  • ดูเอกสารและราคาOpenAI Batch API:
  • https://platform.openai.com/docs/api-reference/batch
  • https://platform.openai.com/pricing

ตัวอย่างคอนฟิก:

agents: {
  defaults: {
    memorySearch: {
      provider: "openai",
      model: "text-embedding-3-small",
      fallback: "openai",
      remote: {
        batch: { enabled: true, concurrency: 2 }
      },
      sync: { watch: true }
    }
  }
}

เครื่องมือ:

  • memory_search — คืนสแนิปเพ็ตพร้อมไฟล์+ช่วงบรรทัด
  • memory_get — อ่านเนื้อหาไฟล์หน่วยความจำตามพาธ

โหมดโลคัล:

  • ตั้งค่าagents.defaults.memorySearch.provider = "local"
  • ระบุagents.defaults.memorySearch.local.modelPath(GGUFหรือhf:URI)
  • ไม่บังคับ:ตั้งค่าagents.defaults.memorySearch.fallback = "none"เพื่อหลีกเลี่ยงการถอยกลับไปรีโมต

เครื่องมือหน่วยความจำทำงานอย่างไร

  • memory_search semantically searches Markdown chunks (~400 token target, 80-token overlap) from MEMORY.md + memory/**/*.md. It returns snippet text (capped ~700 chars), file path, line range, score, provider/model, and whether we fell back from local → remote embeddings. No full file payload is returned.
  • memory_getอ่านไฟล์Markdownหน่วยความจำเฉพาะ(สัมพันธ์กับเวิร์กสเปซ)เลือกได้จากบรรทัดเริ่มต้นและจำนวนบรรทัดNพาธนอกMEMORY.md/memory/จะถูกปฏิเสธ Paths outside MEMORY.md / memory/ are rejected.
  • เครื่องมือทั้งสองเปิดใช้งานเฉพาะเมื่อmemorySearch.enabledประเมินเป็นจริงสำหรับเอเจนต์

สิ่งที่ถูกทำดัชนี(และเมื่อใด)

  • ประเภทไฟล์:เฉพาะMarkdown(MEMORY.md,memory/**/*.md)
  • ที่เก็บดัชนี:SQLiteต่อเอเจนต์ที่~/.openclaw/memory/<agentId>.sqlite(ตั้งค่าได้ผ่านagents.defaults.memorySearch.store.path,รองรับโทเคน{agentId})
  • Freshness: watcher on MEMORY.md + memory/ marks the index dirty (debounce 1.5s). Sync is scheduled on session start, on search, or on an interval and runs asynchronously. Session transcripts use delta thresholds to trigger background sync.
  • ทริกเกอร์การทำดัชนีใหม่:ดัชนีเก็บลายนิ้วมือของผู้ให้บริการ/โมเดลการฝัง+เอนด์พอยต์+พารามิเตอร์การตัดชิ้นหากสิ่งใดเปลี่ยนOpenClawจะรีเซ็ตและทำดัชนีใหม่ทั้งหมดโดยอัตโนมัติ If any of those change, OpenClaw automatically resets and reindexes the entire store.

การค้นหาไฮบริด(BM25+เวกเตอร์)

เมื่อเปิดใช้งานOpenClawจะผสาน:

  • ความคล้ายคลึงของเวกเตอร์(จับคู่เชิงความหมายถ้อยคำอาจต่างกัน)
  • ความเกี่ยวข้องของคีย์เวิร์ดBM25(โทเคนตรงเช่นIDตัวแปรสภาพแวดล้อมสัญลักษณ์โค้ด)

หากการค้นหาแบบข้อความเต็มไม่พร้อมใช้งานบนแพลตฟอร์มของคุณOpenClawจะถอยกลับเป็นการค้นหาเวกเตอร์อย่างเดียว

ทำไมต้องไฮบริด?

การค้นหาเวกเตอร์เก่งด้าน“ความหมายเดียวกัน”:

  • “Mac Studio gateway host”เทียบกับ“เครื่องที่รันเกตเวย์”
  • “debounce file updates”เทียบกับ“หลีกเลี่ยงการทำดัชนีทุกครั้งที่เขียน”

แต่จะอ่อนกับโทเคนที่ตรงและมีสัญญาณสูง:

  • ID(a828e60,b3b9895a…)
  • สัญลักษณ์โค้ด(memorySearch.query.hybrid)
  • สตริงข้อผิดพลาด(“sqlite-vec unavailable”)

BM25 (full-text) is the opposite: strong at exact tokens, weaker at paraphrases. BM25(ข้อความเต็ม)ตรงข้าม:เก่งโทเคนตรงอ่อนกับการถอดความ การค้นหาไฮบริดคือจุดกึ่งกลางเชิงปฏิบัติ: ใช้สัญญาณการดึงข้อมูลทั้งสองเพื่อให้ได้ผลลัพธ์ที่ดีทั้งคิวรีภาษาธรรมชาติและคิวรีแบบ“เข็มในกองฟาง”

วิธีรวมผลลัพธ์(ดีไซน์ปัจจุบัน)

Implementation sketch:

  1. ดึงพูลผู้สมัครจากทั้งสองฝั่ง:
  • เวกเตอร์:อันดับบนmaxResults * candidateMultiplierตามcosine similarity
  • BM25:อันดับบนmaxResults * candidateMultiplierตามอันดับFTS5 BM25(ยิ่งต่ำยิ่งดี)
  1. แปลงอันดับBM25เป็นคะแนนประมาณ0..1:
  • textScore = 1 / (1 + max(0, bm25Rank))
  1. รวมผู้สมัครตามchunk idและคำนวณคะแนนถ่วงน้ำหนัก:
  • finalScore = vectorWeight * vectorScore + textWeight * textScore

หมายเหตุ:

  • vectorWeight+textWeightถูกทำให้เป็น1.0ในการแก้ไขคอนฟิกดังนั้นน้ำหนักจึงทำงานเหมือนเปอร์เซ็นต์
  • หากการฝังไม่พร้อมใช้งาน(หรือผู้ให้บริการคืนเวกเตอร์ศูนย์)เรายังคงรันBM25และคืนผลลัพธ์คีย์เวิร์ด
  • หากไม่สามารถสร้างFTS5ได้เราจะคงการค้นหาเวกเตอร์อย่างเดียว(ไม่ล้มเหลวแบบฮาร์ด)

This isn’t “IR-theory perfect”, but it’s simple, fast, and tends to improve recall/precision on real notes. นี่ไม่ใช่“สมบูรณ์แบบตามทฤษฎีIR”แต่เรียบง่ายเร็วและมักปรับปรุงrecall/precisionกับโน้ตจริง หากต้องการซับซ้อนขึ้นในอนาคตขั้นถัดไปทั่วไปคือReciprocal Rank Fusion(RRF)หรือการทำ normalizationของคะแนน (min/maxหรือz-score)ก่อนผสม

คอนฟิก:

agents: {
  defaults: {
    memorySearch: {
      query: {
        hybrid: {
          enabled: true,
          vectorWeight: 0.7,
          textWeight: 0.3,
          candidateMultiplier: 4
        }
      }
    }
  }
}

แคชการฝัง

OpenClawสามารถแคชการฝังของชิ้นส่วนในSQLiteเพื่อให้การทำดัชนีใหม่และการอัปเดตบ่อย(โดยเฉพาะทรานสคริปต์เซสชัน)ไม่ต้องฝังข้อความที่ไม่เปลี่ยนซ้ำ

คอนฟิก:

agents: {
  defaults: {
    memorySearch: {
      cache: {
        enabled: true,
        maxEntries: 50000
      }
    }
  }
}

การค้นหาหน่วยความจำเซสชัน(ทดลอง)

คุณสามารถเลือกทำดัชนีทรานสคริปต์เซสชันและแสดงผ่านmemory_searchได้ ฟีเจอร์นี้ถูกกั้นด้วยแฟล็กทดลอง This is gated behind an experimental flag.

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

หมายเหตุ:

  • การทำดัชนีเซสชันเป็นแบบเลือกใช้(ปิดเป็นค่าเริ่มต้น)
  • การอัปเดตเซสชันถูกdebounceและทำดัชนีแบบอะซิงก์เมื่อข้ามเกณฑ์เดลต้า(พยายามอย่างดีที่สุด)
  • memory_searchไม่บล็อกการทำดัชนีผลลัพธ์อาจล้าหลังเล็กน้อยจนกว่าการซิงก์เบื้องหลังจะเสร็จ
  • ผลลัพธ์ยังคงเป็นสแนิปเพ็ตเท่านั้น;memory_getยังคงจำกัดที่ไฟล์หน่วยความจำ
  • การทำดัชนีเซสชันแยกต่อเอเจนต์(ทำดัชนีเฉพาะบันทึกเซสชันของเอเจนต์นั้น)
  • Session logs live on disk (~/.openclaw/agents/<agentId>/sessions/*.jsonl). บันทึกเซสชันอยู่บนดิสก์(~/.openclaw/agents/<agentId>/sessions/*.jsonl)กระบวนการ/ผู้ใช้ใดที่เข้าถึงไฟล์ระบบได้สามารถอ่านได้ดังนั้นให้ถือว่าการเข้าถึงดิสก์คือขอบเขตความเชื่อถือเพื่อการแยกที่เข้มงวดขึ้นให้รันเอเจนต์ภายใต้ผู้ใช้OSหรือโฮสต์แยกกัน For stricter isolation, run agents under separate OS users or hosts.

เกณฑ์เดลต้า(ค่าเริ่มต้นแสดง):

agents: {
  defaults: {
    memorySearch: {
      sync: {
        sessions: {
          deltaBytes: 100000,   // ~100 KB
          deltaMessages: 50     // JSONL lines
        }
      }
    }
  }
}

การเร่งเวกเตอร์SQLite(sqlite-vec)

เมื่อมีส่วนขยายsqlite-vecOpenClawจะเก็บการฝังในตารางเสมือนSQLite(vec0)และทำคิวรีระยะเวกเตอร์ในฐานข้อมูลช่วยให้การค้นหาเร็วโดยไม่ต้องโหลดการฝังทั้งหมดเข้าJS This keeps search fast without loading every embedding into JS.

การกำหนดค่า(ไม่บังคับ):

agents: {
  defaults: {
    memorySearch: {
      store: {
        vector: {
          enabled: true,
          extensionPath: "/path/to/sqlite-vec"
        }
      }
    }
  }
}

หมายเหตุ:

  • enabledค่าเริ่มต้นเป็นtrue;เมื่อปิดการค้นหาจะถอยกลับไปใช้cosine similarityในโปรเซสเหนือการฝังที่เก็บไว้
  • หากส่วนขยายsqlite-vecหายไปหรือโหลดไม่สำเร็จOpenClawจะบันทึกข้อผิดพลาดและทำงานต่อด้วยทางเลือกJS(ไม่มีตารางเวกเตอร์)
  • extensionPathแทนที่พาธsqlite-vecที่มาพร้อม(มีประโยชน์สำหรับบิลด์กำหนดเองหรือที่ติดตั้งไม่มาตรฐาน)

การดาวน์โหลดการฝังโลคัลอัตโนมัติ

  • โมเดลการฝังโลคัลค่าเริ่มต้น:hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf(~0.6GB)
  • เมื่อmemorySearch.provider = "local",node-llama-cppแก้ไขเป็นmodelPath;หากไม่มีGGUFจะดาวน์โหลดอัตโนมัติไปยังแคช(หรือlocal.modelCacheDirหากตั้งค่า)จากนั้นโหลดการดาวน์โหลดจะต่อเมื่อพยายามใหม่ Downloads resume on retry.
  • ข้อกำหนดบิลด์เนทีฟ:รันpnpm approve-builds,เลือกnode-llama-cpp,จากนั้นpnpm rebuild node-llama-cpp
  • การถอยกลับ:หากการตั้งค่าโลคัลล้มเหลวและmemorySearch.fallback = "openai"เราจะสลับไปใช้การฝังแบบรีโมตโดยอัตโนมัติ(openai/text-embedding-3-smallเว้นแต่มีการแทนที่)และบันทึกเหตุผล

ตัวอย่างเอนด์พอยต์ที่เข้ากันได้กับOpenAIแบบกำหนดเอง

agents: {
  defaults: {
    memorySearch: {
      provider: "openai",
      model: "text-embedding-3-small",
      remote: {
        baseUrl: "https://api.example.com/v1/",
        apiKey: "YOUR_REMOTE_API_KEY",
        headers: {
          "X-Organization": "org-id",
          "X-Project": "project-id"
        }
      }
    }
  }
}

หมายเหตุ:

  • remote.*มีลำดับความสำคัญเหนือmodels.providers.openai.*
  • remote.headersผสานกับเฮดเดอร์OpenAI;ฝั่งรีโมตชนะเมื่อคีย์ชนกันละremote.headersออกเพื่อใช้ค่าเริ่มต้นของOpenAI Omit remote.headers to use the OpenAI defaults.