feat(rag): 大文件 RAG 做深 —— 并发入库/图谱窗口化 + Bleve落盘 + file_id治理
几十万字文件从"广而浅"到准生产级: - 向量化串行→并发分批保序(embedAll);几十万字上千块快数倍 - 图谱整篇喂LLM(爆上下文只抽开头)→窗口化并发抽(extractGraphWindowed), 全覆盖;窗口/封顶/并发 env 可配;图谱可单配便宜模型(GRAPH_CHAT_*,未配回退主chat) - Bleve 内存索引(重启即丢、三路退两路)→落盘 scorch(env BLEVE_PATH,失败退内存兜底) - 下游键改稳定 file_id:Neo4j 关系打 file_id(实体仍 kb+name 共享); 新增 kb_delete 工具 + Engine.DeleteDoc 级联删 Milvus/Bleve/Neo4j - 单测:窗口化/去重/env可配/落盘持久/图谱模型回退 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -56,7 +56,9 @@ func (g *graphStore) close(ctx context.Context) {
|
||||
}
|
||||
|
||||
// store 把三元组 MERGE 进 Neo4j(实体 + 关系,按 kb 隔离)。
|
||||
func (g *graphStore) store(ctx context.Context, kb string, triples []Triple) (int, error) {
|
||||
// 关系带 file_id(来源文档稳定 ID)→ 同一三元组来自不同文档各成一条边,供按文档级联删;
|
||||
// 实体仍按 (kb,name) 共享去重(一个实体可被多篇文档提及)。
|
||||
func (g *graphStore) store(ctx context.Context, kb, fileID string, triples []Triple) (int, error) {
|
||||
if !g.ready() {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -68,8 +70,8 @@ func (g *graphStore) store(ctx context.Context, kb string, triples []Triple) (in
|
||||
_, err := neo4j.ExecuteQuery(ctx, g.driver,
|
||||
`MERGE (a:Entity {kb:$kb, name:$s})
|
||||
MERGE (b:Entity {kb:$kb, name:$o})
|
||||
MERGE (a)-[r:REL {type:$p}]->(b)`,
|
||||
map[string]any{"kb": kb, "s": t.S, "o": t.O, "p": t.P},
|
||||
MERGE (a)-[r:REL {type:$p, file_id:$fid}]->(b)`,
|
||||
map[string]any{"kb": kb, "s": t.S, "o": t.O, "p": t.P, "fid": fileID},
|
||||
neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j"))
|
||||
if err != nil {
|
||||
return n, err
|
||||
@@ -79,6 +81,26 @@ func (g *graphStore) store(ctx context.Context, kb string, triples []Triple) (in
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// deleteByFile 删除某文档(file_id)贡献的全部关系,再清掉因此变孤儿的实体(无任何关系)。
|
||||
// 共享实体(仍被其它文档的关系连着)保留。kb 作用域隔离。
|
||||
func (g *graphStore) deleteByFile(ctx context.Context, kb, fileID string) error {
|
||||
if !g.ready() || fileID == "" {
|
||||
return nil
|
||||
}
|
||||
if _, err := neo4j.ExecuteQuery(ctx, g.driver,
|
||||
`MATCH (:Entity {kb:$kb})-[r:REL {file_id:$fid}]->(:Entity {kb:$kb}) DELETE r`,
|
||||
map[string]any{"kb": kb, "fid": fileID},
|
||||
neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j")); err != nil {
|
||||
return err
|
||||
}
|
||||
// 孤儿实体清理:本 kb 内不再连任何关系的实体删除。
|
||||
_, err := neo4j.ExecuteQuery(ctx, g.driver,
|
||||
`MATCH (e:Entity {kb:$kb}) WHERE NOT (e)--() DELETE e`,
|
||||
map[string]any{"kb": kb},
|
||||
neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j"))
|
||||
return err
|
||||
}
|
||||
|
||||
// search 图谱召回:找查询里提到的实体,返回其相连三元组(文本化)。
|
||||
func (g *graphStore) search(ctx context.Context, kb, query string, limit int) []Hit {
|
||||
if !g.ready() || query == "" {
|
||||
|
||||
Reference in New Issue
Block a user