docs: 添加系统架构图和核心业务流程图 (drawio)

This commit is contained in:
2026-06-11 10:58:15 +08:00
parent b02d3378fc
commit 4c51d8ce7f
2 changed files with 720 additions and 0 deletions

302
docs/arc.drawio Normal file
View File

@@ -0,0 +1,302 @@
<mxfile host="65bd71144e">
<diagram id="5pkIbrPrzeIIfLiHXYUX" name="Page-1">
<mxGraphModel dx="1152" dy="493" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="title" value="GraphRAG Studio — 系统架构图" style="text;fontSize=20;fontStyle=1;fillColor=none;strokeColor=none;align=center;" parent="1" vertex="1">
<mxGeometry x="250" y="5" width="300" height="30" as="geometry"/>
</mxCell>
<mxCell id="user-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#30363d;dashed=1;" parent="1" vertex="1">
<mxGeometry x="160" y="40" width="420" height="45" as="geometry"/>
</mxCell>
<mxCell id="user" value="🌐 用户浏览器 (Browser)" style="rounded=1;fillColor=#1a3a22;strokeColor=#3fb950;fontColor=#f0f6fc;fontSize=14;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="230" y="48" width="280" height="30" as="geometry"/>
</mxCell>
<mxCell id="edge1" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=2;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="85" as="sourcePoint"/>
<mxPoint x="370" y="105" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fe-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#58a6ff;strokeWidth=2;fillStyle=auto;" parent="1" vertex="1">
<mxGeometry x="30" y="108" width="680" height="125" as="geometry"/>
</mxCell>
<mxCell id="fe-label" value="Frontend — React SPA (Vite + TypeScript + Tailwind CSS)" style="text;fontSize=12;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#58a6ff;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="110" width="350" height="18" as="geometry"/>
</mxCell>
<mxCell id="page-dash" value="Dashboard" style="rounded=1;fillColor=#21262d;strokeColor=#30363d;fontColor=#c9d1d9;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="45" y="133" width="100" height="28" as="geometry"/>
</mxCell>
<mxCell id="page-docs" value="Documents" style="rounded=1;fillColor=#21262d;strokeColor=#30363d;fontColor=#c9d1d9;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="155" y="133" width="100" height="28" as="geometry"/>
</mxCell>
<mxCell id="page-kg" value="KG Explorer" style="rounded=1;fillColor=#21262d;strokeColor=#30363d;fontColor=#c9d1d9;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="265" y="133" width="100" height="28" as="geometry"/>
</mxCell>
<mxCell id="page-chat" value="QA Chat" style="rounded=1;fillColor=#21262d;strokeColor=#30363d;fontColor=#c9d1d9;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="375" y="133" width="100" height="28" as="geometry"/>
</mxCell>
<mxCell id="page-search" value="Search" style="rounded=1;fillColor=#21262d;strokeColor=#30363d;fontColor=#c9d1d9;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="485" y="133" width="100" height="28" as="geometry"/>
</mxCell>
<mxCell id="fe-state" value="AppProvider (React Context)" style="rounded=1;fillColor=#1c2128;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="45" y="170" width="200" height="24" as="geometry"/>
</mxCell>
<mxCell id="fe-d3" value="D3.js 力导向图" style="rounded=1;fillColor=#1c2128;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="260" y="170" width="200" height="24" as="geometry"/>
</mxCell>
<mxCell id="fe-api" value="API Client (api.ts)" style="rounded=1;fillColor=#1c2128;strokeColor=#d29922;fontColor=#d29922;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="475" y="170" width="220" height="24" as="geometry"/>
</mxCell>
<mxCell id="edge2" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=2;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="233" as="sourcePoint"/>
<mxPoint x="370" y="253" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="edge2-label" value="REST /api/v1" style="text;fontSize=9;fontColor=#8b949e;fillColor=none;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="378" y="234" width="70" height="16" as="geometry"/>
</mxCell>
<mxCell id="api-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#3fb950;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="30" y="258" width="680" height="90" as="geometry"/>
</mxCell>
<mxCell id="api-label" value="Backend — FastAPI (Python) :8000" style="text;fontSize=12;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#3fb950;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="260" width="250" height="18" as="geometry"/>
</mxCell>
<mxCell id="r-docs" value="/documents" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="40" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-idx" value="/index" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="146" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-kg" value="/kg" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="252" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-query" value="/query" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="358" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-search" value="/search" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="464" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-sys" value="/system" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;fontStyle=1;" parent="1" vertex="1">
<mxGeometry x="570" y="285" width="96" height="28" as="geometry"/>
</mxCell>
<mxCell id="r-docs-d" value="上传/列表/删除" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="40" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="r-idx-d" value="索引任务管理" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="146" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="r-kg-d" value="图谱 CRUD" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="252" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="r-query-d" value="QA问答" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="358" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="r-search-d" value="实体/路径/子图" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="464" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="r-sys-d" value="健康/统计/Demo" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="570" y="314" width="96" height="14" as="geometry"/>
</mxCell>
<mxCell id="edge3" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=2;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="348" as="sourcePoint"/>
<mxPoint x="370" y="368" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="svc-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#d29922;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="30" y="373" width="680" height="52" as="geometry"/>
</mxCell>
<mxCell id="svc-label" value="Service Layer" style="text;fontSize=11;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#d29922;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="375" width="100" height="16" as="geometry"/>
</mxCell>
<mxCell id="s-doc" value="document_service" style="rounded=1;fillColor=#21262d;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="40" y="394" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="s-idx" value="indexing_service" style="rounded=1;fillColor=#21262d;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="170" y="394" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="s-kg" value="kg_service" style="rounded=1;fillColor=#21262d;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="300" y="394" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="s-qa" value="qa_service" style="rounded=1;fillColor=#21262d;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="430" y="394" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="s-search" value="search_service" style="rounded=1;fillColor=#21262d;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="560" y="394" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="edge4" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=2;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="425" as="sourcePoint"/>
<mxPoint x="370" y="448" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="pipe-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#8957e5;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="30" y="453" width="680" height="52" as="geometry"/>
</mxCell>
<mxCell id="pipe-label" value="Pipeline Layer" style="text;fontSize=11;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#8957e5;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="455" width="100" height="16" as="geometry"/>
</mxCell>
<mxCell id="p-text" value="text_assembler" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="40" y="474" width="110" height="24" as="geometry"/>
</mxCell>
<mxCell id="p-extr" value="entity_extractor" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="185" y="474" width="110" height="24" as="geometry"/>
</mxCell>
<mxCell id="p-kgb" value="kg_builder" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="330" y="474" width="110" height="24" as="geometry"/>
</mxCell>
<mxCell id="p-qa" value="qa_agent" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="475" y="474" width="110" height="24" as="geometry"/>
</mxCell>
<mxCell id="pa1" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="150" y="486" as="sourcePoint"/>
<mxPoint x="182" y="486" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="pa2" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="295" y="486" as="sourcePoint"/>
<mxPoint x="327" y="486" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="pa3" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="440" y="486" as="sourcePoint"/>
<mxPoint x="472" y="486" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="st-layer" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#ff7b72;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="30" y="528" width="680" height="52" as="geometry"/>
</mxCell>
<mxCell id="st-label" value="Storage Layer — JSON File Store (backend/data/)" style="text;fontSize=11;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#ff7b72;align=left;" parent="1" vertex="1">
<mxGeometry x="40" y="530" width="320" height="16" as="geometry"/>
</mxCell>
<mxCell id="st-docs" value="docs_index.json" style="rounded=1;fillColor=#21262d;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="40" y="549" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="st-kgn" value="kg_nodes.json" style="rounded=1;fillColor=#21262d;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="175" y="549" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="st-kge" value="kg_edges.json" style="rounded=1;fillColor=#21262d;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="310" y="549" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="st-jobs" value="jobs/*.json" style="rounded=1;fillColor=#21262d;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="445" y="549" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="st-hist" value="query_history.jsonl" style="rounded=1;fillColor=#21262d;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" parent="1" vertex="1">
<mxGeometry x="580" y="549" width="120" height="24" as="geometry"/>
</mxCell>
<mxCell id="edge5" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=2;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="505" as="sourcePoint"/>
<mxPoint x="370" y="525" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="ext-box" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#8b949e;strokeWidth=1;dashed=1;" parent="1" vertex="1">
<mxGeometry x="740" y="108" width="190" height="175" as="geometry"/>
</mxCell>
<mxCell id="ext-label" value="外部依赖" style="text;fontSize=12;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" parent="1" vertex="1">
<mxGeometry x="760" y="110" width="150" height="18" as="geometry"/>
</mxCell>
<mxCell id="ext-mineru" value="MinerU&#xa;(PDF 解析)" style="rounded=1;fillColor=#21262d;strokeColor=#8b949e;fontColor=#ffa657;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="135" width="150" height="38" as="geometry"/>
</mxCell>
<mxCell id="ext-deepseek" value="DeepSeek API&#xa;(LLM 推理)" style="rounded=1;fillColor=#21262d;strokeColor=#8b949e;fontColor=#58a6ff;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="183" width="150" height="38" as="geometry"/>
</mxCell>
<mxCell id="ext-lx" value="LangExtract&#xa;(实体抽取框架)" style="rounded=1;fillColor=#21262d;strokeColor=#8b949e;fontColor=#bc8cff;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="231" width="150" height="38" as="geometry"/>
</mxCell>
<mxCell id="e2mineru" style="endArrow=classic;strokeColor=#ffa657;strokeWidth=1;dashed=1;entryX=0;entryY=0.5;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="185" y="453" as="sourcePoint"/>
<mxPoint x="757" y="154" as="targetPoint"/>
<Array as="points">
<mxPoint x="725" y="440"/>
<mxPoint x="725" y="154"/>
<mxPoint x="757" y="154"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e2ds" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1;dashed=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="475" y="453" as="sourcePoint"/>
<mxPoint x="757" y="202" as="targetPoint"/>
<Array as="points">
<mxPoint x="730" y="453"/>
<mxPoint x="730" y="202"/>
<mxPoint x="757" y="202"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="legend-box" value="" style="rounded=1;fillColor=#FFFFFF;strokeColor=#30363d;" parent="1" vertex="1">
<mxGeometry x="740" y="340" width="190" height="240" as="geometry"/>
</mxCell>
<mxCell id="legend-title" value="图例" style="text;fontSize=12;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#f0f6fc;align=center;" parent="1" vertex="1">
<mxGeometry x="760" y="345" width="150" height="18" as="geometry"/>
</mxCell>
<mxCell id="leg-fe" value="" style="rounded=1;fillColor=#58a6ff;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="370" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-fe-t" value="前端层 (React)" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="368" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-api" value="" style="rounded=1;fillColor=#3fb950;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="392" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-api-t" value="API 层 (FastAPI)" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="390" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-svc" value="" style="rounded=1;fillColor=#d29922;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="414" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-svc-t" value="服务层 (Service)" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="412" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-pipe" value="" style="rounded=1;fillColor=#8957e5;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="436" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-pipe-t" value="流水线层 (Pipeline)" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="434" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-st" value="" style="rounded=1;fillColor=#ff7b72;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="458" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-st-t" value="存储层 (JSON FileStore)" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="456" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-ext" value="" style="rounded=1;fillColor=#8b949e;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="755" y="480" width="14" height="14" as="geometry"/>
</mxCell>
<mxCell id="leg-ext-t" value="外部依赖" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="775" y="478" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-solid" value="" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="755" y="506" as="sourcePoint"/>
<mxPoint x="775" y="506" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="leg-solid-t" value="同步调用" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="780" y="497" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="leg-dash" value="" style="endArrow=classic;strokeColor=#8b949e;strokeWidth=1;dashed=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="755" y="530" as="sourcePoint"/>
<mxPoint x="775" y="530" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="leg-dash-t" value="异步/外部调用" style="text;fontSize=10;fillColor=none;strokeColor=none;fontColor=#c9d1d9;align=left;" parent="1" vertex="1">
<mxGeometry x="780" y="521" width="140" height="16" as="geometry"/>
</mxCell>
<mxCell id="tech-stack" value="技术栈: React + TypeScript + Vite + TailwindCSS | FastAPI + Python | D3.js | NetworkX | LangChain | DeepSeek | MinerU | LangExtract" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#484f58;align=center;" parent="1" vertex="1">
<mxGeometry x="30" y="595" width="900" height="16" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

418
docs/flow.drawio Normal file
View File

@@ -0,0 +1,418 @@
<mxGraphModel>
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<!-- Title -->
<mxCell id="title" value="GraphRAG Studio — 核心业务流程图" style="text;fontSize=20;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#f0f6fc;align=center;" vertex="1" parent="1">
<mxGeometry x="250" y="5" width="350" height="30" as="geometry"/>
</mxCell>
<!-- ===================================================================== -->
<!-- FLOW 1: 文件上传与索引构建 -->
<!-- ===================================================================== -->
<mxCell id="f1-bg" value="" style="rounded=1;fillColor=#0d1117;strokeColor=#58a6ff;strokeWidth=1;dashed=1;opacity=40;" vertex="1" parent="1">
<mxGeometry x="10" y="40" width="930" height="195" as="geometry"/>
</mxCell>
<mxCell id="f1-label" value="流程一:文件上传与知识图谱构建 (Indexing Pipeline)" style="text;fontSize=13;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#58a6ff;align=left;" vertex="1" parent="1">
<mxGeometry x="20" y="43" width="400" height="20" as="geometry"/>
</mxCell>
<!-- Row 1: Upload steps -->
<mxCell id="f1-start" value="📁 拖拽/选择文件" style="rounded=1;fillColor=#0d2137;strokeColor=#58a6ff;fontColor=#f0f6fc;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="25" y="72" width="110" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-a1" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1.5;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="135" y="89" as="sourcePoint"/>
<mxPoint x="155" y="89" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-validate" value="客户端校验&#xa;(格式+大小)" style="rounded=1;fillColor=#0d2137;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="158" y="72" width="110" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-a2" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="268" y="89" as="sourcePoint"/>
<mxPoint x="288" y="89" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-upload" value="POST /upload&#xa;保存至 uploads/" style="rounded=1;fillColor=#0d2137;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="291" y="72" width="110" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-a3" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="401" y="89" as="sourcePoint"/>
<mxPoint x="421" y="89" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-confirm" value="用户确认索引" style="rounded=1;fillColor=#0d2137;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="424" y="72" width="110" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-a4" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="534" y="89" as="sourcePoint"/>
<mxPoint x="554" y="89" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-startjob" value="POST /index/start&#xa;启动后台线程" style="rounded=1;fillColor=#0d2137;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="557" y="72" width="110" height="34" as="geometry"/>
</mxCell>
<!-- Arrow down to pipeline -->
<mxCell id="f1-down" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="612" y="106" as="sourcePoint"/>
<mxPoint x="612" y="128" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Row 2: Pipeline stages (3 stages) -->
<mxCell id="f1-stage1" value="Stage 1: MinerU 解析&#xa;PDF → content_list.json&#xa;(subprocess 调用)" style="rounded=1;fillColor=#1a2332;strokeColor=#ffa657;fontColor=#ffa657;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="25" y="135" width="170" height="50" as="geometry"/>
</mxCell>
<mxCell id="f1-pa1" style="endArrow=classic;strokeColor=#ffa657;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="195" y="160" as="sourcePoint"/>
<mxPoint x="225" y="160" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-stage2" value="Stage 2: LangExtract + DeepSeek&#xa;page → 实体抽取&#xa;(每页调用 LLM)" style="rounded=1;fillColor=#1a2332;strokeColor=#bc8cff;fontColor=#bc8cff;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="228" y="135" width="180" height="50" as="geometry"/>
</mxCell>
<mxCell id="f1-pa2" style="endArrow=classic;strokeColor=#bc8cff;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="408" y="160" as="sourcePoint"/>
<mxPoint x="438" y="160" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-stage3" value="Stage 3: kg_builder&#xa;实体去重 + CO_OCCURS_IN 建边&#xa;→ kg_nodes.json + kg_edges.json" style="rounded=1;fillColor=#1a2332;strokeColor=#3fb950;fontColor=#3fb950;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="441" y="135" width="195" height="50" as="geometry"/>
</mxCell>
<mxCell id="f1-pa3" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="636" y="160" as="sourcePoint"/>
<mxPoint x="666" y="160" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f1-merge" value="合并全局 KG&#xa;merge_kg()" style="rounded=1;fillColor=#1a2332;strokeColor=#3fb950;fontColor=#3fb950;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="669" y="135" width="120" height="50" as="geometry"/>
</mxCell>
<!-- Decision: result -->
<mxCell id="f1-decision" value="结果?" style="rhombus;fillColor=#1a2332;strokeColor=#d29922;fontColor=#d29922;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="809" y="133" width="60" height="54" as="geometry"/>
</mxCell>
<mxCell id="f1-pa4" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="789" y="160" as="sourcePoint"/>
<mxPoint x="809" y="160" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Success path -->
<mxCell id="f1-success" value="✅ done&#xa;status→indexed" style="rounded=1;fillColor=#1a3a22;strokeColor=#3fb950;fontColor=#3fb950;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="890" y="108" width="105" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-pa5" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="839" y="140" as="sourcePoint"/>
<mxPoint x="887" y="125" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Fail path -->
<mxCell id="f1-fail" value="❌ failed&#xa;显示错误+重试" style="rounded=1;fillColor=#3b1a1a;strokeColor=#f85149;fontColor=#f85149;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="890" y="160" width="105" height="34" as="geometry"/>
</mxCell>
<mxCell id="f1-pa6" style="endArrow=classic;strokeColor=#f85149;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="839" y="180" as="sourcePoint"/>
<mxPoint x="887" y="177" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Polling note -->
<mxCell id="f1-poll" value="⏱ 前端每3s轮询 GET /index/status/{job_id}" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#8b949e;align=left;" vertex="1" parent="1">
<mxGeometry x="25" y="195" width="280" height="14" as="geometry"/>
</mxCell>
<mxCell id="f1-cancel" value="✕ 支持取消: DELETE /index/jobs/{job_id}" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#8b949e;align=left;" vertex="1" parent="1">
<mxGeometry x="310" y="195" width="260" height="14" as="geometry"/>
</mxCell>
<mxCell id="f1-note" value="后台线程执行,支持 cancel flag 中断" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#8b949e;align=left;" vertex="1" parent="1">
<mxGeometry x="580" y="195" width="250" height="14" as="geometry"/>
</mxCell>
<!-- ===================================================================== -->
<!-- FLOW 2: Agentic-RAG 智能问答 -->
<!-- ===================================================================== -->
<mxCell id="f2-bg" value="" style="rounded=1;fillColor=#0d1117;strokeColor=#3fb950;strokeWidth=1;dashed=1;opacity=40;" vertex="1" parent="1">
<mxGeometry x="10" y="245" width="930" height="200" as="geometry"/>
</mxCell>
<mxCell id="f2-label" value="流程二Agentic-RAG 智能问答 (ReAct Agent)" style="text;fontSize=13;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#3fb950;align=left;" vertex="1" parent="1">
<mxGeometry x="20" y="248" width="400" height="20" as="geometry"/>
</mxCell>
<!-- Row 1: Input -->
<mxCell id="f2-q" value="💬 用户输入问题&#xa;(+ 对话历史)" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#f0f6fc;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="25" y="278" width="125" height="38" as="geometry"/>
</mxCell>
<mxCell id="f2-a1" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="150" y="297" as="sourcePoint"/>
<mxPoint x="175" y="297" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-post" value="POST /api/v1/query&#xa;{question, history}" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="178" y="278" width="135" height="38" as="geometry"/>
</mxCell>
<mxCell id="f2-a2" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="313" y="297" as="sourcePoint"/>
<mxPoint x="338" y="297" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-build" value="加载全局 KG&#xa;→ NetworkX Graph" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="341" y="278" width="130" height="38" as="geometry"/>
</mxCell>
<mxCell id="f2-a3" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="471" y="297" as="sourcePoint"/>
<mxPoint x="496" y="297" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-agent" value="创建 ReAct Agent&#xa;ChatOpenAI(deepseek-chat)&#xa;+ 4 个 @tool" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="499" y="278" width="145" height="38" as="geometry"/>
</mxCell>
<!-- Arrow down to ReAct loop -->
<mxCell id="f2-down" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="571" y="316" as="sourcePoint"/>
<mxPoint x="571" y="345" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- ReAct Loop (centerpiece) -->
<mxCell id="f2-react" value="" style="rounded=1;fillColor=#161b22;strokeColor=#d29922;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="310" y="348" width="340" height="85" as="geometry"/>
</mxCell>
<mxCell id="f2-react-label" value="🔄 ReAct 推理循环" style="text;fontSize=11;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#d29922;align=center;" vertex="1" parent="1">
<mxGeometry x="400" y="350" width="160" height="18" as="geometry"/>
</mxCell>
<mxCell id="f2-think" value="Think&#xa;(LLM 推理决策)" style="rounded=1;fillColor=#2d2a16;strokeColor=#d29922;fontColor=#d29922;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="325" y="373" width="100" height="40" as="geometry"/>
</mxCell>
<mxCell id="f2-ra1" style="endArrow=classic;strokeColor=#d29922;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="425" y="393" as="sourcePoint"/>
<mxPoint x="455" y="393" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-toolcall" value="Tool Call&#xa;(执行工具函数)" style="rounded=1;fillColor=#2d2a16;strokeColor=#d29922;fontColor=#d29922;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="458" y="373" width="100" height="40" as="geometry"/>
</mxCell>
<mxCell id="f2-ra2" style="endArrow=classic;strokeColor=#d29922;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="558" y="393" as="sourcePoint"/>
<mxPoint x="588" y="393" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-observe" value="Observe&#xa;(分析工具结果)" style="rounded=1;fillColor=#2d2a16;strokeColor=#d29922;fontColor=#d29922;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="591" y="373" width="100" height="40" as="geometry"/>
</mxCell>
<!-- Loop back arrow -->
<mxCell id="f2-loop" style="endArrow=classic;strokeColor=#d29922;strokeWidth=1;dashed=1;curved=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="641" y="413" as="sourcePoint"/>
<mxPoint x="375" y="413" as="targetPoint"/>
<Array as="points">
<mxPoint x="641" y="430"/>
<mxPoint x="375" y="430"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="f2-loop-label" value="需要更多信息则继续循环" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#8b949e;align=center;" vertex="1" parent="1">
<mxGeometry x="415" y="425" width="140" height="12" as="geometry"/>
</mxCell>
<!-- 4 Tools box -->
<mxCell id="f2-tools" value="" style="rounded=1;fillColor=#161b22;strokeColor=#8957e5;strokeWidth=1;dashed=1;" vertex="1" parent="1">
<mxGeometry x="680" y="278" width="250" height="120" as="geometry"/>
</mxCell>
<mxCell id="f2-tools-label" value="4 个 KG 检索工具" style="text;fontSize=11;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#8957e5;align=center;" vertex="1" parent="1">
<mxGeometry x="730" y="282" width="150" height="16" as="geometry"/>
</mxCell>
<mxCell id="f2-t1" value="🔍 search_entities" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="695" y="303" width="105" height="22" as="geometry"/>
</mxCell>
<mxCell id="f2-t2" value="🔗 get_neighbors" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="810" y="303" width="105" height="22" as="geometry"/>
</mxCell>
<mxCell id="f2-t3" value="📋 get_entities_by_type" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="695" y="332" width="105" height="22" as="geometry"/>
</mxCell>
<mxCell id="f2-t4" value="📊 describe_graph" style="rounded=1;fillColor=#21262d;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="810" y="332" width="105" height="22" as="geometry"/>
</mxCell>
<mxCell id="f2-tools-note" value="基于 NetworkX 本地计算,无 API 调用" style="text;fontSize=8;fillColor=none;strokeColor=none;fontColor=#484f58;align=center;" vertex="1" parent="1">
<mxGeometry x="695" y="360" width="220" height="12" as="geometry"/>
</mxCell>
<!-- Final output row -->
<mxCell id="f2-down2" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=2;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="480" y="433" as="sourcePoint"/>
<mxPoint x="480" y="438" as="targetPoint"/>
<mxPoint as="array"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-out" value="提取最终答案 + 工具调用链 + 引用节点" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="330" y="440" width="220" height="30" as="geometry"/>
</mxCell>
<mxCell id="f2-a4" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="550" y="455" as="sourcePoint"/>
<mxPoint x="690" y="455" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f2-render" value="前端渲染&#xa;Markdown 答案&#xa;+ ToolCall 面板&#xa;+ Cited Node 标签" style="rounded=1;fillColor=#0d3320;strokeColor=#3fb950;fontColor=#f0f6fc;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="693" y="438" width="130" height="50" as="geometry"/>
</mxCell>
<!-- Save history note -->
<mxCell id="f2-save" value="💾 保存到 query_history.jsonl" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#8b949e;align=left;" vertex="1" parent="1">
<mxGeometry x="26" y="345" width="200" height="14" as="geometry"/>
</mxCell>
<!-- ===================================================================== -->
<!-- FLOW 3: 多模式搜索 -->
<!-- ===================================================================== -->
<mxCell id="f3-bg" value="" style="rounded=1;fillColor=#0d1117;strokeColor=#8957e5;strokeWidth=1;dashed=1;opacity=40;" vertex="1" parent="1">
<mxGeometry x="10" y="455" width="930" height="165" as="geometry"/>
</mxCell>
<mxCell id="f3-label" value="流程三:多模式实体搜索" style="text;fontSize=13;fontStyle=1;fillColor=none;strokeColor=none;fontColor=#8957e5;align=left;" vertex="1" parent="1">
<mxGeometry x="20" y="458" width="250" height="20" as="geometry"/>
</mxCell>
<!-- Search input -->
<mxCell id="f3-input" value="🔎 用户输入搜索" style="rounded=1;fillColor=#1c1830;strokeColor=#8957e5;fontColor=#f0f6fc;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="25" y="488" width="120" height="34" as="geometry"/>
</mxCell>
<mxCell id="f3-sel" value="选择搜索模式" style="rhombus;fillColor=#1c1830;strokeColor=#8957e5;fontColor=#bc8cff;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="165" y="480" width="80" height="50" as="geometry"/>
</mxCell>
<mxCell id="f3-a0" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="145" y="505" as="sourcePoint"/>
<mxPoint x="162" y="505" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Mode 1: Entity Search -->
<mxCell id="f3-m1" value="Entity Search&#xa;GET /search/entities" style="rounded=1;fillColor=#1c1830;strokeColor=#58a6ff;fontColor=#58a6ff;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="270" y="488" width="135" height="34" as="geometry"/>
</mxCell>
<mxCell id="f3-a1" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1.5;exitX=0.8;exitY=0.2;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="229" y="488" as="sourcePoint"/>
<mxPoint x="267" y="495" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="f3-m1r" value="实体列表 +&#xa;1-hop 预览图" style="rounded=1;fillColor=#1c1830;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="270" y="535" width="135" height="30" as="geometry"/>
</mxCell>
<mxCell id="f3-ma1" style="endArrow=classic;strokeColor=#58a6ff;strokeWidth=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="337" y="522" as="sourcePoint"/>
<mxPoint x="337" y="532" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Mode 2: Path Search -->
<mxCell id="f3-m2" value="Path Search&#xa;GET /search/path" style="rounded=1;fillColor=#1c1830;strokeColor=#3fb950;fontColor=#3fb950;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="425" y="488" width="135" height="34" as="geometry"/>
</mxCell>
<mxCell id="f3-a2" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1.5;exitX=0.5;exitY=0.2;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="205" y="488" as="sourcePoint"/>
<mxPoint x="422" y="495" as="targetPoint"/>
<Array as="points">
<mxPoint x="422" y="488"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="f3-m2r" value="路径链可视&#xa;+ 文字描述" style="rounded=1;fillColor=#1c1830;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="425" y="535" width="135" height="30" as="geometry"/>
</mxCell>
<mxCell id="f3-ma2" style="endArrow=classic;strokeColor=#3fb950;strokeWidth=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="492" y="522" as="sourcePoint"/>
<mxPoint x="492" y="532" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Mode 3: Graph Search -->
<mxCell id="f3-m3" value="Graph Search&#xa;GET /search/graph" style="rounded=1;fillColor=#1c1830;strokeColor=#ff7b72;fontColor=#ff7b72;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="580" y="488" width="135" height="34" as="geometry"/>
</mxCell>
<mxCell id="f3-a3" style="endArrow=classic;strokeColor=#8957e5;strokeWidth=1.5;exitX=1;exitY=0.8;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="245" y="520" as="sourcePoint"/>
<mxPoint x="577" y="505" as="targetPoint"/>
<Array as="points">
<mxPoint x="577" y="520"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="f3-m3r" value="D3 子图渲染&#xa;+ 匹配节点列表" style="rounded=1;fillColor=#1c1830;strokeColor=#ff7b72;fontColor=#c9d1d9;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="580" y="535" width="135" height="30" as="geometry"/>
</mxCell>
<mxCell id="f3-ma3" style="endArrow=classic;strokeColor=#ff7b72;strokeWidth=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="647" y="522" as="sourcePoint"/>
<mxPoint x="647" y="532" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Cross-page navigation -->
<mxCell id="f3-nav" value="跨页面联动" style="rounded=1;fillColor=#2d2a16;strokeColor=#d29922;fontColor=#f0f6fc;fontSize=10;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="760" y="488" width="120" height="34" as="geometry"/>
</mxCell>
<mxCell id="f3-nav-detail" value="[View KG] → #/graph?node=id&#xa;[Chat] → #/chat?q=xxx" style="rounded=1;fillColor=#2d2a16;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=9;" vertex="1" parent="1">
<mxGeometry x="740" y="535" width="160" height="30" as="geometry"/>
</mxCell>
<mxCell id="f3-nav-a" style="endArrow=classic;strokeColor=#d29922;strokeWidth=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="820" y="522" as="sourcePoint"/>
<mxPoint x="820" y="532" as="targetPoint"/>
</mxGeometry>
</mxCell>
<!-- Global search note -->
<mxCell id="f3-global" value="🔍 Header 全局搜索框 (debounce 300ms) → GET /search/entities → 实时建议下拉 → 跳转" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#8b949e;align=left;" vertex="1" parent="1">
<mxGeometry x="25" y="578" width="450" height="14" as="geometry"/>
</mxCell>
<!-- Tech stack footer -->
<mxCell id="flow-footer" value="3 条核心流程 | 25 个 REST API 端点 | 后台线程异步索引 | ReAct Agent 多步推理 | 前端轮询 3s/10s | 跨页面 Hash 路由联动" style="text;fontSize=9;fillColor=none;strokeColor=none;fontColor=#484f58;align=center;" vertex="1" parent="1">
<mxGeometry x="60" y="605" width="700" height="16" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>