feat: 知识库管理界面(入库监控 + 检索台)
桌面端「知识库」模块从占位变为可用:入库(切块/embedding/Milvus 监控) +
检索调试台(向量召回,带分数与来源)。
- mcp-go: 新工具 kb_search(返回结构化 JSON [{text,score}]);rag.Hit 加 json 标签
- gateway: POST /api/v1/kb/search → kb_search(结构化命中给检索台)
- desktop: lib/api ingestKb/searchKb;新 KbView(左 入库+监控日志 / 右 检索台命中列表
带 Milvus 来源徽标+分数);App 接 kb 视图;LeftNav 知识库 ready
- 验证: gateway/mcp-go build✓ + e2e PASS + 前端 build✓;真实浏览器——入库3条→监控
'已入库3块';语义查询'存储和搜索向量的组件'→Milvus(0.612)>Neo4j>NATS 排序正确,
全走真实百炼 embedding(控制面下发)+Milvus
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,7 @@ func (g *Gateway) Serve(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = unsub() }()
|
||||
log.Printf("[mcp_go] tools ready on %s (queue=%s): wiki_search, kb_ingest, memory_get, memory_upsert, history_get, history_append, echo",
|
||||
log.Printf("[mcp_go] tools ready on %s (queue=%s): wiki_search, kb_ingest, kb_search, memory_get, memory_upsert, history_get, history_append, echo",
|
||||
contract.SubjectToolsGoAll, contract.QueueToolsGo)
|
||||
<-ctx.Done()
|
||||
return ctx.Err()
|
||||
@@ -51,6 +51,8 @@ func (g *Gateway) dispatch(ctx context.Context, call *contract.ToolCall) *contra
|
||||
return g.wikiSearch(ctx, call)
|
||||
case "kb_ingest":
|
||||
return g.kbIngest(ctx, call)
|
||||
case "kb_search":
|
||||
return g.kbSearch(ctx, call)
|
||||
case "memory_get":
|
||||
return g.memoryGet(ctx, call)
|
||||
case "memory_upsert":
|
||||
@@ -139,6 +141,25 @@ func (g *Gateway) wikiSearch(ctx context.Context, call *contract.ToolCall) *cont
|
||||
return &contract.ToolResult{OK: true, Content: strings.TrimRight(b.String(), "\n")}
|
||||
}
|
||||
|
||||
// kbSearch 检索台用:返回结构化命中 JSON [{text,score},...](供检索台展示分数)。
|
||||
func (g *Gateway) kbSearch(ctx context.Context, call *contract.ToolCall) *contract.ToolResult {
|
||||
q, _ := call.Args["q"].(string)
|
||||
kb, _ := call.Args["kb"].(string)
|
||||
topK := 5
|
||||
if v, ok := call.Args["topK"].(float64); ok && v > 0 {
|
||||
topK = int(v)
|
||||
}
|
||||
if !g.rag.Ready() {
|
||||
return &contract.ToolResult{OK: true, Content: "[]"}
|
||||
}
|
||||
hits, err := g.rag.Search(ctx, kb, q, topK)
|
||||
if err != nil {
|
||||
return &contract.ToolResult{OK: false, Error: "kb_search: " + err.Error()}
|
||||
}
|
||||
data, _ := json.Marshal(hits)
|
||||
return &contract.ToolResult{OK: true, Content: string(data)}
|
||||
}
|
||||
|
||||
// kbIngest 把文本入库(切块→embedding→Milvus)。
|
||||
func (g *Gateway) kbIngest(ctx context.Context, call *contract.ToolCall) *contract.ToolResult {
|
||||
kb, _ := call.Args["kb"].(string)
|
||||
|
||||
@@ -120,8 +120,8 @@ func vectorDim(coll *entity.Collection) int {
|
||||
|
||||
// Hit 是一条检索结果。
|
||||
type Hit struct {
|
||||
Text string
|
||||
Score float32
|
||||
Text string `json:"text"`
|
||||
Score float32 `json:"score"`
|
||||
}
|
||||
|
||||
// search 用查询向量做 topK 向量检索(可按 kb 过滤)。
|
||||
|
||||
Reference in New Issue
Block a user