内存
OpenClaw 内存?代理工作区中的纯 Markdown*。文件是真相来源;模型只”记住”写入磁盘的内容?
内存搜索工具由活动的内存插件提供(默认:memory-core)。使?plugins.slots.memory = "none" 禁用内存插件?
内存文件(Markdown?
默认工作区布局使用两层内存?
memory/YYYY-MM-DD.md- 每日日志(仅追加)?
- 会话开始时读取今天和昨天?
MEMORY.md(可选)- 精选的长期内存?
- 仅在主、私人会话中加载(绝不在群组上下文中)?
这些文件位于工作区下(agents.defaults.workspace,默?~/.openclaw/workspace)。完整布局见代理工作区?
内存工具
OpenClaw 为这?Markdown 文件暴露两个面向代理的工具:
memory_search?对索引片段的语义召回?memory_get?读取特定 Markdown 文件/行范围的定向读取?
memory_get 现在**在文件不存在时优雅降?*(例如,今天的每日日志在首次写入之前)。内置管理器?QMD 后端都返?{ text: "", path } 而不是抛?ENOENT,因此代理可以处?尚无记录”并继续其工作流,而无需将工具调用包装在 try/catch 逻辑中?
何时写入内存
- 决策、偏好和持久事实写入
MEMORY.md? - 日常笔记和运行上下文写入
memory/YYYY-MM-DD.md? - 如果有人?记住这个”,写下来(不要保存在 RAM 中)?
- 这个领域仍在演变。提醒模型存储记忆会有帮助;它会知道怎么做?
- 如果你想让某些东西记住,**让机器人?*到内存中?
自动内存刷新(压缩前 ping?
当会?接近自动压缩**时,OpenClaw 触发一?静默的、代理驱动的轮次,提醒模型在上下文被压缩之前写入持久内存。默认提示明确说模型可以回复,但通常 NO_REPLY 是正确的响应,这样用户永远不会看到这个轮次?
这由 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.",
},
},
},
},
}
详情?
- **软阈?*:当会话 token 估计超过
contextWindow - reserveTokensFloor - softThresholdTokens时触发刷新? - 默认静默:提示包?
NO_REPLY以便不交付任何内容? - 两个提示:用户提示加上系统提示附加提醒?
- **每次压缩周期一次刷?*(在
sessions.json中跟踪)? - **工作区必须可?*:如果会话在沙箱中运行且
workspaceAccess: "ro"?"none",则跳过刷新?
有关完整压缩生命周期,参见会话管理 + 压缩?
向量内存搜索
OpenClaw 可以?MEMORY.md ?memory/*.md 上构建一个小向量索引,以便语义查询可以找到相关笔记,即使措辞不同?
默认值:
- 默认启用?
- 监视内存文件更改(防抖)?
- ?
agents.defaults.memorySearch下配置内存搜索(不是顶级memorySearch)? - 默认使用远程嵌入。如果未设置
memorySearch.provider,OpenClaw 自动选择?local如果配置?memorySearch.local.modelPath且文件存在?openai如果可以解析 OpenAI 密钥?gemini如果可以解析 Gemini 密钥?voyage如果可以解析 Voyage 密钥?mistral如果可以解析 Mistral 密钥?- 否则内存搜索保持禁用直到配置?
- 本地模式使用 node-llama-cpp,可能需?
pnpm approve-builds? - 使用 sqlite-vec(如果有)加?SQLite 内的向量搜索?
远程嵌入**需?*嵌入 provider ?API 密钥。OpenClaw 从认证配置文件、models.providers.*.apiKey 或环境变量解析密钥。Codex OAuth 仅涵盖聊?completions?*不满?*内存搜索的嵌入。对?Gemini,使?GEMINI_API_KEY ?models.providers.google.apiKey。对?Voyage,使?VOYAGE_API_KEY ?models.providers.voyage.apiKey。对?Mistral,使?MISTRAL_API_KEY ?models.providers.mistral.apiKey。使用自定义 OpenAI 兼容端点时,设置 memorySearch.remote.apiKey(和可选的 memorySearch.remote.headers)?
QMD 后端(实验性)
设置 memory.backend = "qmd" 将内?SQLite 索引器替换为 QMD:一个本地优先的搜索辅助工具,结?BM25 + 向量 + 重新排序。Markdown 保持为真相来源;OpenClaw 调用 QMD 进行检索。关键点?
前置条件
- 默认禁用。按配置选择加入(
memory.backend = "qmd")? - 单独安装 QMD CLI(
bun install -g https://github.com/tobi/qmd或获取发布版)并确保qmd二进制文件在 gateway ?PATH上? - QMD 需要允许扩展的 SQLite 构建(macOS ?
brew install sqlite)? - QMD 通过 Bun +
node-llama-cpp完全本地运行,并在首次使用时?HuggingFace 自动下载 GGUF 模型(不需要单独的 Ollama 守护进程)? - gateway 通过设置
XDG_CONFIG_HOME?XDG_CACHE_HOME在自包含?XDG 主目录下运行 QMD,位?~/.openclaw/agents/<agentId>/qmd/? - OS 支持:一旦安?Bun + SQLite,macOS ?Linux 开箱即用。Windows 最好通过 WSL2 支持?
辅助工具如何运行
- gateway ?
~/.openclaw/agents/<agentId>/qmd/(配?+ 缓存 + sqlite DB)下编写自包含的 QMD 主目录? - 集合通过
qmd collection add?memory.qmd.paths(加上默认工作区内存文件)创建,然后qmd update+qmd embed在启动时和可配置间隔(memory.qmd.update.interval,默?5 分钟)运行? - gateway 现在在启动时初始?QMD 管理器,因此定期更新计时器甚至在第一?
memory_search调用之前就已启动? - 启动刷新默认在后台运行,因此聊天启动不会被阻塞;设置
memory.qmd.update.waitForBootSync = true保持之前的阻塞行为? - 搜索通过
memory.qmd.searchMode运行(默?qmd search --json;也支持vsearch?query)。如果所选模式在你的 QMD 构建上拒绝标志,OpenClaw 使用qmd query重试。如?QMD 失败或二进制文件丢失,OpenClaw 自动回退到内?SQLite 管理器,因此内存工具保持工作? - OpenClaw 今天不公开 QMD 嵌入批量大小调优;批量行为由 QMD 自己控制?
- 首次搜索可能很慢:QMD 可能在第一?
qmd query运行时下载本?GGUF 模型(重新排序器/查询扩展)?-
OpenClaw 在运?QMD 时自动设?
XDG_CONFIG_HOME/XDG_CACHE_HOME? -
如果你想手动预下载模型(并预?OpenClaw 使用的相同索引),使用代理的 XDG 目录运行一次性查询?
OpenClaw ?QMD 状态位于你?状态目?(默?
~/.openclaw)。你可以通过导出?OpenClaw 使用的相?XDG 变量来指?qmd相同的索引:# 选择?OpenClaw 使用的相同状态目? STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config" export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache" # (可选)强制索引刷新 + 嵌入 qmd update qmd embed # 预热 / 触发首次模型下载 qmd query "test" -c memory-root --json >/dev/null 2>&1
-
*配置表面(memory.qmd.*?
command(默?qmd):覆盖可执行文件路径?searchMode(默?search):选择哪个 QMD 命令支持memory_search(search、vsearch、query)?includeDefaultMemory(默?true):自动索引MEMORY.md+memory/**/*.md?paths[]:添加额外目?文件(path、可?pattern、可选稳?name)?sessions:选择加入会话 JSONL 索引(enabled、retentionDays、exportDir)?update:控制刷新节奏和维护执行(interval、debounceMs、onBoot、waitForBootSync、embedInterval、commandTimeoutMs、updateTimeoutMs、embedTimeoutMs)?limits:限制召回负载(maxResults、maxSnippetChars、maxInjectedChars、timeoutMs)?scope:与session.sendPolicy相同的模式。默认仅 DM(deny所有,直接聊天allow);放宽它以在群?频道中显?QMD 命中?match.keyPrefix匹配**规范?*的会话键(小写,剥离任何前导agent:<id>:)。例如:discord:channel:?match.rawKeyPrefix匹配原始会话键(小写),包括agent:<id>:。例如:agent:main:discord:?- 遗留:
match.keyPrefix: "agent:..."仍然被视为原始键前缀,但为清晰起见首?rawKeyPrefix?
- ?
scope拒绝搜索时,OpenClaw 记录带有派生channel/chatType的警告,以便更容易调试空结果? - 来自工作区外的片段在
memory_search结果中显示为qmd/<collection>/<relative-path>;memory_get理解该前缀并从配置?QMD 集合根读取? - ?
memory.qmd.sessions.enabled = true时,OpenClaw 导出清理过的会话记录(用?助手轮次)到~/.openclaw/agents/<id>/qmd/sessions/下的专用 QMD 集合,以?memory_search可以召回最近的对话而不触及内置 SQLite 索引? - ?
memory.citations?auto/on时,memory_search片段现在包含Source: <path#line>页脚;设?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" } },
// Normalized session-key prefix (strips `agent:<id>:`).
{ action: "deny", match: { keyPrefix: "discord:channel:" } },
// Raw session-key prefix (includes `agent:<id>:`).
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
]
},
paths: [
{ name: "docs", path: "~/notes", pattern: "**/*.md" }
]
}
}
引用和回退
memory.citations无论后端如何都适用(auto/on/off)?- ?QMD 运行时,我们标记
status().backend = "qmd",以便诊断显示哪个引擎服务了结果。如?QMD 子进程退出或无法解析 JSON 输出,搜索管理器记录警告并返回内?provider(现?Markdown 嵌入)直?QMD 恢复?
额外内存路径
如果你想索引默认工作区布局之外?Markdown 文件,添加显式路径:
agents: {
defaults: {
memorySearch: {
extraPaths: ["../team-docs", "/srv/shared-notes/overview.md"]
}
}
}
注意?
- 路径可以是绝对路径或相对于工作区?
- 目录递归扫描
.md文件? - 仅索?Markdown 文件?
- 符号链接被忽略(文件或目录)?
Gemini 嵌入(原生)
设置 provider ?gemini 以直接使?Gemini 嵌入 API?
agents: {
defaults: {
memorySearch: {
provider: "gemini",
model: "gemini-embedding-001",
remote: {
apiKey: "YOUR_GEMINI_API_KEY"
}
}
}
}
注意?
remote.baseUrl是可选的(默认为 Gemini API 基础 URL)?remote.headers让你在需要时添加额外头?- 默认模型:
gemini-embedding-001?
如果你想使用自定?OpenAI 兼容端点(OpenRouter、vLLM 或代理),你可以?remote 配置?OpenAI provider 一起使用:
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、voyage、mistral、local?none?- 回退 provider 仅在主嵌?provider 失败时使用?
批量索引(OpenAI + Gemini + Voyage):
- 默认禁用。为大规模索引设?
agents.defaults.memorySearch.remote.batch.enabled = true(OpenAI、Gemini ?Voyage)? - 默认行为等待批量完成;如需要可调整
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 文档和定价:
配置示例?
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?MEMORY.md+memory/**/*.md中的 Markdown 片段进行语义搜索(~400 token 目标?0 token 重叠)。它返回片段文本(上限约 700 字符)、文件路径、行范围、分数、provider/模型,以及我们是否从本地 ?远程嵌入回退。不返回完整文件负载?memory_get读取特定内存 Markdown 文件(相对于工作区),可选择从起始行开始并读取 N 行。拒?MEMORY.md/memory/之外的路径?- 仅当
memorySearch.enabled对代理解析为 true 时,这两个工具才启用?
什么被索引(以及何时)
- 文件类型:仅 Markdown(
MEMORY.md、memory/**/*.md)? - 索引存储:每个代理的 SQLite,位?
~/.openclaw/memory/<agentId>.sqlite(可通过agents.defaults.memorySearch.store.path配置,支?{agentId}令牌)? - 新鲜度:
MEMORY.md+memory/上的监视器将索引标记为脏(防?1.5s)。同步在会话开始、搜索或按间隔安排时调度,并异步运行。会话记录使用增量阈值触发后台同步? - 重新索引触发:索引存储嵌?provider/model + 端点指纹 + 分块参数。如果其中任何一项更改,OpenClaw 自动重置并重新索引整个存储?
混合搜索(BM25 + 向量?
启用时,OpenClaw 结合?
- **向量相似?*(语义匹配,措辞可以不同?
- **BM25 关键字相关?*(精?token,如 ID、环境变量、代码符号)
如果你的平台不支持全文搜索,OpenClaw 回退到仅向量搜索?
为什么混合?
向量搜索擅长”这意味着相同的事??
- “Mac Studio gateway host” vs “运行 gateway 的机?
- “debounce file updates” vs “避免每次写入时索?
但它可能对精确、高信号 token 较弱?
- ID(
a828e60、b3b9895a…? - 代码符号(
memorySearch.query.hybrid? - 错误字符串(“sqlite-vec unavailable”?
BM25(全文)相反:强于精?token,弱于释义。混合搜索是务实的中间立场:**使用两种检索信?*,以便你?自然语言”查询?大海捞针”查询都能获得良好结果?
我们如何合并结果(当前设计)
实现草图?
- 从两边检索候选池?
- 向量:按余弦相似度检索前
maxResults * candidateMultiplier? - BM25:按 FTS5 BM25 排名检索前
maxResults * candidateMultiplier(越低越好)?
- ?BM25 排名转换?0..1 分数?
textScore = 1 / (1 + max(0, bm25Rank))
- 按块 ID 联合候选并计算加权分数?
finalScore = vectorWeight * vectorScore + textWeight * textScore
注意?
vectorWeight+textWeight在配置解析中规范化为 1.0,因此权重行为如百分比?- 如果嵌入不可用(?provider 返回零向量),我们仍然运?BM25 并返回关键字匹配?
- 如果无法创建 FTS5,我们保持仅向量搜索(无硬失败)?
这不?IR 理论完美”,但它简单、快速,并且倾向于改善真实笔记的召回/精确? 如果我们以后想更花哨,常见的下一步是互惠排名融合(RRF)或分数归一化(min/max ?z-score)然后混合?
后处理管?
在合并向量和关键字分数后,两个可选的后处理阶段在结果到达代理之前优化结果列表?
向量 + 关键??加权合并 ?时间衰减 ?排序 ?MMR ?Top-K 结果
两个阶段默认关闭,可以独立启用?
MMR 重新排序(多样性)
当混合搜索返回结果时,多个片段可能包含相似或重叠的内容。例如,搜索”家庭网络设置”可能返回五个几乎相同的片段,来自不同的每日笔记,都提到相同的路由器配置?
MMR(最大边际相关性) 重新排序结果以平衡相关性和多样性,确保顶级结果覆盖查询的不同方面,而不是重复相同信息?
工作原理?
- 按原始相关性(向量 + BM25 加权分数)评分结果?
- MMR 迭代选择结果,最大化:
λ × 相关?- (1-λ) × max_similarity_to_selected? - 结果之间的相似度使用分词内容?Jaccard 文本相似度测量?
lambda 参数控制权衡?
lambda = 1.0?纯相关性(无多样性惩罚)lambda = 0.0?最大多样性(忽略相关性)- 默认:
0.7(平衡,轻微相关性偏差)
示例 ?查询?home network setup”
给定这些内存文件?
memory/2026-02-10.md ?"Configured Omada router, set VLAN 10 for IoT devices"
memory/2026-02-08.md ?"Configured Omada router, moved IoT to VLAN 10"
memory/2026-02-05.md ?"Set up AdGuard DNS on 192.168.10.2"
memory/network.md ?"Router: Omeda ER605, AdGuard: 192.168.10.2, VLAN 10: IoT"
没有 MMR ??3 结果?
1. memory/2026-02-10.md (score: 0.92) ?router + VLAN
2. memory/2026-02-08.md (score: 0.89) ?router + VLAN (near-duplicate!)
3. memory/network.md (score: 0.85) ?reference doc
?MMR(?0.7)??3 结果?
1. memory/2026-02-10.md (score: 0.92) ?router + VLAN
2. memory/network.md (score: 0.85) ?reference doc (diverse!)
3. memory/2026-02-05.md (score: 0.78) ?AdGuard DNS (diverse!)
来自 2 ?8 日的近似重复被删除,代理获得三个不同的信息片段?
*何时启用? 如果你注意到 memory_search 返回冗余或近似重复的片段,特别是每日笔记经常在不同日期重复相似信息时?
时间衰减(最近优先)
具有每日笔记的代理随着时间积累数百个带日期的文件。没有衰减,一个措辞良好的六个月前的笔记可能超过昨天关于同一主题的更新?
时间衰减 根据每个结果的年龄对分数应用指数乘数,因此最近的记忆自然排名更高,而旧的逐渐消失?
decayedScore = score × e^(-λ × ageInDays)
其中 λ = ln(2) / halfLifeDays?
默认半衰?30 天:
- 今天的笔记:100% 原始分数
- 7 天前?*~84%**
- 30 天前?50%*
- 90 天前?12.5%*
- 180 天前?*~1.6%**
*永久文件永不衰减?
MEMORY.md(根内存文件?memory/中未带日期的文件(例?memory/projects.md、memory/network.md?- 这些包含应始终正常排名的持久参考信息?
带日期的每日文件(memory/YYYY-MM-DD.md)使用从文件名提取的日期。其他来源(例如会话记录)回退到文件修改时间(mtime)?
示例 ?查询?Rod 的工作时间表是什么?”
给定这些内存文件(今天是 2 ?10 日)?
memory/2025-09-15.md ?"Rod works Mon-Fri, standup at 10am, pairing at 2pm" (148 天前)
memory/2026-02-10.md ?"Rod has standup at 14:15, 1:1 with Zeb at 14:45" (今天)
memory/2026-02-03.md ?"Rod started new team, standup moved to 14:15" (7 天前)
没有衰减?
1. memory/2025-09-15.md (score: 0.91) ?最佳语义匹配,但过时了?
2. memory/2026-02-10.md (score: 0.82)
3. memory/2026-02-03.md (score: 0.80)
有衰减(halfLife=30):
1. memory/2026-02-10.md (score: 0.82 × 1.00 = 0.82) ?今天,无衰减
2. memory/2026-02-03.md (score: 0.80 × 0.85 = 0.68) ?7 天,轻微衰减
3. memory/2025-09-15.md (score: 0.91 × 0.03 = 0.03) ?148 天,几乎消失
过时?9 月笔记尽管具有最佳原始语义匹配,但仍降至底部?
*何时启用? 如果你的代理有多个月的每日笔记且发现旧、过时的信息排名超过最近的上下文?0 天的半衰期对每日笔记密集的工作流程效果良好;如果你经常参考旧笔记,增加它(例?90 天)?
配置
两个功能都在 memorySearch.query.hybrid 下配置:
agents: {
defaults: {
memorySearch: {
query: {
hybrid: {
enabled: true,
vectorWeight: 0.7,
textWeight: 0.3,
candidateMultiplier: 4,
// 多样性:减少冗余结果
mmr: {
enabled: true, // default: false
lambda: 0.7 // 0 = 最大多样性,1 = 最大相关?
},
// 最近:提升较新记忆
temporalDecay: {
enabled: true, // default: false
halfLifeDays: 30 // 分数?30 天减?
}
}
}
}
}
}
你可以独立启用任一功能?
- ?MMR ?当你有许多相似笔记但年龄不重要时有用?
- *仅时间衰? ?当最近重要但你的结果已经多样化时有用?
- *两? ?推荐用于具有大量、长期运行每日笔记历史的代理?
嵌入缓存
OpenClaw 可以?*块嵌?*缓存?SQLite 中,这样重新索引和频繁更新(尤其是会话记录)不会重新嵌入未更改的文本?
配置?
agents: {
defaults: {
memorySearch: {
cache: {
enabled: true,
maxEntries: 50000
}
}
}
}
会话内存搜索(实验性)
你可以选择索引会话记录并通过 memory_search 将其显示。这由实验性标志控制?
agents: {
defaults: {
memorySearch: {
experimental: { sessionMemory: true },
sources: ["memory", "sessions"]
}
}
}
注意?
- 会话索引?选择加入*(默认关闭)?
- 会话更新被防抖并异步索引,一旦它们超?delta 阈值(尽力而为)?
memory_search永远不阻塞索引;结果在后台同步完成前可能略微陈旧?- 结果仍然仅包括片段;
memory_get仍然限于内存文件? - 会话索引按代理隔离(仅该代理的会话日志被索引)?
- 会话日志位于磁盘上(
~/.openclaw/agents/<agentId>/sessions/*.jsonl)。任何具有文件系统访问权限的进程/用户都可以读取它们,因此将磁盘访问视为信任边界。对于更严格的隔离,请在单独 OS 用户或主机下运行代理?
Delta 阈值(显示默认值)?
agents: {
defaults: {
memorySearch: {
sync: {
sessions: {
deltaBytes: 100000, // ~100 KB
deltaMessages: 50 // JSONL ?
}
}
}
}
}
SQLite 向量加速(sqlite-vec?
?sqlite-vec 扩展可用时,OpenClaw 将嵌入存储在 SQLite 虚拟表(vec0)中,并在数据库中执行向量距离查询。这保持搜索快速,无需将每个嵌入加载到 JS 中?
配置(可选)?
agents: {
defaults: {
memorySearch: {
store: {
vector: {
enabled: true,
extensionPath: "/path/to/sqlite-vec"
}
}
}
}
}
注意?
enabled默认?true;禁用时,搜索回退到进程中存储嵌入的余弦相似度?- 如果 sqlite-vec 扩展丢失或加载失败,OpenClaw 记录错误并继?JS 回退(无向量表)?
extensionPath覆盖捆绑?sqlite-vec 路径(对自定义构建或非标准安装位置有用)?
本地嵌入自动下载
- 默认本地嵌入模型:
hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf(约 0.6 GB)? - ?
memorySearch.provider = "local"时,node-llama-cpp解析modelPath;如?GGUF 缺失,它自动下载到缓存(?local.modelCachePath如果设置),然后加载它。下载在重试时恢复? - 本地构建要求:运?
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 默认值?