基于SQLite与RRF融合策略的轻量级混合搜索实践指南
1. 项目概述:混合搜索的“刚需”与OpenClaw的解法
最近在折腾RAG(检索增强生成)应用,发现一个普遍痛点:纯向量检索虽然语义理解能力强,但有时会“跑偏”,搜出一些语义相关但实际无关的内容;而传统的全文检索(关键词匹配)虽然精准,却又缺乏对用户意图的深度理解。这就好比你想找“苹果”,向量检索可能会把“iPhone”、“MacBook”甚至“牛顿”都找出来,而全文检索则死死盯着“苹果”这两个字,对“Apple”公司或相关产品视而不见。这种时候,混合搜索(Hybrid Search)就成了一个“刚需”——它结合了向量检索的“意会”和全文检索的“言传”,让搜索既聪明又靠谱。
OpenClaw这个开源项目,恰好提供了一个轻量、易上手的混合搜索实现方案。它没有选择那些重型、复杂的专用向量数据库,而是巧妙地基于我们熟悉的SQLite,通过集成sqlite-vss扩展,在单文件数据库里就实现了向量索引和全文检索的融合。这对于中小型应用、原型验证或者资源受限的环境来说,吸引力巨大。你不用搭建一整套复杂的分布式系统,一个SQLite文件加上OpenClaw,就能快速验证混合搜索的效果。今天,我就结合自己的实操,拆解一下OpenClaw是如何实现这套混合搜索机制的,从设计思路、核心配置到踩坑实录,希望能给你一个清晰的参考。
2. 混合搜索的核心设计思路与方案选型
2.1 为什么是“向量 + 全文”?
在深入OpenClaw之前,我们必须先理解混合搜索为什么有效。这源于两种检索方式本质上的互补性:
- 向量检索(语义搜索):核心是将文本(或图像、音频等)通过Embedding模型转换为高维空间中的向量(一组数字)。搜索时,计算查询向量与库中所有向量之间的相似度(常用余弦相似度或点积)。它的优势在于理解语义,例如“汽车”和“轿车”的向量会很接近。但其劣势也很明显:对措辞变化敏感度低(“苹果公司”和“Apple Inc.”的文本可能差异大,但向量应接近),且无法进行精确的字面匹配、布尔过滤(AND, OR, NOT)或基于元数据(如日期、分类)的筛选。
- 全文检索(关键词搜索):基于倒排索引,快速定位包含特定词汇的文档。它擅长精确匹配、短语查询和复杂的布尔逻辑。但它的致命弱点是无法理解同义词、近义词或更上位的概念,完全依赖于词汇的表面形式。
混合搜索不是简单地把两个结果集拼在一起,而是需要对两者的分数进行归一化(Normalization)和加权融合(Weighted Fusion)。OpenClaw采用的是一种经典且实用的策略:倒数排名融合(Reciprocal Rank Fusion, RRF)。简单来说,它不关心向量检索和全文检索各自给出的原始分数(比如余弦相似度0.92,或TF-IDF得分2.5),而是只关心每个文档在各自结果列表中的排名。然后,根据一个公式为每个文档计算一个融合分数,这个公式会给予高排名(靠前)的文档更高的权重。这种方法的好处是避免了不同检索系统分数尺度不一致带来的融合难题,实现简单且效果通常不错。
2.2 OpenClaw的轻量化架构选型
OpenClaw选择SQLite +sqlite-vss作为技术底座,是一个极具针对性的选择,主要基于以下几点考量:
- 零运维与极致轻量:SQLite是进程内数据库,无需单独的服务器进程,它的数据库就是一个单一的文件。这意味着部署、备份、迁移都极其简单。对于很多需要内嵌搜索能力的桌面应用、移动应用或小型服务,这种零运维的特性是巨大的优势。
- 功能完备性:
sqlite-vss扩展为SQLite带来了向量相似性搜索能力。它底层通常依赖FAISS或HNSWlib这样的高效向量索引库。同时,SQLite自身通过FTS5(全文搜索)扩展提供了强大的全文检索功能。OpenClaw在SQLite这一层之上,构建了统一的数据模型和查询接口,将两者封装起来。 - 开发与集成成本低:使用SQLite意味着你可以用最熟悉的SQL语句来操作数据,无论是插入、更新还是复杂的联表查询。OpenClaw的API设计也力求简洁,降低了集成到现有项目中的门槛。
- 适用场景清晰:它非常适合文档数量在百万级以下、对延迟要求不是极端苛刻(亚毫秒级)的场景。例如,个人知识库、企业内部的文档检索系统、中小型网站的站内搜索、或是作为大型应用中的一个特定模块。
注意:虽然
sqlite-vss性能不错,但它毕竟不是为每秒处理数十亿次向量查询的互联网规模而设计的。如果你的数据量极大或并发极高,Milvus、Pinecone、Weaviate等专业向量数据库仍然是更优选择。OpenClaw的定位是“够用、好用、易用”的轻量级解决方案。
3. 核心细节解析与实操要点
3.1 数据模型与索引的协同设计
OpenClaw的核心数据表结构设计,直接决定了混合搜索的效率和效果。一个典型的设计包含以下几张表:
- 主文档表(
documents):存储文档的元数据。CREATE TABLE documents ( id INTEGER PRIMARY KEY, title TEXT, content TEXT, -- 原始文本内容 metadata JSON, -- 额外的结构化信息,如作者、日期、分类等 created_at TIMESTAMP ); - 全文搜索虚拟表(
documents_fts):使用SQLite的FTS5扩展创建,用于对content和title字段进行快速全文检索。
这个虚拟表会自动维护一个倒排索引。当你向CREATE VIRTUAL TABLE documents_fts USING fts5( title, content, content=documents, -- 内容源表 content_rowid=id -- 关联列 );documents表插入数据时,documents_fts会自动同步更新。 - 向量存储表(
document_embeddings):存储文档内容的向量表示。CREATE TABLE document_embeddings ( doc_id INTEGER PRIMARY KEY, embedding BLOB, -- 存储序列化的向量(如numpy数组转bytes) FOREIGN KEY (doc_id) REFERENCES documents(id) ); - 向量索引:这是
sqlite-vss发挥作用的地方。你需要在document_embeddings.embedding列上创建一个向量索引,以加速相似性搜索。-- 假设使用vss0扩展,并创建基于HNSW的索引 CREATE VIRTUAL TABLE vss_document_embeddings USING vss0( embedding(1536) -- 1536是例如text-embedding-3-small模型的维度 ); -- 将数据从document_embeddings表插入到向量索引虚拟表 INSERT INTO vss_document_embeddings(rowid, embedding) SELECT rowid, embedding FROM document_embeddings;
关键要点:
- 向量维度一致性:创建向量索引时指定的维度必须与你使用的Embedding模型输出维度完全一致,否则会导致搜索失败或结果异常。
- 索引更新策略:向
documents表插入新文档后,你需要同步完成三件事:1) 自动生成该文档的向量(调用Embedding模型);2) 将向量存入document_embeddings表;3) 将新向量的数据插入或更新到vss_document_embeddings虚拟表。这个过程最好封装在一个事务中,或由应用层逻辑保证一致性。OpenClaw通常会提供相应的工具函数或类方法来处理这个流程。 - 全文检索的Tokenizer:FTS5支持不同的分词器,对于中文,你可能需要集成如
jieba等中文分词器作为FTS5的插件,否则默认的分词器会将中文按字分割,效果不佳。这是部署中文应用时需要特别处理的一环。
3.2 混合查询的SQL实现剖析
混合搜索最核心的一步,就是将向量检索和全文检索的结果融合。我们来看一下在SQL层面,OpenClaw是如何巧妙实现的。以下是一个简化但核心的查询示例:
-- 步骤1: 向量相似性搜索 (假设查询向量已计算好,存储在变量`query_embedding`中) WITH vector_search AS ( SELECT doc_id, 1.0 / (0.1 + rank) AS vector_score -- 使用RRF公式的一个变体计算分数,rank是相似度排名 FROM ( SELECT de.doc_id, row_number() OVER (ORDER BY vss.distance) AS rank -- 按距离升序排名 FROM vss_document_embeddings vss JOIN document_embeddings de ON vss.rowid = de.rowid WHERE vss.search(embedding, query_embedding, 10) -- 搜索最相似的10个 ORDER BY vss.distance ASC ) ), -- 步骤2: 全文检索搜索 (搜索关键词'机器学习') text_search AS ( SELECT doc_id, 1.0 / (0.1 + rank) AS text_score FROM ( SELECT doc_id, row_number() OVER (ORDER BY bm25(documents_fts) DESC) AS rank -- 按BM25分数降序排名 FROM documents_fts WHERE documents_fts MATCH '机器学习' ORDER BY bm25(documents_fts) DESC LIMIT 10 ) ) -- 步骤3: 融合两个结果集 SELECT d.id, d.title, d.content, COALESCE(vs.vector_score, 0) * :vector_weight + COALESCE(ts.text_score, 0) * :text_weight AS hybrid_score FROM documents d LEFT JOIN vector_search vs ON d.id = vs.doc_id LEFT JOIN text_search ts ON d.id = ts.doc_id WHERE vs.doc_id IS NOT NULL OR ts.doc_id IS NOT NULL -- 确保至少在一个结果集中 ORDER BY hybrid_score DESC LIMIT 10;代码解读与参数说明:
WITH ... AS (...):这是CTE(公共表表达式),用于构建临时的结果集,让查询逻辑更清晰。vss.search(embedding, query_embedding, 10):这是sqlite-vss提供的搜索函数,在向量索引中查找与query_embedding最相似的10个向量。bm25(documents_fts):FTS5提供的BM25排序函数,用于评估全文检索的相关性得分。:vector_weight和:text_weight:这是两个权重参数。你可以通过调整它们来控制向量检索和全文检索在最终结果中的影响力。例如,如果你更看重语义相关性,可以将vector_weight设为0.7,text_weight设为0.3。COALESCE(... , 0):这个函数用于处理NULL值。如果一个文档只在向量搜索结果中,那么它的text_score就是NULL,COALESCE会将其转换为0,避免计算错误。
这个查询清晰地展示了混合搜索的“分-治-合”流程:分别执行两种检索,分别计算基于排名的分数,最后进行加权求和并排序。
4. 实操过程与核心环节实现
4.1 环境准备与OpenClaw部署
OpenClaw的部署方式比较灵活,你可以通过Docker快速启动,也可以直接在本地Python环境中安装。
方案一:Docker部署(推荐,隔离性好)
# 1. 拉取镜像 (请根据OpenClaw官方仓库确认最新镜像名) docker pull some-registry/openclaw:latest # 2. 运行容器 docker run -d \ --name openclaw \ -p 8000:8000 \ # OpenClaw的API服务端口 -v /path/to/your/data:/app/data \ # 挂载数据目录,持久化SQLite数据库 -e EMBEDDING_MODEL=text-embedding-3-small \ # 指定Embedding模型 -e OPENAI_API_KEY=your_key \ # 如果使用OpenAI的Embedding模型 some-registry/openclaw:latest这种方式最简单,适合快速体验和测试。你需要关注的是数据卷的挂载,确保数据库文件得以持久化。
方案二:本地Python环境安装
# 1. 克隆仓库 git clone https://github.com/your-org/openclaw.git cd openclaw # 2. 创建虚拟环境并安装依赖 python -m venv venv source venv/bin/activate # Linux/Mac # venv\Scripts\activate # Windows pip install -r requirements.txt # 3. 安装sqlite-vss扩展 # 这是一个关键且可能遇到问题的步骤。sqlite-vss需要编译,通常有预编译的二进制包。 # 对于Linux,可能需要从源码编译,依赖cmake和g++。 # 更简单的方法是使用集成了sqlite-vss的SQLite版本,或者使用pysqlite3-binary等包。 # OpenClaw的文档或requirements.txt通常会给出明确的指引。 # 例如,有时会这样安装: pip install sqlite-vss # 4. 配置环境变量 export OPENAI_API_KEY=your_key export EMBEDDING_MODEL=text-embedding-3-small # 或者使用本地模型,如BGE-M3,需配置对应的模型路径 # 5. 启动服务 python app/main.py本地安装更灵活,便于调试和定制,但环境配置,特别是sqlite-vss的安装,可能是第一个“坑”。
4.2 数据灌入与索引构建流程
假设我们有一个包含多篇技术文章的JSON文件需要导入。以下是使用OpenClaw Python SDK(或模拟其逻辑)的步骤:
import json import openclaw_client # 假设的客户端 from openclaw_client.embedding import get_embedding # 获取向量的函数 # 1. 初始化客户端 client = openclaw_client.Client(base_url="http://localhost:8000") # 2. 读取数据 with open('tech_articles.json', 'r', encoding='utf-8') as f: articles = json.load(f) # 3. 批量处理与导入 batch_size = 50 # 小批量处理,避免内存和API限制 for i in range(0, len(articles), batch_size): batch = articles[i:i+batch_size] documents_to_insert = [] for article in batch: # 构建文档结构 doc = { "id": f"article_{article['id']}", # 唯一ID "text": article["title"] + "\n" + article["content"], # 合并标题和内容作为检索文本 "metadata": { "source": article["url"], "author": article["author"], "publish_date": article["date"] } } documents_to_insert.append(doc) # 使用客户端的批量导入接口 # 这个接口内部会负责:切分文本(如果需要)、生成向量、插入SQLite并构建索引 response = client.ingest_documents(documents_to_insert) if not response.success: print(f"批量 {i//batch_size} 导入失败: {response.error}") else: print(f"已导入 {len(documents_to_insert)} 篇文档,当前总计: {response.total_docs}") print("数据导入完成!")关键操作解析:
- 文本预处理:在构建文档对象时,将
title和content合并是一个常见技巧,这能让全文检索和向量检索同时覆盖标题和正文信息,提升召回率。 - 批量处理:始终使用批量操作。无论是调用Embedding API(有速率限制)还是数据库插入,批量处理都能极大提升效率。
- 客户端
ingest_documents方法:这是一个黑盒魔法,它内部至少做了以下几件事:- 文本分块:如果单个文档内容过长(例如超过1000字),它可能会自动将文档分割成更小的“块”(chunks)。每个块会独立生成向量并被索引。这是处理长文档的标准做法。
- 向量化:调用配置的Embedding模型,为每个文本块生成向量。
- 原子化写入:在一个数据库事务中,将文档元数据、文本块、向量分别写入
documents表、documents_fts虚拟表和vss_document_embeddings索引,保证数据一致性。
4.3 执行混合搜索查询
数据准备好后,就可以进行搜索了。OpenClaw通常会提供一个简洁的搜索API。
# 使用OpenClaw客户端进行混合搜索 query = "如何优化深度学习模型的训练速度?" search_params = { "query": query, "search_type": "hybrid", # 指定混合搜索 "vector_weight": 0.6, # 向量检索权重 "text_weight": 0.4, # 全文检索权重 "top_k": 10, # 返回结果数量 "filter": { # 可选的元数据过滤 "metadata": { "publish_date": {"$gte": "2023-01-01"} # 只搜索2023年后的文章 } } } results = client.search(search_params) print(f"查询: '{query}'") print("="*50) for i, result in enumerate(results): print(f"{i+1}. [分数: {result['score']:.4f}] {result['title']}") print(f" 片段: {result['snippet'][:200]}...") # 显示匹配的内容片段 print(f" 元数据: {result.get('metadata', {})}") print()参数深度解读:
search_type: 除了hybrid,可能还支持vector(纯向量)、text(纯全文)。vector_weight&text_weight: 这是调整搜索行为的“旋钮”。如果你的查询是高度语义化的(如“表达喜悦心情的诗词”),提高vector_weight;如果是精确的技术术语或代码错误(如“ModuleNotFoundError: No module named 'torch'”),提高text_weight。需要通过A/B测试找到适合你场景的最佳权重。filter: 这是混合搜索的强大之处。你可以在语义/关键词搜索的基础上,叠加精确的结构化过滤。例如,只搜索某个作者的文章、某个时间段内的新闻、特定类别的产品等。这利用了SQLite本身对结构化数据查询的强大能力。
5. 性能调优与高级配置
5.1 向量索引参数调优
sqlite-vss创建的向量索引(如HNSW)有其关键参数,直接影响搜索速度和精度。
ef_construction:在建索引时,控制图构建的精细度。值越大,构建的图质量越高,索引更准确,但构建时间更长,索引文件也更大。建议:对于精度要求高的场景,可以设为200-400;对于追求速度或数据量大的场景,100-200可能足够。M:图中每个节点的最大连接数。值越大,图的连通性越好,搜索精度越高,但内存占用和搜索时间也会增加。建议:这是一个空间换时间的权衡。对于1536维的向量,16-48是常见范围。可以从16开始,根据效果调整。ef_search:在搜索时,控制搜索范围的广度。值越大,搜索越彻底,结果越准确,但耗时越长。建议:在查询时动态设置。对于要求高召回率的场景(如召回阶段),可以设高一些(如100-200);对于要求低延迟的在线服务,可以设低一些(如10-50)。
在OpenClaw的配置中,你可能需要在初始化数据库或创建集合时指定这些参数。查看sqlite-vss的文档以获取准确的配置方式。
5.2 全文检索优化
- 中文分词:如前所述,默认的FTS5分词器对中文不友好。你需要为SQLite编译或加载一个中文分词器模块(如
fts5_jieba)。OpenClaw如果面向中文用户,其Docker镜像或部署指南应该包含这一步。否则,你需要自行解决。 - 停用词(Stopwords):可以配置FTS5忽略“的”、“了”、“在”等常见但无实际检索意义的词,减少索引大小,提升效率。
- 词干提取(Stemming):对于英文,启用词干提取可以将“running”、“ran”、“runs”都归约为“run”,提升召回率。FTS5本身不支持,但可以通过外部扩展实现。
5.3 缓存与预热策略
对于生产环境,尤其是并发访问时,可以考虑以下优化:
- 查询缓存:对频繁出现的查询词及其混合搜索结果进行缓存。由于混合搜索涉及向量生成和数据库查询,开销较大,缓存能显著降低延迟。可以使用Redis或内存缓存(如
functools.lru_cache)实现。 - 向量缓存:将常用的查询文本对应的Embedding向量缓存起来,避免重复调用Embedding模型。
- 索引预热:在服务启动后、接受正式流量前,先执行一些典型的查询,让数据库文件和索引被加载到操作系统缓存中,避免“冷启动”导致的首次查询慢。
6. 常见问题与排查技巧实录
在实际使用OpenClaw进行混合搜索的开发和运维中,我遇到了不少典型问题。这里记录下排查思路和解决方法,希望能帮你绕过这些坑。
6.1 部署与依赖问题
问题1:sqlite-vss扩展加载失败,提示“no such module: vss0”
- 现象:运行OpenClaw时,在创建向量索引或执行搜索时,程序报错,提示找不到
vss0模块。 - 排查:
- 首先确认SQLite版本是否支持加载扩展。执行
python -c "import sqlite3; print(sqlite3.sqlite_version)",确保版本较新。 - 确认
sqlite-vss的库文件(.so,.dylib或.dll)是否已正确编译并放置在SQLite能加载的路径下。 - 检查OpenClaw的启动代码或配置,是否正确使用了
sqlite3.enable_load_extension(True)并调用了load_extension()函数来加载sqlite-vss。
- 首先确认SQLite版本是否支持加载扩展。执行
- 解决:
- Docker用户:确保使用的OpenClaw Docker镜像已经正确集成了
sqlite-vss。如果官方镜像没有,可能需要自己构建Dockerfile,在其中编译安装sqlite-vss。 - 本地安装用户:最可靠的方法是使用
pysqlite3-binary包替换标准库的sqlite3,因为它通常预编译了常用扩展。或者,严格按照sqlite-vss的GitHub仓库的编译指南进行操作。 - 临时测试:可以尝试在代码中显式加载:
conn.execute(“SELECT load_extension(‘./path/to/vss’)”)。
- Docker用户:确保使用的OpenClaw Docker镜像已经正确集成了
问题2:生成Embedding时API调用失败或超时
- 现象:数据导入过程中断,日志显示OpenAI API或本地Embedding模型调用错误。
- 排查:
- 检查网络连接和API密钥是否正确。
- 检查是否触发了速率限制(Rate Limit)。OpenAI等云服务对每分钟/每天的调用次数有限制。
- 如果是本地模型,检查模型文件是否下载完整,内存是否足够。
- 解决:
- 在数据导入代码中加入重试机制和指数退避。
- 降低批量处理的大小(
batch_size)。 - 使用更轻量的Embedding模型(如
text-embedding-3-small)。 - 考虑使用离线Embedding模型(如
BGE-M3、all-MiniLM-L6-v2),完全避免网络依赖和API费用。
6.2 搜索效果问题
问题3:混合搜索结果不理想,感觉不如纯向量或纯全文
- 现象:调整了
vector_weight和text_weight,但总觉得结果要么太“飘”(语义偏差大),要么太“死”(关键词卡太死)。 - 排查与调优:
- 分析查询类型:将你的典型查询分为几类:概念性查询(如“机器学习入门”)、事实性查询(如“Python 3.12 发布时间”)、精确匹配查询(如“错误代码 0x80070005”)。针对不同类型,预设不同的权重策略。
- A/B测试:准备一个包含查询和预期相关文档的小测试集。编写脚本,用不同的权重组合进行搜索,计算召回率(Recall)和归一化折损累计增益(NDCG)等指标,找到最优权重。OpenClaw本身可能不提供评估工具,需要自己实现。
- 检查Embedding模型:不同的Embedding模型在不同领域(如通用文本、代码、法律文书)的表现差异很大。如果你处理的是专业领域文本,尝试使用在该领域微调过的Embedding模型。
- 检查文本分块:如果文档很长,分块策略(块大小、重叠度)对向量检索效果影响巨大。块太小可能丢失上下文,块太大可能包含无关信息稀释向量。尝试调整OpenClaw的分块参数(如
chunk_size=500, chunk_overlap=50)。
问题4:搜索速度慢,特别是数据量增长后
- 现象:当文档数量从几千增加到几十万时,查询延迟明显上升。
- 排查:
- 检查索引:确认向量索引(HNSW)和全文索引(FTS5)是否都已正确创建。可以通过SQLite命令行工具执行
EXPLAIN QUERY PLAN ...来分析查询是否使用了索引。 - 监控硬件:查看CPU、内存和磁盘I/O。向量搜索是计算密集型,全文检索是I/O密集型。如果磁盘是机械硬盘,可能会成为瓶颈。
- 分析查询模式:是否使用了复杂的元数据过滤?这些过滤条件是否在相应字段上建立了索引?
- 检查索引:确认向量索引(HNSW)和全文索引(FTS5)是否都已正确创建。可以通过SQLite命令行工具执行
- 解决:
- 优化索引参数:适当降低
ef_search以提升搜索速度(会轻微牺牲精度)。 - 硬件升级:使用SSD硬盘能极大提升全文检索和数据库随机读写的性能。确保有足够的内存,让SQLite可以更多地利用内存缓存。
- 查询简化:避免过于复杂的联表查询或在大量数据上使用
LIKE ‘%...%’这样的全表扫描操作。 - 考虑分库分表:如果数据量真的非常大(千万级),SQLite可能不再是最佳选择。这时需要评估是否迁移到更专业的数据库。但对于百万级数据,经过优化的SQLite通常可以胜任。
- 优化索引参数:适当降低
6.3 数据一致性与维护
问题5:数据更新后,搜索不到最新内容
- 现象:通过程序更新了
documents表中的某条记录的内容,但用混合搜索查询时,返回的还是旧内容。 - 原因:这是最容易被忽略的一点。更新
documents表后,必须同步更新documents_fts虚拟表和vss_document_embeddings向量索引。它们不是自动联动的。 - 解决:
- 使用OpenClaw提供的更新API:如果OpenClaw提供了
update_document之类的方法,务必使用它,而不是直接操作底层SQL。 - 手动维护:如果必须直接操作SQL,需要在一个事务内完成以下步骤:
- 更新
documents表。 - 对
documents_fts表执行DELETE后INSERT操作(或使用FTS5的xUpdate函数)。 - 重新计算更新后内容的Embedding向量。
- 更新
document_embeddings表。 - 更新
vss_document_embeddings虚拟表(通常也是先删除旧行再插入新行)。
- 更新
- 使用OpenClaw提供的更新API:如果OpenClaw提供了
问题6:数据库文件越来越大,性能下降
- 现象:SQLite数据库文件(
.db)体积膨胀,插入和查询速度变慢。 - 解决:
- 定期VACUUM:SQLite的删除操作并不会立即释放空间。定期执行
VACUUM;命令可以重建数据库文件,释放未使用的空间。注意:这是一个重量级操作,会阻塞读写,应在业务低峰期进行。 - 考虑WAL模式:将SQLite的日志模式设置为预写日志模式(
PRAGMA journal_mode=WAL;)。这可以显著提升并发读写性能,尤其是在读多写少的场景下。 - 数据归档:将旧的、很少被查询的数据迁移到另一个历史数据库文件中,主库只保留热点数据。
- 定期VACUUM:SQLite的删除操作并不会立即释放空间。定期执行
混合搜索的实践是一个持续调优的过程。OpenClaw提供了一个优秀的起点,让你能以很低的成本验证想法并构建可用的系统。但要想让它真正在生产环境中稳定、高效地运行,就需要深入理解其背后的每一个组件,并针对自己的数据和查询负载进行细致的优化。从向量模型的选择、文本分块策略,到索引参数、权重配置,每一个环节都影响着最终的搜索体验。