From 8ff68078b7ce6fcfd1fdffac392d0370af8b7728 Mon Sep 17 00:00:00 2001 From: Blizzard Date: Wed, 10 Jun 2026 17:40:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=9F=A5=E8=AF=86=E5=BA=93=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=95=8C=E9=9D=A2=EF=BC=88=E5=85=A5=E5=BA=93=E7=9B=91?= =?UTF-8?q?=E6=8E=A7=20+=20=E6=A3=80=E7=B4=A2=E5=8F=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 桌面端「知识库」模块从占位变为可用:入库(切块/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 --- sundynix-desktop/frontend/src/App.tsx | 3 + sundynix-desktop/frontend/src/lib/api.ts | 29 ++++ .../frontend/src/shell/LeftNav.tsx | 2 +- .../frontend/src/views/KbView.tsx | 144 ++++++++++++++++++ sundynix-gateway/internal/handler/kb.go | 31 ++++ sundynix-gateway/internal/router/router.go | 1 + sundynix-mcp-go/internal/mcp/gateway.go | 23 ++- sundynix-mcp-go/internal/rag/milvus.go | 4 +- 8 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 sundynix-desktop/frontend/src/views/KbView.tsx diff --git a/sundynix-desktop/frontend/src/App.tsx b/sundynix-desktop/frontend/src/App.tsx index 0582008..d2192da 100644 --- a/sundynix-desktop/frontend/src/App.tsx +++ b/sundynix-desktop/frontend/src/App.tsx @@ -5,6 +5,7 @@ import { LeftNav, type ViewKey } from "./shell/LeftNav"; import { BottomDrawer } from "./shell/BottomDrawer"; import { StudioView } from "./studio/StudioView"; import { MemoryView } from "./views/MemoryView"; +import { KbView } from "./views/KbView"; import { Placeholder } from "./views/Placeholder"; import { submitTask, streamTokens, type Identity } from "./lib/api"; import type { TaskDsl } from "./lib/dsl"; @@ -70,6 +71,8 @@ export default function App() {
{view === "studio" ? ( + ) : view === "kb" ? ( + ) : view === "memory" ? ( ) : ( diff --git a/sundynix-desktop/frontend/src/lib/api.ts b/sundynix-desktop/frontend/src/lib/api.ts index 5ed32c5..e01850b 100644 --- a/sundynix-desktop/frontend/src/lib/api.ts +++ b/sundynix-desktop/frontend/src/lib/api.ts @@ -47,6 +47,35 @@ export function streamTokens( return () => es.close(); } +// ingestKb: POST /api/v1/kb/ingest,把文本入库(→ mcp-go kb_ingest:切块/embedding/Milvus)。 +export async function ingestKb(kb: string, text: string): Promise { + const res = await fetch(`${GATEWAY}/api/v1/kb/ingest`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ kb, text }), + }); + const data = (await res.json()) as { message?: string; error?: string }; + if (!res.ok) throw new Error(data.error ?? `ingest failed: ${res.status}`); + return data.message ?? "ok"; +} + +export interface KbHit { + text: string; + score: number; +} + +// searchKb: POST /api/v1/kb/search,检索台查询(→ mcp-go kb_search,带分数)。 +export async function searchKb(kb: string, q: string, topK = 5): Promise { + const res = await fetch(`${GATEWAY}/api/v1/kb/search`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ kb, q, topK }), + }); + const data = (await res.json()) as { hits?: KbHit[]; error?: string }; + if (!res.ok) throw new Error(data.error ?? `search failed: ${res.status}`); + return data.hits ?? []; +} + // setMemory: PUT /api/v1/memory,登记一条用户偏好(→ mcp-go memory_upsert)。 export async function setMemory( id: Identity, diff --git a/sundynix-desktop/frontend/src/shell/LeftNav.tsx b/sundynix-desktop/frontend/src/shell/LeftNav.tsx index 7dedf45..00fe3f2 100644 --- a/sundynix-desktop/frontend/src/shell/LeftNav.tsx +++ b/sundynix-desktop/frontend/src/shell/LeftNav.tsx @@ -19,7 +19,7 @@ interface Item { const ITEMS: Item[] = [ { key: "home", label: "工作台", icon: "■" }, { key: "studio", label: "编排", icon: "◆", group: "BUILD", ready: true }, - { key: "kb", label: "知识库", icon: "▣", group: "BUILD" }, + { key: "kb", label: "知识库", icon: "▣", group: "BUILD", ready: true }, { key: "report", label: "报告", icon: "▤", group: "BUILD" }, { key: "runs", label: "运行", icon: "▸", group: "RUN" }, { key: "memory", label: "记忆", icon: "◇", group: "MANAGE", ready: true }, diff --git a/sundynix-desktop/frontend/src/views/KbView.tsx b/sundynix-desktop/frontend/src/views/KbView.tsx new file mode 100644 index 0000000..cf7fd9d --- /dev/null +++ b/sundynix-desktop/frontend/src/views/KbView.tsx @@ -0,0 +1,144 @@ +import { useState } from "react"; +import { ingestKb, searchKb, type KbHit } from "../lib/api"; + +interface IngestLog { + t: string; + msg: string; + ok: boolean; +} + +// 知识库管理:入库监控(切块/embedding/Milvus)+ 检索调试台(带分数与来源)。 +export function KbView() { + const [kb, setKb] = useState("docs"); + const [text, setText] = useState(""); + const [logs, setLogs] = useState([]); + const [ingesting, setIngesting] = useState(false); + + const [q, setQ] = useState(""); + const [topK, setTopK] = useState(5); + const [hits, setHits] = useState(null); + const [searching, setSearching] = useState(false); + const [err, setErr] = useState(""); + + const stamp = () => new Date().toLocaleTimeString(); + + const onIngest = async () => { + if (!text.trim()) return; + setIngesting(true); + try { + const msg = await ingestKb(kb, text); + setLogs((l) => [{ t: stamp(), msg, ok: true }, ...l]); + setText(""); + } catch (e) { + setLogs((l) => [{ t: stamp(), msg: (e as Error).message, ok: false }, ...l]); + } finally { + setIngesting(false); + } + }; + + const onSearch = async () => { + if (!q.trim()) return; + setSearching(true); + setErr(""); + try { + setHits(await searchKb(kb, q, topK)); + } catch (e) { + setErr((e as Error).message); + setHits(null); + } finally { + setSearching(false); + } + }; + + return ( +
+
+ 知识库 + setKb(e.target.value)} + placeholder="知识库名" + title="知识库(Milvus kb 字段分区)" + /> + 入库 → 切块 / embedding / Milvus;检索 → 向量召回 +
+ +
+ {/* 左:入库 + 监控日志 */} +
+

入库(按行切块)

+