fix(rag): 合并后修正-升级脚本兼容 MySQL 8、重解析按 docId 清理旧向量

1. 升级脚本 2026-07-20-knowledge-fragment-fid.sql 使用了 MySQL 8 不支持的
   ADD COLUMN IF NOT EXISTS(MariaDB 语法),在存量库执行会直接语法报错。
   改为与脚本内索引守卫一致的 information_schema 判断 + PREPARE 方式,保持幂等。

2. parse() 重新解析时按 fragment.fid 删除旧向量:存量数据的 fid 为迁移脚本
   回填的 MD5 值,与向量库中实际存储的随机 fid 不一致,首次重解析无法命中
   旧向量,导致新旧向量重复累积。改为写入新向量前先按 docId 清理(三种
   向量库策略均支持),写入失败时仍补偿删除新 fid。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ageerle
2026-07-21 14:33:28 +08:00
parent 46a8d6b552
commit 9a2f326e42
2 changed files with 20 additions and 9 deletions

View File

@@ -215,8 +215,6 @@ public class KnowledgeAttachServiceImpl implements IKnowledgeAttachService {
? DocumentSplitConfig.DEFAULT_OVERLAP : knowledgeInfoVo.getOverlapChar().intValue();
DocumentSplitConfig splitConfig = new DocumentSplitConfig(
knowledgeInfoVo.getSeparator(), blockSize, overlap, attach.getType());
List<KnowledgeFragment> oldFragments = knowledgeFragmentMapper.selectList(
Wrappers.<KnowledgeFragment>lambdaQuery().eq(KnowledgeFragment::getDocId, docId));
// 获取文件信息并下载
List<OssDTO> ossDTOs = ossService.selectByIds(String.valueOf(attach.getOssId()));
@@ -262,12 +260,11 @@ public class KnowledgeAttachServiceImpl implements IKnowledgeAttachService {
storeEmbeddingBo.setApiKey(chatModelVo.getApiKey());
storeEmbeddingBo.setBaseUrl(chatModelVo.getApiHost());
try {
// 写入新向量前,先按 docId 清理该文档的旧向量:
// 历史数据的片段 fid 为迁移脚本回填的 MD5 值,与向量库中实际存储的 fid 不一致,
// 按 fid 删除无法命中旧向量,会导致重复向量累积;按 docId 清理对三种向量库均一致有效。
vectorStoreService.removeByDocId(docId, String.valueOf(knowledgeId));
vectorStoreService.storeEmbeddings(storeEmbeddingBo);
for (KnowledgeFragment old : oldFragments) {
if (StringUtils.isNotBlank(old.getFid())) {
vectorStoreService.removeByFid(old.getFid(), String.valueOf(knowledgeId));
}
}
} catch (Exception vectorError) {
for (String newFid : fids) {
try {