知识库的搜索测试无法查到数据(实际上是有相关数据的)
例行检查
- [ ] 我已确认目前没有类似 issue
- [ ] 我已完整查看过项目 README,以及项目文档
- [ ] 我使用了自己的 key,并确认我的 key 是可正常使用的
- [ ] 我理解并愿意跟进此 issue,协助测试和提供反馈
- [x] 我理解并认可上述内容,并理解项目维护者精力有限,不遵循规则的 issue 可能会被无视或直接关闭
你的版本
- [ ] 公有云版本
- [x] 私有部署版本, 具体版本号: 4.8.22-alpha 使用的pg版本
问题描述, 日志截图,配置文件等
知识库中搜索测试,无法查询到数据,实际上是有数据的
查看了fastGPT容器的日志如下:
打印了一个sql
我将sql拷贝出来,发现是一个带分页的sql查询语句,我用navicat连上postgres之后执行了一下,如果不带limit分页条件,是可以查出数据的,如下
但是如果带上limit分页,就查不出结果了
复现步骤
- 上传自己的pdf文档
- 在知识库测试搜索
- 搜索结果为空
预期结果 预期应该搜出来数据
相关截图
重新构建索引或者增大 ef search 试试
好像是pgvector的锅,在pgvector的issue里找到了这个 https://github.com/pgvector/pgvector/issues/719 ,这个issue目前还没关闭,似乎这个bug还没修复
那我把这个issue关闭了,等待pgvector那边修复吧
留着好了,准备升级 0.8.0,到时候再试试。可以先把索引参数调整一下。估计还是 hnsw 索引的问题。
重建索引后,把索引参数调到1000了,还是不行
https://github.com/pgvector/pgvector/issues/719 这个issue被关闭了。另外我将插件的版本已经升级到了0.8.0了,问题依旧存在
https://github.com/pgvector/pgvector/issues/719 这个issue被关闭了。另外我将插件的版本已经升级到了0.8.0了,问题依旧存在
你增加迭代次数了吗
没有,我仅仅是升级了插件版本,并在V4.8.22版本上测试
没有,我仅仅是升级了插件版本,并在V4.8.22版本上测试
这并不会有任何变化,它并不是一个错误,而是 hnsw 索引与 where 条件的问题,根据它的 issue 描述,需要通过增加迭代查询来解决。
咱们的查询语句是不是应该增加SET hnsw.iterative_scan = on; 开启迭代器
我修改了源码中的如下语句,增加了打开迭代器的配置,但是问题依旧
const results: any = await PgClient.query(
`
BEGIN;
SET hnsw.iterative_scan = on;
SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100};
select id, collection_id, vector <#> '[${vector}]' AS score
from ${DatasetVectorTableName}
where team_id='${teamId}'
AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')})
${filterCollectionIdSql}
${forbidCollectionSql}
order by score limit ${limit};
COMMIT;`
);
我修改了源码中的如下语句,增加了打开迭代器的配置,但是问题依旧
const results: any = await PgClient.query( ` BEGIN; SET hnsw.iterative_scan = on; SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100}; select id, collection_id, vector <#> '[${vector}]' AS score from ${DatasetVectorTableName} where team_id='${teamId}' AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')}) ${filterCollectionIdSql} ${forbidCollectionSql} order by score limit ${limit}; COMMIT;` );
按它issue里推荐配置加上试试
测试方法: 分别配置和调整如下3个参数,在console中进行测试 SET hnsw.scan_mem_multiplier = 2; (调整范围1-8) SET hnsw.max_scan_tuples = 20000; (调整范围1000000-20000) SET hnsw.iterative_scan = relaxed_order;(调整范围strict_order/relaxed_order)
测试结论:
- 增加SET hnsw.iterative_scan = relaxed_order;后,能够部分解决(我这边数据集场景下,limit100 能出来4条,耗时229ms)
- 调整hnsw.scan_mem_multiplier和hnsw.max_scan_tuples 这两个值,能够提高limit 100情况下,返回的数据。但同时也增加了耗时,特别是scan_mem_multiplier值的增加会成倍增加耗时(当scan_mem_multiplier=2时,耗时提高到了3228ms)。
但是: 如果在代码中调整为如下内容,则所有的向量搜索都返回空结果。:
const results: any = await PgClient.query(
`
BEGIN;
SET LOCAL hnsw.iterative_scan = relaxed_order;
SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100};
select id, collection_id, vector <#> '[${vector}]' AS score
from ${DatasetVectorTableName}
where team_id='${teamId}'
AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')})
${filterCollectionIdSql}
${forbidCollectionSql}
order by score limit ${limit};
COMMIT;`
);
我通过console中记录的慢查询日志,将语句复制到console中,是可以查询到的。所以很奇怪,是什么原因导致最终的查询结果仍然为空。
我们这边遇到一个非常奇怪的问题,已导入的知识库,都无法搜索了,报错:搜索结果为空,但新导入的又没问题,旧知识重新构建也没问题(能想到的变更就是中间做了一次数据库升配操作),问题非常诡异
测试方法: 分别配置和调整如下3个参数,在console中进行测试 SET hnsw.scan_mem_multiplier = 2; (调整范围1-8) SET hnsw.max_scan_tuples = 20000; (调整范围1000000-20000) SET hnsw.iterative_scan = relaxed_order;(调整范围strict_order/relaxed_order)
测试结论:
- 增加SET hnsw.iterative_scan = relaxed_order;后,能够部分解决(我这边数据集场景下,limit100 能出来4条,耗时229ms)
- 调整hnsw.scan_mem_multiplier和hnsw.max_scan_tuples 这两个值,能够提高limit 100情况下,返回的数据。但同时也增加了耗时,特别是scan_mem_multiplier值的增加会成倍增加耗时(当scan_mem_multiplier=2时,耗时提高到了3228ms)。
但是: 如果在代码中调整为如下内容,则所有的向量搜索都返回空结果。:
const results: any = await PgClient.query( ` BEGIN; SET LOCAL hnsw.iterative_scan = relaxed_order; SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100}; select id, collection_id, vector <#> '[${vector}]' AS score from ${DatasetVectorTableName} where team_id='${teamId}' AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')}) ${filterCollectionIdSql} ${forbidCollectionSql} order by score limit ${limit}; COMMIT;` );我通过console中记录的慢查询日志,将语句复制到console中,是可以查询到的。所以很奇怪,是什么原因导致最终的查询结果仍然为空。
通过手动执行一次pg主动回收解决了所有问题,然后看了下自动回收,默认阈值在20%,不太适合向量表,调整了些参数后好很多。 回收策论示例
// 积极策略 100万推荐配置
ALTER TABLE modeldata SET (
autovacuum_vacuum_scale_factor = 0.01, -- 死组清理的比例
autovacuum_analyze_scale_factor = 0.02, -- 重新统计的比例
autovacuum_vacuum_threshold = 1000, -- 更高的基础阈值
autovacuum_analyze_threshold = 1000,
autovacuum_vacuum_cost_delay = 10, -- 降低清理过程的休眠时间(ms),默认20ms
autovacuum_vacuum_cost_limit = 2000 -- 增加每轮清理的工作量,默认200
);
This issue has not been updated for more than 6 months and is marked as stale. If there is no further activity within 7 days, it will be automatically closed. Please reply to this issue if you need to continue following up on it.