anhuiqiang il y a 19 heures
Parent
commit
bf839a88e4
4 fichiers modifiés avec 2510 ajouts et 0 suppressions
  1. 119 0
      README_ZH.md
  2. 831 0
      docs/military-simulation-ai-solution.html
  3. 779 0
      docs/system-overview-zh.html
  4. 781 0
      docs/system-overview.html

+ 119 - 0
README_ZH.md

@@ -0,0 +1,119 @@
+# AuraK:企业级全栈智能 AI 知识平台
+
+AuraK 是一个基于 **React 19** 与 **NestJS** 构建的现代化企业级 AI 知识库与人才评价系统。它不仅提供了高度可扩展的 RAG(检索增强生成)能力,还深度集成了多租户管理、交互式评价工作流及飞书办公生态。
+
+---
+
+## ✨ 核心特性
+
+### 🔐 企业级多租户与权限
+- **租户隔离**:严格的数据与资源租户级物理隔离,支持独立域名/子域名挂载。
+- **RBAC 权限管理**:预置超级管理员、租户管理员、普通用户等多种角色。
+- **成员管理**:支持租户内成员邀请、权限分配与配额限制。
+
+### 📚 智能知识路由与管理
+- **层级化分组**:支持知识库文件的文件夹式层级管理(Knowledge Groups),轻松应对海量文档。
+- **双模式处理流水线**:
+    - **快速模式 (Fast)**:基于 Apache Tika,极速提取海量纯文本。
+    - **高精度模式 (High-Precision)**:集成了 **Vision Pipeline**,利用多模态模型识别复杂 PDF/图片中的图文混合内容。
+- **格式全支持**:原生支持 PDF, Word, PPT, Excel, TXT, Markdown 以及各类图片格式。
+
+### 📊 交互式人才评价 (Assessment)
+- **LangGraph 工作流**:基于图结构的 AI 对话逻辑,实现逻辑严密的自动化面试与素质评价。
+- **落地式出题 (Grounded Q&A)**:基于 RAG 技术,从自有知识库中根据关键词精准提取素材生成专业题目。
+- **加权智能评分**:支持 Standard (1.0), Advanced (1.5), Specialist (2.0) 三级难度权重的自动化综合评分。
+- **多语言评价**:支持中、英、日三语同步测评。
+
+### 🤖 深度飞书办公集成
+- **免公网 WebSocket 机器人**:支持通过飞书长连接(WebSocket)直接接入企业内网,无需公网 IP 或域名映射。
+- **互动消息卡片**:在飞书中实时展示 AI 思考过程、检索来源及测评进度。
+- **移动端评价**:用户可直接在飞书聊天窗口完成完整的人才评价流程。
+
+### 🚀 高级 RAG 性能优化
+- **混合检索 (Hybrid Search)**:结合 Elasticsearch 的 BM25 关键词检索与高维度向量检索,大幅提升首选片段准确率。
+- **智能重排序 (Rerank)**:内置 Rerank 模型二次校验,确保生成内容的真实性与相关性。
+- **SSE 流式响应**:秒级首屏响应,实时展示知识检索状态与生成进度。
+
+### 🛠️ 生产力增强工具
+- **播客生成 (Podcasts)**:一键将长文档转化为播客形式的音频摘要。
+- **智能笔记 (Notes)**:支持对知识库内容记录分类笔记。
+- **搜索历史溯源**:完整的聊天历史记录与引用文档回溯。
+
+---
+
+## 🏗️ 技术架构
+
+### 前端 (Web)
+- **核心**:React 19 + TypeScript + Vite
+- **UI/样式**:Tailwind CSS + Lucide React
+- **交互**:React Context + SSE Streaming + Framer Motion (微动画)
+
+### 后端 (Server)
+- **框架**:NestJS (Node.js) + TypeScript
+- **AI 引擎**:LangChain + **LangGraph** (评价工作流)
+- **存储**:SQLite (元数据) + **Elasticsearch** (向量与全文检索)
+- **处理层**:Apache Tika + Vision Pipeline + LibreOffice (文档转换)
+- **通信**:Feishu WebSocket Manager + SSE
+
+---
+
+## 🏢 内网部署支持
+
+AuraK 专为私有化部署设计:
+- **资源本地化**:KaTeX、字体等静态资源完全本地化,无需访问 CDN。
+- **私有模型接入**:支持接入各类 OpenAI 兼容格式的内网私有化模型服务。
+- **容器化部署**:提供完整的 Docker Compose 一键启动方案,支持私有镜像仓库。
+
+详细指南请参考 [内网部署手册](INTERNAL_DEPLOYMENT_GUIDE.md)。
+
+---
+
+## 🚀 快速开始
+
+### 1. 准备工作
+- Node.js 18+
+- Yarn
+- Docker & Docker Compose
+
+### 2. 克隆与安装
+```bash
+git clone <repository-url>
+cd auraAuraK
+yarn install
+```
+
+### 3. 启动周边服务
+```bash
+docker-compose up -d elasticsearch tika libreoffice
+```
+
+### 4. 环境配置
+分别修改 `server/.env` 和 `web/.env`。
+
+### 5. 启动项目
+```bash
+yarn dev
+```
+访问 `http://localhost:5173` 开始体验!
+
+---
+
+## 📁 项目目录
+```
+auraAuraK/
+├── web/                    # 前端 React 应用
+├── server/                 # 后端 NestJS 应用
+│   ├── src/
+│   │   ├── tenant/         # 多租户管理
+│   │   ├── assessment/     # 合才评价 (LangGraph)
+│   │   ├── feishu/         # 飞书集成
+│   │   ├── knowledge-group/# 知识库分组
+│   │   └── chat/           # RAG 核心逻辑
+├── docs/                   # 技术方案与 API 文档
+└── docker-compose.yml      # 全栈部署配置
+```
+
+---
+
+## 📄 开源协议
+本项目采用 MIT 协议。详见 [LICENSE](LICENSE) 文件。

+ 831 - 0
docs/military-simulation-ai-solution.html

@@ -0,0 +1,831 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>军事仿真 AI 原生解决方案</title>
+  <style>
+    :root {
+      --bg: #0f1117;
+      --surface: #1a1d27;
+      --surface2: #232736;
+      --border: #2e3348;
+      --text: #e2e4ed;
+      --text-dim: #8b8fa3;
+      --accent: #6c8cff;
+      --accent2: #a78bfa;
+      --green: #34d399;
+      --orange: #fb923c;
+      --red: #f87171;
+      --cyan: #22d3ee;
+      --yellow: #fbbf24;
+    }
+    * { margin: 0; padding: 0; box-sizing: border-box; }
+    body {
+      font-family: -apple-system, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
+      background: var(--bg);
+      color: var(--text);
+      line-height: 1.7;
+      padding: 0;
+    }
+
+    /* Header */
+    .hero {
+      background: linear-gradient(135deg, #1e1b4b 0%, #0f172a 50%, #0c1220 100%);
+      border-bottom: 1px solid var(--border);
+      padding: 80px 40px 60px;
+      text-align: center;
+      position: relative;
+      overflow: hidden;
+    }
+    .hero::before {
+      content: '';
+      position: absolute;
+      top: -50%;
+      left: -50%;
+      width: 200%;
+      height: 200%;
+      background: radial-gradient(circle at 30% 50%, rgba(108,140,255,0.08) 0%, transparent 50%),
+                  radial-gradient(circle at 70% 50%, rgba(167,139,250,0.06) 0%, transparent 50%);
+    }
+    .hero h1 {
+      font-size: 2.6em;
+      font-weight: 700;
+      background: linear-gradient(135deg, var(--accent), var(--accent2));
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+      position: relative;
+      margin-bottom: 12px;
+    }
+    .hero .subtitle {
+      color: var(--text-dim);
+      font-size: 1.15em;
+      position: relative;
+    }
+
+    /* Layout */
+    .container {
+      max-width: 1200px;
+      margin: 0 auto;
+      padding: 0 32px;
+    }
+
+    /* Pipeline overview */
+    .pipeline {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 0;
+      padding: 48px 0 24px;
+      flex-wrap: wrap;
+    }
+    .pipeline-node {
+      background: var(--surface);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 18px 28px;
+      text-align: center;
+      min-width: 140px;
+      transition: border-color 0.2s;
+    }
+    .pipeline-node:hover { border-color: var(--accent); }
+    .pipeline-node .step-num {
+      display: inline-block;
+      width: 28px; height: 28px;
+      border-radius: 50%;
+      background: var(--accent);
+      color: #fff;
+      font-size: 0.8em;
+      font-weight: 700;
+      line-height: 28px;
+      margin-bottom: 6px;
+    }
+    .pipeline-node .label { font-weight: 600; font-size: 1em; }
+    .pipeline-node .sub { color: var(--text-dim); font-size: 0.82em; }
+    .pipeline-arrow {
+      color: var(--text-dim);
+      font-size: 1.4em;
+      padding: 0 8px;
+      user-select: none;
+    }
+
+    /* Sections */
+    section {
+      margin: 48px 0;
+    }
+    .section-header {
+      display: flex;
+      align-items: center;
+      gap: 14px;
+      margin-bottom: 24px;
+      padding-bottom: 12px;
+      border-bottom: 1px solid var(--border);
+    }
+    .section-header .icon {
+      width: 42px; height: 42px;
+      border-radius: 10px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 1.3em;
+      flex-shrink: 0;
+    }
+    .section-header h2 {
+      font-size: 1.55em;
+      font-weight: 700;
+    }
+    .section-header .tag {
+      font-size: 0.78em;
+      padding: 3px 10px;
+      border-radius: 20px;
+      font-weight: 600;
+    }
+
+    /* Cards grid */
+    .cards {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+      gap: 16px;
+    }
+    .card {
+      background: var(--surface);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 22px;
+      transition: border-color 0.2s, transform 0.15s;
+    }
+    .card:hover {
+      border-color: var(--accent);
+      transform: translateY(-2px);
+    }
+    .card h4 {
+      font-size: 0.95em;
+      margin-bottom: 6px;
+      display: flex;
+      align-items: center;
+      gap: 8px;
+    }
+    .card p {
+      color: var(--text-dim);
+      font-size: 0.88em;
+      line-height: 1.6;
+    }
+
+    /* Diagram box */
+    .diagram-box {
+      background: var(--surface2);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 32px;
+      margin-top: 20px;
+      overflow-x: auto;
+    }
+    .diagram-box pre {
+      font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace;
+      font-size: 0.82em;
+      line-height: 1.65;
+      color: var(--cyan);
+      white-space: pre;
+      margin: 0;
+    }
+
+    /* Table */
+    .data-table {
+      width: 100%;
+      border-collapse: collapse;
+      margin-top: 16px;
+    }
+    .data-table th {
+      text-align: left;
+      padding: 12px 16px;
+      background: var(--surface2);
+      border-bottom: 1px solid var(--border);
+      font-size: 0.85em;
+      color: var(--text-dim);
+      font-weight: 600;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+    }
+    .data-table td {
+      padding: 12px 16px;
+      border-bottom: 1px solid var(--border);
+      font-size: 0.9em;
+    }
+    .data-table tr:hover td { background: rgba(108,140,255,0.04); }
+
+    /* Tags */
+    .tag-blue { background: rgba(108,140,255,0.15); color: var(--accent); }
+    .tag-purple { background: rgba(167,139,250,0.15); color: var(--accent2); }
+    .tag-green { background: rgba(52,211,153,0.15); color: var(--green); }
+    .tag-orange { background: rgba(251,146,60,0.15); color: var(--orange); }
+    .tag-cyan { background: rgba(34,211,238,0.15); color: var(--cyan); }
+    .tag-yellow { background: rgba(251,191,36,0.15); color: var(--yellow); }
+
+    .icon-blue { background: rgba(108,140,255,0.12); }
+    .icon-purple { background: rgba(167,139,250,0.12); }
+    .icon-green { background: rgba(52,211,153,0.12); }
+    .icon-orange { background: rgba(251,146,60,0.12); }
+    .icon-cyan { background: rgba(34,211,238,0.12); }
+    .icon-yellow { background: rgba(251,191,36,0.12); }
+    .icon-red { background: rgba(248,113,113,0.12); }
+
+    /* Code block */
+    code {
+      font-family: "JetBrains Mono", "Fira Code", monospace;
+      background: var(--surface2);
+      padding: 2px 7px;
+      border-radius: 4px;
+      font-size: 0.88em;
+      color: var(--cyan);
+    }
+
+    /* Callout */
+    .callout {
+      background: rgba(108,140,255,0.06);
+      border-left: 3px solid var(--accent);
+      border-radius: 0 10px 10px 0;
+      padding: 20px 24px;
+      margin-top: 20px;
+    }
+    .callout strong { color: var(--accent); }
+    .callout p { color: var(--text-dim); font-size: 0.92em; margin-top: 6px; }
+
+    /* Roadmap */
+    .roadmap {
+      display: grid;
+      grid-template-columns: repeat(3, 1fr);
+      gap: 20px;
+      margin-top: 16px;
+    }
+    .roadmap-item {
+      background: var(--surface);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 24px;
+      position: relative;
+      overflow: hidden;
+    }
+    .roadmap-item::before {
+      content: attr(data-phase);
+      position: absolute;
+      top: 0; left: 0; right: 0;
+      height: 3px;
+    }
+    .roadmap-item h4 {
+      font-size: 1.05em;
+      margin-bottom: 8px;
+    }
+    .roadmap-item ul {
+      list-style: none;
+      padding: 0;
+    }
+    .roadmap-item li {
+      color: var(--text-dim);
+      font-size: 0.88em;
+      padding: 3px 0;
+      padding-left: 16px;
+      position: relative;
+    }
+    .roadmap-item li::before {
+      content: '›';
+      position: absolute;
+      left: 0;
+      color: var(--accent);
+      font-weight: 700;
+    }
+
+    /* Flow diagram with SVG-like CSS */
+    .flow-section {
+      background: var(--surface);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 28px;
+      margin-top: 16px;
+    }
+    .flow-row {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 12px;
+      flex-wrap: wrap;
+    }
+    .flow-box {
+      border-radius: 10px;
+      padding: 14px 22px;
+      text-align: center;
+      font-size: 0.88em;
+      font-weight: 600;
+      min-width: 120px;
+      border: 1px solid var(--border);
+    }
+    .flow-arrow {
+      color: var(--text-dim);
+      font-size: 1.2em;
+    }
+
+    /* Footer */
+    .footer {
+      text-align: center;
+      padding: 40px;
+      color: var(--text-dim);
+      font-size: 0.82em;
+      border-top: 1px solid var(--border);
+      margin-top: 60px;
+    }
+
+    /* Responsive */
+    @media (max-width: 768px) {
+      .hero { padding: 48px 20px 36px; }
+      .hero h1 { font-size: 1.8em; }
+      .container { padding: 0 16px; }
+      .pipeline { gap: 4px; }
+      .pipeline-node { min-width: 100px; padding: 12px 14px; }
+      .pipeline-arrow { font-size: 1em; padding: 0 4px; }
+      .roadmap { grid-template-columns: 1fr; }
+      .diagram-box pre { font-size: 0.72em; }
+    }
+  </style>
+</head>
+<body>
+
+  <!-- Hero -->
+  <div class="hero">
+    <h1>军事仿真 AI 原生解决方案</h1>
+    <div class="subtitle">场景 → 想定 → 方案 → 推演 → 评估 · 端到端闭环智能体系</div>
+  </div>
+
+  <div class="container">
+
+    <!-- Pipeline Overview -->
+    <div class="pipeline">
+      <div class="pipeline-node">
+        <div class="step-num">1</div>
+        <div class="label">场景构建</div>
+        <div class="sub">Scene Construction</div>
+      </div>
+      <span class="pipeline-arrow">→</span>
+      <div class="pipeline-node">
+        <div class="step-num">2</div>
+        <div class="label">想定生成</div>
+        <div class="sub">Wargaming Scenario</div>
+      </div>
+      <span class="pipeline-arrow">→</span>
+      <div class="pipeline-node">
+        <div class="step-num">3</div>
+        <div class="label">方案生成</div>
+        <div class="sub">Plan Generation</div>
+      </div>
+      <span class="pipeline-arrow">→</span>
+      <div class="pipeline-node">
+        <div class="step-num">4</div>
+        <div class="label">仿真推演</div>
+        <div class="sub">Simulation Run</div>
+      </div>
+      <span class="pipeline-arrow">→</span>
+      <div class="pipeline-node">
+        <div class="step-num">5</div>
+        <div class="label">仿真评估</div>
+        <div class="sub">Assessment</div>
+      </div>
+    </div>
+
+    <!-- ========== 1. 场景构建 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-blue"> </div>
+        <h2>一、场景构建</h2>
+        <span class="tag tag-blue">Scene Construction</span>
+      </div>
+      <p style="color:var(--text-dim);margin-bottom:16px;">构建战场环境,涵盖地理、气象、电磁、基础设施等多维态势。核心目标:<strong>用自然语言快速生成结构化战场场景</strong>。</p>
+
+      <div class="cards">
+        <div class="card">
+          <h4><span class="tag tag-blue">NLP</span> 自然语言 → 场景</h4>
+          <p>LLM 将 "红蓝双方在东海某海域对峙,气象条件 XX" 解析为结构化场景参数 (JSON / DSL)</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-purple">Vision</span> 地理环境生成</h4>
+          <p>多模态模型从卫星图 / 地图自动提取地形特征、道路网络、关键地标</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-green">RAG</span> 场景模板推荐</h4>
+          <p>基于历史场景库做 RAG 检索,推荐相似场景作为起点,降低构建成本</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-orange">Validate</span> 一致性校验</h4>
+          <p>LLM + 规则引擎联合检查参数矛盾,如海拔与水深冲突、时间线逻辑错误</p>
+        </div>
+      </div>
+
+      <div class="diagram-box">
+<pre>
+  [自然语言输入]
+       │
+       ▼
+  [场景 DSL 生成器 (LLM)]
+       │
+       ▼
+  [场景参数 JSON Schema] ──→ [场景渲染引擎 (3D / GIS)]
+       │
+       ▼
+  [一致性校验 (规则 + LLM)]
+       │
+       ▼
+  [结构化场景定义]
+</pre>
+      </div>
+    </section>
+
+    <!-- ========== 2. 想定生成 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-purple">⚔️</div>
+        <h2>二、想定生成</h2>
+        <span class="tag tag-purple">Wargaming Scenario</span>
+      </div>
+      <p style="color:var(--text-dim);margin-bottom:16px;">在场景基础上定义双方作战目标、兵力编成、交战规则 (ROE)、时间线。核心创新:<strong>红蓝对抗博弈 Agent 自动迭代生成想定</strong>。</p>
+
+      <div class="cards">
+        <div class="card">
+          <h4><span class="tag tag-blue">Generate</span> 想定自动生成</h4>
+          <p>LLM 基于场景 + 作战意图,生成结构化想定:兵力部署、阶段划分、ROE 规则</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-red">Game</span> 对抗性博弈</h4>
+          <p>红蓝两个 Agent 各自独立生成意图,通过多轮对抗迭代完善想定</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-green">Review</span> 合理性评估</h4>
+          <p>战术知识库 RAG + LLM 审查,标注兵力不足、后勤断链等风险点</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-cyan">Version</span> 版本管理</h4>
+          <p>每次修改生成 diff,支持分支 / 合并,类 Git 的想定版本管理</p>
+        </div>
+      </div>
+
+      <div class="diagram-box">
+<pre>
+        场景描述 + 红方目标
+              │
+              ▼
+  ┌─────────────────────────┐
+  │    Red Agent (LLM)       │ ← 战术知识库 (RAG)
+  │   生成红方兵力部署方案     │
+  └───────────┬─────────────┘
+              ▼
+  ┌─────────────────────────┐
+  │    Blue Agent (LLM)      │ ← 战术知识库 (RAG)
+  │   针对红方部署制定对策     │
+  └───────────┬─────────────┘
+              ▼
+  ┌─────────────────────────┐
+  │    Referee Agent         │
+  │   平衡性审查 + 冲突标注    │
+  └───────────┬─────────────┘
+              ▼
+         最终想定文档
+</pre>
+      </div>
+    </section>
+
+    <!-- ========== 3. 方案生成 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-green"> </div>
+        <h2>三、方案生成</h2>
+        <span class="tag tag-green">Plan Generation</span>
+      </div>
+      <p style="color:var(--text-dim);margin-bottom:16px;">基于想定为各作战单元生成具体行动计划。核心价值:<strong>多方案并行生成 + 量化比较,突破人工只能覆盖少数方案的局限</strong>。</p>
+
+      <div class="cards">
+        <div class="card">
+          <h4><span class="tag tag-blue">Ensemble</span> 多方案并行</h4>
+          <p>LLM + 规划算法 (HTN / MCTS) 并行输出 3-5 个差异化方案,覆盖不同战术风格</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-yellow">Score</span> 多维评价打分</h4>
+          <p>风险、时效、资源消耗、达成概率等维度自动评分,附 LLM 解释</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-purple">Merge</span> 方案对比与融合</h4>
+          <p>LLM 对多方案做优劣势分析,可融合不同方案的优点生成复合方案</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-cyan">HITL</span> 人在回路修正</h4>
+          <p>指挥员用自然语言修改方案,LLM 实时调整并反馈级联影响</p>
+        </div>
+      </div>
+
+      <div class="diagram-box">
+<pre>
+  想定 + 约束条件
+       │
+       ▼
+  ┌────────────────────────────────────────┐
+  │          Plan Generator Ensemble        │
+  │  ┌──────────┐ ┌──────────┐ ┌─────────┐│
+  │  │ 方案 A    │ │ 方案 B    │ │ 方案 C   ││
+  │  │(激进突防) │ │(稳健推进) │ │(迂回包围)││
+  │  └─────┬────┘ └─────┬────┘ └────┬────┘│
+  │        └────────────┼───────────┘     │
+  │                     ▼                  │
+  │           Plan Evaluator               │
+  │      (多维度打分 + LLM 解释)            │
+  └─────────────────────┬──────────────────┘
+                        ▼
+           排序推荐 + 可视化对比
+</pre>
+      </div>
+
+      <div class="callout">
+        <strong>方案 DSL 示例</strong>
+        <p>每个方案以结构化 YAML 描述,包含阶段、兵力、行动指令,便于 LLM 生成、校验和推演引擎执行。</p>
+      </div>
+
+      <div class="diagram-box" style="margin-top:12px;">
+<pre>
+plan_id: PLAN-2026-0320-A
+name: "东海封锁作战方案 A — 激进突防"
+phases:
+  - phase: 1
+    name: "电子压制"
+    start_time: T+0
+    units: [EW-01, EW-02]
+    actions:
+      - type: jamming
+        target: enemy_radar_net
+        power: high
+  - phase: 2
+    name: "第一波突击"
+    start_time: T+00:30
+    units: [AIR-01, AIR-02, NAV-01]
+    actions:
+      - type: strike
+        target: port_facility_A
+        weapon: cruise_missile
+        quantity: 12
+</pre>
+      </div>
+    </section>
+
+    <!-- ========== 4. 仿真推演 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-orange"> </div>
+        <h2>四、仿真推演</h2>
+        <span class="tag tag-orange">Simulation Execution</span>
+      </div>
+      <p style="color:var(--text-dim);margin-bottom:16px;">按方案驱动各作战单元在仿真环境中执行,产生时序态势数据。核心创新:<strong>每个作战单元挂载 LLM Agent,自主感知-决策-行动</strong>。</p>
+
+      <div class="cards">
+        <div class="card">
+          <h4><span class="tag tag-blue">Agent</span> 智能体行为决策</h4>
+          <p>每个作战单元挂载 LLM Agent,根据实时态势自主决策,非脚本化行为树</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-green">Adaptive</span> 自适应仿真步长</h4>
+          <p>战斗激烈区域用小步长,平静区域用大步长,AI 动态调度提升仿真效率</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-yellow">Inject</span> 意外事件注入</h4>
+          <p>LLM 作为 "战局导演",在关键节点注入意外事件,考验方案鲁棒性</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-cyan">Monitor</span> 实时态势理解</h4>
+          <p>推演过程中 LLM 持续解读态势,自动生成态势报告与异常告警</p>
+        </div>
+      </div>
+
+      <div class="diagram-box">
+<pre>
+  ┌──────────────────────────────────────────────────┐
+  │               Simulation Engine                   │
+  │                                                    │
+  │   ┌────────────┐  ┌────────────┐  ┌────────────┐ │
+  │   │ Unit Agent  │  │ Unit Agent  │  │ Unit Agent  ││
+  │   │  (驱逐舰)   │  │  (战斗机)   │  │  (雷达站)   ││
+  │   │            │  │            │  │            │ │
+  │   │  观测→推理  │  │  观测→推理  │  │  观测→推理  │ │
+  │   │  →决策→行动 │  │  →决策→行动 │  │  →决策→行动 │ │
+  │   └──────┬─────┘  └──────┬─────┘  └──────┬─────┘ │
+  │          └───────────────┼───────────────┘        │
+  │                          ▼                         │
+  │               态势融合与冲突仲裁                      │
+  │                          ▼                         │
+  │               仿真时间推进                           │
+  └──────────────────────────┬─────────────────────────┘
+                             ▼
+                  时序态势数据流 (SSE)
+</pre>
+      </div>
+
+      <div class="callout">
+        <strong>Unit Agent 决策循环</strong>
+        <p>每个 Agent 遵循 <code>观测 (Observe) → 推理 (Reason) → 决策 (Decide) → 行动 (Act)</code> 循环,输出可审计的决策链,支持事后复盘分析。</p>
+      </div>
+
+      <div class="diagram-box" style="margin-top:12px;">
+<pre>
+UNIT_AGENT_SYSTEM_PROMPT = """
+  你是 {unit_type} {unit_id} 的指挥 AI。
+  当前态势:{current_situation}
+  你的任务:{mission_objective}
+  ROE 规则:{rules_of_engagement}
+  可用武器/资源:{available_resources}
+
+  输出格式:
+    1. 态势判断 — 你观察到了什么
+    2. 决策依据 — 为什么这么做
+    3. 行动指令 — 具体做什么
+    4. 预期结果 — 预计产生什么效果
+"""
+</pre>
+      </div>
+    </section>
+
+    <!-- ========== 5. 仿真评估 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-yellow"> </div>
+        <h2>五、仿真评估</h2>
+        <span class="tag tag-yellow">Assessment</span>
+      </div>
+      <p style="color:var(--text-dim);margin-bottom:16px;">对推演结果进行多维度评估,输出报告,支持方案迭代优化。核心价值:<strong>LLM 自动将海量推演数据转化为可读评估报告 + 可执行的改进建议</strong>。</p>
+
+      <div class="cards">
+        <div class="card">
+          <h4><span class="tag tag-blue">Metrics</span> 多维自动评估</h4>
+          <p>从推演数据自动计算战损比、时间达成率、资源效率、态势控制面积等指标</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-green">Report</span> 自然语言报告</h4>
+          <p>LLM 将指标数据转化为结构化评估报告,含关键节点叙事与图表引用</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-purple">Root Cause</span> 根因分析</h4>
+          <p>LLM 分析关键转折点,构建因果链,追溯胜负根本原因</p>
+        </div>
+        <div class="card">
+          <h4><span class="tag tag-orange">Loop</span> 方案迭代闭环</h4>
+          <p>基于评估结果自动提出改进建议,闭环反馈至方案生成阶段</p>
+        </div>
+      </div>
+
+      <div class="diagram-box">
+<pre>
+  推演时序数据
+       │
+       ▼
+  ┌─────────────────────────┐
+  │   评估指标计算引擎        │
+  │  (战损 / 时间 / 资源 态势)│
+  └───────────┬─────────────┘
+              ▼
+  ┌─────────────────────────┐
+  │   LLM 评估报告生成器     │
+  │   指标 → 叙事 → 图表 → 建议│
+  └───────────┬─────────────┘
+              ▼
+  ┌─────────────────────────┐
+  │   根因分析 Agent         │
+  │   关键节点回溯 + 因果链   │
+  └───────────┬─────────────┘
+              ▼
+  ┌─────────────────────────┐
+  │   方案优化建议           │
+  │   → 反馈至方案生成阶段    │
+  └─────────────────────────┘
+</pre>
+      </div>
+    </section>
+
+    <!-- ========== 端到端架构 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-cyan"> </div>
+        <h2>六、端到端闭环架构</h2>
+        <span class="tag tag-cyan">Full Loop</span>
+      </div>
+
+      <div class="flow-section">
+        <div class="flow-row" style="margin-bottom:20px;">
+          <div class="flow-box" style="border-color:var(--accent);background:rgba(108,140,255,0.08);">场景构建<br><small style="color:var(--text-dim)">LLM 解析 + RAG 模板</small></div>
+          <span class="flow-arrow">→</span>
+          <div class="flow-box" style="border-color:var(--accent2);background:rgba(167,139,250,0.08);">想定生成<br><small style="color:var(--text-dim)">对抗博弈 Agent</small></div>
+          <span class="flow-arrow">→</span>
+          <div class="flow-box" style="border-color:var(--green);background:rgba(52,211,153,0.08);">方案生成<br><small style="color:var(--text-dim)">多方案并行生成</small></div>
+          <span class="flow-arrow">→</span>
+          <div class="flow-box" style="border-color:var(--orange);background:rgba(251,146,60,0.08);">仿真推演<br><small style="color:var(--text-dim)">Agent 化推演引擎</small></div>
+          <span class="flow-arrow">→</span>
+          <div class="flow-box" style="border-color:var(--yellow);background:rgba(251,191,36,0.08);">仿真评估<br><small style="color:var(--text-dim)">LLM 报告 + 根因分析</small></div>
+        </div>
+        <div style="text-align:center;color:var(--text-dim);font-size:0.88em;">
+          <span style="border:1px dashed var(--border);padding:6px 16px;border-radius:20px;">  闭环迭代:评估结果 → 优化建议 → 回到方案生成</span>
+        </div>
+      </div>
+
+      <div class="callout" style="margin-top:24px;">
+        <strong>核心设计哲学</strong>
+        <p>让 LLM 承担 <strong>"认知"</strong> 工作(理解、推理、生成、评估),传统算法承担 <strong>"计算"</strong> 工作(物理仿真、路径规划、优化求解),两者通过结构化 DSL 桥接。这一分层保证了 AI 的创造性与仿真的精确性互不干扰。</p>
+      </div>
+    </section>
+
+    <!-- ========== 技术选型 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-green"> </div>
+        <h2>七、关键技术选型</h2>
+        <span class="tag tag-green">Tech Stack</span>
+      </div>
+
+      <table class="data-table">
+        <thead>
+          <tr>
+            <th>层级</th>
+            <th>技术</th>
+            <th>说明</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr>
+            <td><span class="tag tag-blue">LLM 编排</span></td>
+            <td>LangGraph / 自研 Agent 框架</td>
+            <td>管理多 Agent 协作、状态流转、对话历史</td>
+          </tr>
+          <tr>
+            <td><span class="tag tag-purple">知识库</span></td>
+            <td>Elasticsearch + 向量检索</td>
+            <td>作战条令、战术案例、历史战例的 RAG 索引</td>
+          </tr>
+          <tr>
+            <td><span class="tag tag-orange">仿真引擎</span></td>
+            <td>离散事件仿真 (DES) + Agent 调度</td>
+            <td>战场事件驱动,Agent 自主决策,支持多时间尺度</td>
+          </tr>
+          <tr>
+            <td><span class="tag tag-green">态势存储</span></td>
+            <td>时序 DB (InfluxDB / TDengine)</td>
+            <td>高频态势数据写入与时间范围查询</td>
+          </tr>
+          <tr>
+            <td><span class="tag tag-cyan">可视化</span></td>
+            <td>Cesium (3D GIS) + WebSocket</td>
+            <td>实时态势可视化,支持 2D/3D 切换</td>
+          </tr>
+          <tr>
+            <td><span class="tag tag-yellow">方案 DSL</span></td>
+            <td>YAML / JSON Schema</td>
+            <td>结构化方案描述,便于 LLM 生成、校验和引擎执行</td>
+          </tr>
+        </tbody>
+      </table>
+    </section>
+
+    <!-- ========== 落地路径 ========== -->
+    <section>
+      <div class="section-header">
+        <div class="icon icon-red"> </div>
+        <h2>八、落地路径</h2>
+        <span class="tag tag-orange">Roadmap</span>
+      </div>
+
+      <div class="roadmap">
+        <div class="roadmap-item" data-phase="" style="border-top: 3px solid var(--green);">
+          <h4 style="color:var(--green);">Phase 1 · MVP</h4>
+          <ul>
+            <li>跑通场景→想定→单方案→简单推演→评估的最小闭环</li>
+            <li>LLM 做自然语言到 DSL 的转换</li>
+            <li>基础知识库 RAG 索引(作战条令)</li>
+            <li>脚本化仿真引擎 + 基础指标评估</li>
+          </ul>
+        </div>
+        <div class="roadmap-item" data-phase="" style="border-top: 3px solid var(--accent);">
+          <h4 style="color:var(--accent);">Phase 2 · 增强</h4>
+          <ul>
+            <li>引入红蓝对抗博弈 Agent</li>
+            <li>多方案并行生成 + 量化对比</li>
+            <li>Agent 化推演引擎(自主决策)</li>
+            <li>实时态势可视化 + SSE 推送</li>
+          </ul>
+        </div>
+        <div class="roadmap-item" data-phase="" style="border-top: 3px solid var(--accent2);">
+          <h4 style="color:var(--accent2);">Phase 3 · 成熟</h4>
+          <ul>
+            <li>自适应仿真步长 + 异常检测</li>
+            <li>方案自动迭代优化(评估→改进闭环)</li>
+            <li>跨域多兵种联合作战仿真</li>
+            <li>历史战例深度挖掘与战术知识图谱</li>
+          </ul>
+        </div>
+      </div>
+    </section>
+
+  </div>
+
+  <div class="footer">
+    军事仿真 AI 原生解决方案 · 2026-03-20
+  </div>
+
+</body>
+</html>

+ 779 - 0
docs/system-overview-zh.html

@@ -0,0 +1,779 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Simple Knowledge Base - 系统概览</title>
+  <style>
+    :root {
+      --primary: #6366f1;
+      --primary-light: #818cf8;
+      --primary-dark: #4f46e5;
+      --bg: #0f172a;
+      --bg-card: #1e293b;
+      --bg-code: #0d1117;
+      --text: #e2e8f0;
+      --text-muted: #94a3b8;
+      --border: #334155;
+      --accent-green: #34d399;
+      --accent-blue: #38bdf8;
+      --accent-orange: #fb923c;
+      --accent-pink: #f472b6;
+    }
+
+    * { margin: 0; padding: 0; box-sizing: border-box; }
+
+    body {
+      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
+      background: var(--bg);
+      color: var(--text);
+      line-height: 1.8;
+    }
+
+    .hero {
+      background: linear-gradient(135deg, #1e1b4b 0%, #312e81 30%, #0f172a 70%, #0c0a09 100%);
+      padding: 80px 20px 60px;
+      text-align: center;
+      position: relative;
+      overflow: hidden;
+    }
+
+    .hero::before {
+      content: '';
+      position: absolute;
+      top: -50%;
+      left: -50%;
+      width: 200%;
+      height: 200%;
+      background: radial-gradient(circle at 30% 50%, rgba(99, 102, 241, 0.15) 0%, transparent 50%),
+                  radial-gradient(circle at 70% 50%, rgba(56, 189, 248, 0.1) 0%, transparent 50%);
+      animation: pulse 8s ease-in-out infinite;
+    }
+
+    @keyframes pulse {
+      0%, 100% { opacity: 0.6; }
+      50% { opacity: 1; }
+    }
+
+    .hero h1 {
+      font-size: 2.8rem;
+      font-weight: 800;
+      background: linear-gradient(135deg, #c7d2fe, #818cf8, #38bdf8);
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+      background-clip: text;
+      position: relative;
+      margin-bottom: 12px;
+    }
+
+    .hero .subtitle {
+      font-size: 1.15rem;
+      color: var(--text-muted);
+      position: relative;
+      max-width: 700px;
+      margin: 0 auto;
+    }
+
+    .badge-row {
+      display: flex;
+      gap: 10px;
+      justify-content: center;
+      flex-wrap: wrap;
+      margin-top: 24px;
+      position: relative;
+    }
+
+    .badge {
+      display: inline-flex;
+      align-items: center;
+      gap: 6px;
+      padding: 5px 14px;
+      border-radius: 999px;
+      font-size: 0.82rem;
+      font-weight: 600;
+      border: 1px solid;
+    }
+
+    .badge.react { color: #61dafb; border-color: #61dafb33; background: #61dafb10; }
+    .badge.nest { color: #e0234e; border-color: #e0234e33; background: #e0234e10; }
+    .badge.rag { color: var(--accent-green); border-color: #34d39933; background: #34d39910; }
+    .badge.ts { color: #3178c6; border-color: #3178c633; background: #3178c610; }
+
+    .container {
+      max-width: 1100px;
+      margin: 0 auto;
+      padding: 0 20px;
+    }
+
+    .features-grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+      gap: 20px;
+      margin: -40px auto 60px;
+      position: relative;
+      z-index: 1;
+    }
+
+    .feature-card {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 16px;
+      padding: 28px;
+      transition: transform 0.2s, border-color 0.2s;
+    }
+
+    .feature-card:hover {
+      transform: translateY(-3px);
+      border-color: var(--primary);
+    }
+
+    .feature-card .icon {
+      width: 44px;
+      height: 44px;
+      border-radius: 12px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 1.3rem;
+      margin-bottom: 16px;
+    }
+
+    .feature-card h3 {
+      font-size: 1.05rem;
+      margin-bottom: 8px;
+      color: #f1f5f9;
+    }
+
+    .feature-card p {
+      font-size: 0.9rem;
+      color: var(--text-muted);
+    }
+
+    .icon-blue { background: #38bdf818; }
+    .icon-green { background: #34d39918; }
+    .icon-orange { background: #fb923c18; }
+    .icon-pink { background: #f472b618; }
+    .icon-purple { background: #a78bfa18; }
+    .icon-yellow { background: #fbbf2418; }
+
+    section {
+      margin-bottom: 56px;
+    }
+
+    .section-title {
+      font-size: 1.5rem;
+      font-weight: 700;
+      margin-bottom: 24px;
+      padding-bottom: 12px;
+      border-bottom: 2px solid var(--border);
+      display: flex;
+      align-items: center;
+      gap: 10px;
+    }
+
+    .section-title .num {
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      width: 32px;
+      height: 32px;
+      border-radius: 8px;
+      background: var(--primary);
+      font-size: 0.85rem;
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    /* Architecture Diagram */
+    .arch-diagram {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 16px;
+      padding: 32px;
+      overflow-x: auto;
+    }
+
+    .arch-row {
+      display: flex;
+      justify-content: center;
+      gap: 16px;
+      margin-bottom: 16px;
+      flex-wrap: wrap;
+    }
+
+    .arch-box {
+      padding: 14px 22px;
+      border-radius: 10px;
+      font-size: 0.85rem;
+      font-weight: 600;
+      text-align: center;
+      min-width: 140px;
+      border: 1px solid;
+    }
+
+    .arch-box.frontend { background: #61dafb12; border-color: #61dafb33; color: #61dafb; }
+    .arch-box.backend { background: #e0234e12; border-color: #e0234e33; color: #e0234e; }
+    .arch-box.infra { background: #34d39912; border-color: #34d39933; color: #34d399; }
+    .arch-box.ai { background: #a78bfa12; border-color: #a78bfa33; color: #a78bfa; }
+    .arch-box.data { background: #fb923c12; border-color: #fb923c33; color: #fb923c; }
+
+    .arch-arrow {
+      text-align: center;
+      color: var(--text-muted);
+      font-size: 1.2rem;
+      margin-bottom: 16px;
+    }
+
+    .arch-label {
+      text-align: center;
+      font-size: 0.78rem;
+      color: var(--text-muted);
+      letter-spacing: 1.5px;
+      margin-bottom: 10px;
+    }
+
+    /* File Tree */
+    .file-tree {
+      background: var(--bg-code);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 24px 28px;
+      font-family: 'Cascadia Code', 'Fira Code', monospace;
+      font-size: 0.85rem;
+      line-height: 1.9;
+      overflow-x: auto;
+    }
+
+    .file-tree .dir { color: var(--accent-blue); font-weight: 600; }
+    .file-tree .comment { color: #64748b; font-style: italic; }
+    .file-tree .file { color: var(--text); }
+
+    /* Pipeline */
+    .pipeline {
+      display: flex;
+      align-items: center;
+      gap: 0;
+      flex-wrap: wrap;
+      justify-content: center;
+      margin: 20px 0;
+    }
+
+    .pipeline-step {
+      padding: 12px 20px;
+      border-radius: 10px;
+      font-size: 0.85rem;
+      font-weight: 600;
+      text-align: center;
+      border: 1px solid var(--border);
+      background: var(--bg-card);
+    }
+
+    .pipeline-arrow {
+      color: var(--text-muted);
+      font-size: 1.1rem;
+      padding: 0 6px;
+    }
+
+    .pipeline-step.active {
+      border-color: var(--primary);
+      background: #6366f118;
+      color: var(--primary-light);
+    }
+
+    /* Tables */
+    .info-table {
+      width: 100%;
+      border-collapse: collapse;
+      margin: 12px 0;
+    }
+
+    .info-table th, .info-table td {
+      padding: 10px 16px;
+      text-align: left;
+      border-bottom: 1px solid var(--border);
+      font-size: 0.9rem;
+    }
+
+    .info-table th {
+      color: var(--text-muted);
+      font-weight: 600;
+      font-size: 0.82rem;
+      letter-spacing: 0.5px;
+    }
+
+    .info-table .port {
+      font-family: 'Cascadia Code', monospace;
+      color: var(--accent-orange);
+      font-weight: 600;
+    }
+
+    .info-table .env-key {
+      font-family: 'Cascadia Code', monospace;
+      color: var(--accent-green);
+      font-size: 0.83rem;
+    }
+
+    /* Code Block */
+    .code-block {
+      background: var(--bg-code);
+      border: 1px solid var(--border);
+      border-radius: 10px;
+      padding: 18px 22px;
+      font-family: 'Cascadia Code', 'Fira Code', monospace;
+      font-size: 0.83rem;
+      line-height: 1.8;
+      overflow-x: auto;
+      margin: 12px 0;
+    }
+
+    .code-block .cmd { color: var(--accent-green); }
+    .code-block .comment { color: #64748b; }
+
+    /* Two Column Layout */
+    .two-col {
+      display: grid;
+      grid-template-columns: 1fr 1fr;
+      gap: 24px;
+    }
+
+    @media (max-width: 768px) {
+      .two-col { grid-template-columns: 1fr; }
+      .hero h1 { font-size: 2rem; }
+      .features-grid { grid-template-columns: 1fr; }
+    }
+
+    .card {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 14px;
+      padding: 24px;
+    }
+
+    .card h4 {
+      font-size: 1rem;
+      margin-bottom: 14px;
+      color: #f1f5f9;
+    }
+
+    .card ul {
+      list-style: none;
+      padding: 0;
+    }
+
+    .card ul li {
+      padding: 6px 0;
+      font-size: 0.88rem;
+      color: var(--text-muted);
+      display: flex;
+      align-items: flex-start;
+      gap: 8px;
+    }
+
+    .card ul li::before {
+      content: '›';
+      color: var(--primary-light);
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    .step-list {
+      list-style: none;
+      padding: 0;
+      counter-reset: step;
+    }
+
+    .step-list li {
+      counter-increment: step;
+      padding: 8px 0;
+      font-size: 0.88rem;
+      color: var(--text-muted);
+      display: flex;
+      align-items: flex-start;
+      gap: 10px;
+    }
+
+    .step-list li::before {
+      content: counter(step);
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      width: 22px;
+      height: 22px;
+      border-radius: 6px;
+      background: var(--primary);
+      color: white;
+      font-size: 0.72rem;
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    .troubleshoot-item {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 10px;
+      padding: 16px 20px;
+      margin-bottom: 10px;
+    }
+
+    .troubleshoot-item strong {
+      color: #f1f5f9;
+      font-size: 0.92rem;
+    }
+
+    .troubleshoot-item p {
+      color: var(--text-muted);
+      font-size: 0.85rem;
+      margin-top: 4px;
+    }
+
+    footer {
+      text-align: center;
+      padding: 40px 20px;
+      color: var(--text-muted);
+      font-size: 0.82rem;
+      border-top: 1px solid var(--border);
+    }
+  </style>
+</head>
+<body>
+
+  <!-- Hero -->
+  <div class="hero">
+    <h1>Simple Knowledge Base</h1>
+    <p class="subtitle">全栈 RAG 问答系统 &mdash; 基于 React 19 + NestJS 的检索增强生成技术</p>
+    <div class="badge-row">
+      <span class="badge react">React 19</span>
+      <span class="badge nest">NestJS</span>
+      <span class="badge rag">RAG 系统</span>
+      <span class="badge ts">TypeScript</span>
+    </div>
+  </div>
+
+  <div class="container">
+
+    <!-- 核心特性 -->
+    <div class="features-grid">
+      <div class="feature-card">
+        <div class="icon icon-purple"> </div>
+        <h3>多模型支持</h3>
+        <p>兼容 OpenAI API(OpenAI、DeepSeek、Claude 等)+ Google Gemini 原生 SDK,可配置 LLM、Embedding 和 Rerank 模型。</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-blue">⚡</div>
+        <h3>双处理模式</h3>
+        <p>快速模式通过 Apache Tika 提取文本,高精度模式通过视觉管线处理图文混合文档。</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-green"> </div>
+        <h3>混合检索</h3>
+        <p>基于 Elasticsearch 的向量 + 关键词混合搜索,支持来源引用、相似度评分,可配置分块大小与重叠。</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-orange"> </div>
+        <h3>用户隔离</h3>
+        <p>JWT 认证 + 每用户独立知识库,数据与配置完全隔离,保障隐私安全。</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-pink"> </div>
+        <h3>流式响应</h3>
+        <p>基于 Server-Sent Events (SSE) 的实时流式输出,提供流畅低延迟的对话体验。</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-yellow"> </div>
+        <h3>多语言支持</h3>
+        <p>界面支持日语、中文和英文,错误信息和 API 响应消息全面国际化。</p>
+      </div>
+    </div>
+
+    <!-- 系统架构 -->
+    <section>
+      <h2 class="section-title"><span class="num">1</span> 系统架构概览</h2>
+
+      <div class="arch-diagram">
+        <div class="arch-label">前端层</div>
+        <div class="arch-row">
+          <div class="arch-box frontend">React 19 + Vite<br><small style="opacity:0.7">端口 13001(开发)/ 80(生产)</small></div>
+        </div>
+        <div class="arch-arrow">↕</div>
+        <div class="arch-label">后端层</div>
+        <div class="arch-row">
+          <div class="arch-box backend">NestJS API<br><small style="opacity:0.7">端口 3001</small></div>
+          <div class="arch-box backend">JWT 认证</div>
+          <div class="arch-box backend">对话 / RAG</div>
+          <div class="arch-box backend">视觉管线</div>
+        </div>
+        <div class="arch-arrow">↕</div>
+        <div class="arch-label">AI 与数据层</div>
+        <div class="arch-row">
+          <div class="arch-box ai">OpenAI / Gemini<br><small style="opacity:0.7">LLM + 向量嵌入</small></div>
+          <div class="arch-box infra">Elasticsearch<br><small style="opacity:0.7">端口 9200</small></div>
+          <div class="arch-box infra">Apache Tika<br><small style="opacity:0.7">端口 9998</small></div>
+          <div class="arch-box infra">LibreOffice<br><small style="opacity:0.7">端口 8100</small></div>
+          <div class="arch-box data">SQLite<br><small style="opacity:0.7">元数据存储</small></div>
+        </div>
+      </div>
+
+      <!-- 处理管线 -->
+      <h4 style="margin-top:28px; margin-bottom:14px; color:#f1f5f9;">双处理管线</h4>
+      <div class="two-col">
+        <div class="card">
+          <h4>快速模式(Tika)</h4>
+          <div class="pipeline">
+            <div class="pipeline-step active">上传</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">Tika 提取</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">向量化</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">存储</div>
+          </div>
+          <p style="font-size:0.85rem; color:var(--text-muted); text-align:center;">快速文本提取,无 API 调用成本</p>
+        </div>
+        <div class="card">
+          <h4>高精度模式(视觉管线)</h4>
+          <div class="pipeline">
+            <div class="pipeline-step active">上传</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">LibreOffice</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">PDF 转图片</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">视觉模型</div>
+          </div>
+          <p style="font-size:0.85rem; color:var(--text-muted); text-align:center;">保留原始排版、图表和图片信息</p>
+        </div>
+      </div>
+    </section>
+
+    <!-- 项目结构 -->
+    <section>
+      <h2 class="section-title"><span class="num">2</span> 项目结构</h2>
+      <div class="file-tree">
+        <span class="dir">simple-kb/</span><br>
+        ├── <span class="dir">web/</span>                      <span class="comment"># React 前端(Vite)</span><br>
+        │   ├── <span class="dir">components/</span>              <span class="comment"># UI 组件(ChatInterface, ConfigPanel 等)</span><br>
+        │   ├── <span class="dir">contexts/</span>                <span class="comment"># React Context 提供者</span><br>
+        │   ├── <span class="dir">services/</span>                <span class="comment"># API 客户端服务</span><br>
+        │   └── <span class="dir">utils/</span>                   <span class="comment"># 工具函数</span><br>
+        ├── <span class="dir">server/</span>                     <span class="comment"># NestJS 后端</span><br>
+        │   ├── <span class="dir">src/</span><br>
+        │   │   ├── <span class="dir">ai/</span>                  <span class="comment"># AI 服务(向量嵌入等)</span><br>
+        │   │   ├── <span class="dir">api/</span>                 <span class="comment"># API 模块</span><br>
+        │   │   ├── <span class="dir">auth/</span>                <span class="comment"># JWT 认证</span><br>
+        │   │   ├── <span class="dir">chat/</span>                <span class="comment"># 对话 / RAG 模块</span><br>
+        │   │   ├── <span class="dir">elasticsearch/</span>        <span class="comment"># Elasticsearch 集成</span><br>
+        │   │   ├── <span class="dir">import-task/</span>          <span class="comment"># 导入任务管理</span><br>
+        │   │   ├── <span class="dir">knowledge-base/</span>       <span class="comment"># 知识库管理</span><br>
+        │   │   ├── <span class="dir">libreoffice/</span>          <span class="comment"># LibreOffice 集成</span><br>
+        │   │   ├── <span class="dir">model-config/</span>         <span class="comment"># 模型配置管理</span><br>
+        │   │   ├── <span class="dir">vision/</span>              <span class="comment"># 视觉模型集成</span><br>
+        │   │   └── <span class="dir">vision-pipeline/</span>      <span class="comment"># 视觉管线编排</span><br>
+        │   ├── <span class="dir">data/</span>                    <span class="comment"># SQLite 数据库存储</span><br>
+        │   ├── <span class="dir">uploads/</span>                 <span class="comment"># 上传文件存储</span><br>
+        │   └── <span class="dir">temp/</span>                    <span class="comment"># 临时文件</span><br>
+        ├── <span class="dir">docs/</span>                        <span class="comment"># 项目文档</span><br>
+        ├── <span class="dir">nginx/</span>                       <span class="comment"># Nginx 配置</span><br>
+        ├── <span class="dir">libreoffice-server/</span>           <span class="comment"># LibreOffice 转换服务(Python/FastAPI)</span><br>
+        └── <span class="file">docker-compose.yml</span>            <span class="comment"># Docker 编排配置</span>
+      </div>
+    </section>
+
+    <!-- 开发环境搭建 -->
+    <section>
+      <h2 class="section-title"><span class="num">3</span> 开发环境搭建</h2>
+
+      <h4 style="margin-bottom:10px; color:#f1f5f9;">前置条件</h4>
+      <div class="card" style="margin-bottom:20px;">
+        <ul>
+          <li>Node.js 18+</li>
+          <li>Yarn 包管理器</li>
+          <li>Docker &amp; Docker Compose</li>
+        </ul>
+      </div>
+
+      <h4 style="margin-bottom:10px; color:#f1f5f9;">快速启动</h4>
+      <div class="code-block">
+        <span class="comment"># 安装依赖</span><br>
+        <span class="cmd">yarn install</span><br><br>
+        <span class="comment"># 启动基础设施服务</span><br>
+        <span class="cmd">docker-compose up -d elasticsearch tika libreoffice</span><br><br>
+        <span class="comment"># 配置环境变量</span><br>
+        <span class="cmd">cp server/.env.sample server/.env</span><br><br>
+        <span class="comment"># 同时启动前后端</span><br>
+        <span class="cmd">yarn dev</span>
+      </div>
+
+      <h4 style="margin:20px 0 10px; color:#f1f5f9;">开发命令</h4>
+      <div class="code-block">
+        <span class="comment"># 仅启动前端(端口 13001)</span><br>
+        <span class="cmd">cd web && yarn dev</span><br><br>
+        <span class="comment"># 仅启动后端(端口 3001)</span><br>
+        <span class="cmd">cd server && yarn start:dev</span><br><br>
+        <span class="comment"># 运行测试</span><br>
+        <span class="cmd">cd server && yarn test</span><br>
+        <span class="cmd">cd server && yarn test:e2e</span><br><br>
+        <span class="comment"># 代码检查和格式化</span><br>
+        <span class="cmd">cd server && yarn lint</span><br>
+        <span class="cmd">cd server && yarn format</span>
+      </div>
+    </section>
+
+    <!-- Docker 服务 -->
+    <section>
+      <h2 class="section-title"><span class="num">4</span> Docker 服务与端口</h2>
+      <div class="card">
+        <table class="info-table">
+          <thead>
+            <tr><th>服务</th><th>端口</th><th>用途</th></tr>
+          </thead>
+          <tbody>
+            <tr><td>Elasticsearch</td><td class="port">9200</td><td>向量存储与混合检索</td></tr>
+            <tr><td>Apache Tika</td><td class="port">9998</td><td>文档文本提取</td></tr>
+            <tr><td>LibreOffice Server</td><td class="port">8100</td><td>文档格式转换</td></tr>
+            <tr><td>后端 API</td><td class="port">3001</td><td>NestJS REST API</td></tr>
+            <tr><td>前端(开发)</td><td class="port">13001</td><td>Vite 开发服务器</td></tr>
+            <tr><td>前端(生产)</td><td class="port">80 / 443</td><td>Nginx 反向代理</td></tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <!-- 环境配置 -->
+    <section>
+      <h2 class="section-title"><span class="num">5</span> 环境配置</h2>
+      <div class="card">
+        <p style="font-size:0.88rem; color:var(--text-muted); margin-bottom:14px;">关键环境变量,配置于 <code style="color:var(--accent-green); background:#0d1117; padding:2px 8px; border-radius:4px; font-size:0.83rem;">server/.env</code></p>
+        <table class="info-table">
+          <thead>
+            <tr><th>变量名</th><th>默认值</th><th>说明</th></tr>
+          </thead>
+          <tbody>
+            <tr><td class="env-key">OPENAI_API_KEY</td><td>&mdash;</td><td>OpenAI 兼容 API 密钥</td></tr>
+            <tr><td class="env-key">GEMINI_API_KEY</td><td>&mdash;</td><td>Google Gemini API 密钥</td></tr>
+            <tr><td class="env-key">ELASTICSEARCH_HOST</td><td>http://localhost:9200</td><td>Elasticsearch 地址</td></tr>
+            <tr><td class="env-key">TIKA_HOST</td><td>http://localhost:9998</td><td>Apache Tika 地址</td></tr>
+            <tr><td class="env-key">LIBREOFFICE_URL</td><td>http://localhost:8100</td><td>LibreOffice 服务器地址</td></tr>
+            <tr><td class="env-key">JWT_SECRET</td><td>&mdash;</td><td>JWT 签名密钥</td></tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <!-- 代码规范 -->
+    <section>
+      <h2 class="section-title"><span class="num">6</span> 代码规范</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>语言要求</h4>
+          <ul>
+            <li>代码注释必须使用英文</li>
+            <li>日志消息必须使用英文</li>
+            <li>错误消息必须支持国际化</li>
+            <li>API 响应消息必须支持国际化</li>
+            <li>界面支持日语、中文和英文</li>
+          </ul>
+        </div>
+        <div class="card">
+          <h4>代码质量</h4>
+          <ul>
+            <li>后端使用 Jest 进行单元测试和端到端测试</li>
+            <li>后端已配置 ESLint 和 Prettier</li>
+            <li>格式化:<code style="color:var(--accent-green);">cd server && yarn format</code></li>
+            <li>检查:<code style="color:var(--accent-green);">cd server && yarn lint</code></li>
+          </ul>
+        </div>
+      </div>
+    </section>
+
+    <!-- 常见开发任务 -->
+    <section>
+      <h2 class="section-title"><span class="num">7</span> 常见开发任务</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>添加新的 API 端点</h4>
+          <ol class="step-list">
+            <li>在 <code style="color:var(--accent-blue);">server/src/</code> 对应模块下创建 Controller</li>
+            <li>添加 Service 方法,使用英文注释</li>
+            <li>更新 DTO 和参数校验</li>
+            <li>在 <code style="color:var(--accent-blue);">*.spec.ts</code> 文件中添加测试</li>
+          </ol>
+        </div>
+        <div class="card">
+          <h4>添加新的前端组件</h4>
+          <ol class="step-list">
+            <li>在 <code style="color:var(--accent-blue);">web/components/</code> 下创建组件</li>
+            <li>在 <code style="color:var(--accent-blue);">web/types.ts</code> 中添加 TypeScript 接口</li>
+            <li>使用 Tailwind CSS 进行样式开发</li>
+            <li>在 <code style="color:var(--accent-blue);">web/services/</code> 中连接后端服务</li>
+          </ol>
+        </div>
+      </div>
+    </section>
+
+    <!-- 部署 -->
+    <section>
+      <h2 class="section-title"><span class="num">8</span> 部署</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>开发环境</h4>
+          <div class="code-block">
+            <span class="cmd">docker-compose up -d elasticsearch tika libreoffice</span><br>
+            <span class="cmd">yarn dev</span>
+          </div>
+        </div>
+        <div class="card">
+          <h4>生产环境</h4>
+          <div class="code-block">
+            <span class="comment"># 构建并启动所有服务</span><br>
+            <span class="cmd">docker-compose up -d</span>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- 故障排查 -->
+    <section>
+      <h2 class="section-title"><span class="num">9</span> 故障排查</h2>
+      <div class="troubleshoot-item">
+        <strong>Elasticsearch 无法启动</strong>
+        <p>检查 docker-compose.yml 中的内存限制配置</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>文件上传失败</strong>
+        <p>确保 <code style="color:var(--accent-green);">uploads/</code> 和 <code style="color:var(--accent-green);">temp/</code> 目录存在且具有正确的读写权限</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>视觉管线报错</strong>
+        <p>确认 LibreOffice 服务正在运行且 8100 端口可访问</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>API 密钥错误</strong>
+        <p>检查 <code style="color:var(--accent-green);">server/.env</code> 中的环境变量配置</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>数据库重置</strong>
+        <p>删除 <code style="color:var(--accent-green);">server/data/metadata.db</code> 及 Elasticsearch 数据卷</p>
+      </div>
+    </section>
+
+    <!-- 调试 -->
+    <section>
+      <h2 class="section-title"><span class="num">10</span> 调试与健康检查</h2>
+      <div class="code-block">
+        <span class="comment"># 检查 Elasticsearch 状态</span><br>
+        <span class="cmd">curl http://localhost:9200/_cat/indices</span><br><br>
+        <span class="comment"># 检查 Tika 状态</span><br>
+        <span class="cmd">curl http://localhost:9998/tika</span><br><br>
+        <span class="comment"># 检查 LibreOffice 状态</span><br>
+        <span class="cmd">curl http://localhost:8100/health</span>
+      </div>
+    </section>
+
+  </div>
+
+  <footer>
+    Simple Knowledge Base &mdash; 全栈 RAG 问答系统 &mdash; React 19 + NestJS + Elasticsearch
+  </footer>
+
+</body>
+</html>

+ 781 - 0
docs/system-overview.html

@@ -0,0 +1,781 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Simple Knowledge Base - System Overview</title>
+  <style>
+    :root {
+      --primary: #6366f1;
+      --primary-light: #818cf8;
+      --primary-dark: #4f46e5;
+      --bg: #0f172a;
+      --bg-card: #1e293b;
+      --bg-code: #0d1117;
+      --text: #e2e8f0;
+      --text-muted: #94a3b8;
+      --border: #334155;
+      --accent-green: #34d399;
+      --accent-blue: #38bdf8;
+      --accent-orange: #fb923c;
+      --accent-pink: #f472b6;
+    }
+
+    * { margin: 0; padding: 0; box-sizing: border-box; }
+
+    body {
+      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans SC', sans-serif;
+      background: var(--bg);
+      color: var(--text);
+      line-height: 1.7;
+    }
+
+    .hero {
+      background: linear-gradient(135deg, #1e1b4b 0%, #312e81 30%, #0f172a 70%, #0c0a09 100%);
+      padding: 80px 20px 60px;
+      text-align: center;
+      position: relative;
+      overflow: hidden;
+    }
+
+    .hero::before {
+      content: '';
+      position: absolute;
+      top: -50%;
+      left: -50%;
+      width: 200%;
+      height: 200%;
+      background: radial-gradient(circle at 30% 50%, rgba(99, 102, 241, 0.15) 0%, transparent 50%),
+                  radial-gradient(circle at 70% 50%, rgba(56, 189, 248, 0.1) 0%, transparent 50%);
+      animation: pulse 8s ease-in-out infinite;
+    }
+
+    @keyframes pulse {
+      0%, 100% { opacity: 0.6; }
+      50% { opacity: 1; }
+    }
+
+    .hero h1 {
+      font-size: 2.8rem;
+      font-weight: 800;
+      background: linear-gradient(135deg, #c7d2fe, #818cf8, #38bdf8);
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+      background-clip: text;
+      position: relative;
+      margin-bottom: 12px;
+    }
+
+    .hero .subtitle {
+      font-size: 1.15rem;
+      color: var(--text-muted);
+      position: relative;
+      max-width: 700px;
+      margin: 0 auto;
+    }
+
+    .badge-row {
+      display: flex;
+      gap: 10px;
+      justify-content: center;
+      flex-wrap: wrap;
+      margin-top: 24px;
+      position: relative;
+    }
+
+    .badge {
+      display: inline-flex;
+      align-items: center;
+      gap: 6px;
+      padding: 5px 14px;
+      border-radius: 999px;
+      font-size: 0.82rem;
+      font-weight: 600;
+      border: 1px solid;
+    }
+
+    .badge.react { color: #61dafb; border-color: #61dafb33; background: #61dafb10; }
+    .badge.nest { color: #e0234e; border-color: #e0234e33; background: #e0234e10; }
+    .badge.rag { color: var(--accent-green); border-color: #34d39933; background: #34d39910; }
+    .badge.ts { color: #3178c6; border-color: #3178c633; background: #3178c610; }
+
+    .container {
+      max-width: 1100px;
+      margin: 0 auto;
+      padding: 0 20px;
+    }
+
+    .features-grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+      gap: 20px;
+      margin: -40px auto 60px;
+      position: relative;
+      z-index: 1;
+    }
+
+    .feature-card {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 16px;
+      padding: 28px;
+      transition: transform 0.2s, border-color 0.2s;
+    }
+
+    .feature-card:hover {
+      transform: translateY(-3px);
+      border-color: var(--primary);
+    }
+
+    .feature-card .icon {
+      width: 44px;
+      height: 44px;
+      border-radius: 12px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 1.3rem;
+      margin-bottom: 16px;
+    }
+
+    .feature-card h3 {
+      font-size: 1.05rem;
+      margin-bottom: 8px;
+      color: #f1f5f9;
+    }
+
+    .feature-card p {
+      font-size: 0.9rem;
+      color: var(--text-muted);
+    }
+
+    .icon-blue { background: #38bdf818; }
+    .icon-green { background: #34d39918; }
+    .icon-orange { background: #fb923c18; }
+    .icon-pink { background: #f472b618; }
+    .icon-purple { background: #a78bfa18; }
+    .icon-yellow { background: #fbbf2418; }
+
+    section {
+      margin-bottom: 56px;
+    }
+
+    .section-title {
+      font-size: 1.5rem;
+      font-weight: 700;
+      margin-bottom: 24px;
+      padding-bottom: 12px;
+      border-bottom: 2px solid var(--border);
+      display: flex;
+      align-items: center;
+      gap: 10px;
+    }
+
+    .section-title .num {
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      width: 32px;
+      height: 32px;
+      border-radius: 8px;
+      background: var(--primary);
+      font-size: 0.85rem;
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    /* Architecture Diagram */
+    .arch-diagram {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 16px;
+      padding: 32px;
+      overflow-x: auto;
+    }
+
+    .arch-row {
+      display: flex;
+      justify-content: center;
+      gap: 16px;
+      margin-bottom: 16px;
+      flex-wrap: wrap;
+    }
+
+    .arch-box {
+      padding: 14px 22px;
+      border-radius: 10px;
+      font-size: 0.85rem;
+      font-weight: 600;
+      text-align: center;
+      min-width: 140px;
+      border: 1px solid;
+    }
+
+    .arch-box.frontend { background: #61dafb12; border-color: #61dafb33; color: #61dafb; }
+    .arch-box.backend { background: #e0234e12; border-color: #e0234e33; color: #e0234e; }
+    .arch-box.infra { background: #34d39912; border-color: #34d39933; color: #34d399; }
+    .arch-box.ai { background: #a78bfa12; border-color: #a78bfa33; color: #a78bfa; }
+    .arch-box.data { background: #fb923c12; border-color: #fb923c33; color: #fb923c; }
+
+    .arch-arrow {
+      text-align: center;
+      color: var(--text-muted);
+      font-size: 1.2rem;
+      margin-bottom: 16px;
+    }
+
+    .arch-label {
+      text-align: center;
+      font-size: 0.78rem;
+      color: var(--text-muted);
+      text-transform: uppercase;
+      letter-spacing: 1.5px;
+      margin-bottom: 10px;
+    }
+
+    /* File Tree */
+    .file-tree {
+      background: var(--bg-code);
+      border: 1px solid var(--border);
+      border-radius: 12px;
+      padding: 24px 28px;
+      font-family: 'Cascadia Code', 'Fira Code', monospace;
+      font-size: 0.85rem;
+      line-height: 1.9;
+      overflow-x: auto;
+    }
+
+    .file-tree .dir { color: var(--accent-blue); font-weight: 600; }
+    .file-tree .comment { color: #64748b; font-style: italic; }
+    .file-tree .file { color: var(--text); }
+
+    /* Pipeline */
+    .pipeline {
+      display: flex;
+      align-items: center;
+      gap: 0;
+      flex-wrap: wrap;
+      justify-content: center;
+      margin: 20px 0;
+    }
+
+    .pipeline-step {
+      padding: 12px 20px;
+      border-radius: 10px;
+      font-size: 0.85rem;
+      font-weight: 600;
+      text-align: center;
+      border: 1px solid var(--border);
+      background: var(--bg-card);
+    }
+
+    .pipeline-arrow {
+      color: var(--text-muted);
+      font-size: 1.1rem;
+      padding: 0 6px;
+    }
+
+    .pipeline-step.active {
+      border-color: var(--primary);
+      background: #6366f118;
+      color: var(--primary-light);
+    }
+
+    /* Tables */
+    .info-table {
+      width: 100%;
+      border-collapse: collapse;
+      margin: 12px 0;
+    }
+
+    .info-table th, .info-table td {
+      padding: 10px 16px;
+      text-align: left;
+      border-bottom: 1px solid var(--border);
+      font-size: 0.9rem;
+    }
+
+    .info-table th {
+      color: var(--text-muted);
+      font-weight: 600;
+      font-size: 0.82rem;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+    }
+
+    .info-table .port {
+      font-family: 'Cascadia Code', monospace;
+      color: var(--accent-orange);
+      font-weight: 600;
+    }
+
+    .info-table .env-key {
+      font-family: 'Cascadia Code', monospace;
+      color: var(--accent-green);
+      font-size: 0.83rem;
+    }
+
+    /* Code Block */
+    .code-block {
+      background: var(--bg-code);
+      border: 1px solid var(--border);
+      border-radius: 10px;
+      padding: 18px 22px;
+      font-family: 'Cascadia Code', 'Fira Code', monospace;
+      font-size: 0.83rem;
+      line-height: 1.8;
+      overflow-x: auto;
+      margin: 12px 0;
+    }
+
+    .code-block .cmd { color: var(--accent-green); }
+    .code-block .comment { color: #64748b; }
+
+    /* Two Column Layout */
+    .two-col {
+      display: grid;
+      grid-template-columns: 1fr 1fr;
+      gap: 24px;
+    }
+
+    @media (max-width: 768px) {
+      .two-col { grid-template-columns: 1fr; }
+      .hero h1 { font-size: 2rem; }
+      .features-grid { grid-template-columns: 1fr; }
+    }
+
+    .card {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 14px;
+      padding: 24px;
+    }
+
+    .card h4 {
+      font-size: 1rem;
+      margin-bottom: 14px;
+      color: #f1f5f9;
+    }
+
+    .card ul {
+      list-style: none;
+      padding: 0;
+    }
+
+    .card ul li {
+      padding: 6px 0;
+      font-size: 0.88rem;
+      color: var(--text-muted);
+      display: flex;
+      align-items: flex-start;
+      gap: 8px;
+    }
+
+    .card ul li::before {
+      content: '›';
+      color: var(--primary-light);
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    .step-list {
+      list-style: none;
+      padding: 0;
+      counter-reset: step;
+    }
+
+    .step-list li {
+      counter-increment: step;
+      padding: 8px 0;
+      font-size: 0.88rem;
+      color: var(--text-muted);
+      display: flex;
+      align-items: flex-start;
+      gap: 10px;
+    }
+
+    .step-list li::before {
+      content: counter(step);
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      width: 22px;
+      height: 22px;
+      border-radius: 6px;
+      background: var(--primary);
+      color: white;
+      font-size: 0.72rem;
+      font-weight: 700;
+      flex-shrink: 0;
+    }
+
+    .troubleshoot-item {
+      background: var(--bg-card);
+      border: 1px solid var(--border);
+      border-radius: 10px;
+      padding: 16px 20px;
+      margin-bottom: 10px;
+    }
+
+    .troubleshoot-item strong {
+      color: #f1f5f9;
+      font-size: 0.92rem;
+    }
+
+    .troubleshoot-item p {
+      color: var(--text-muted);
+      font-size: 0.85rem;
+      margin-top: 4px;
+    }
+
+    footer {
+      text-align: center;
+      padding: 40px 20px;
+      color: var(--text-muted);
+      font-size: 0.82rem;
+      border-top: 1px solid var(--border);
+    }
+  </style>
+</head>
+<body>
+
+  <!-- Hero -->
+  <div class="hero">
+    <h1>Simple Knowledge Base</h1>
+    <p class="subtitle">Full-stack RAG Q&A System &mdash; Retrieval-Augmented Generation powered by React 19 + NestJS</p>
+    <div class="badge-row">
+      <span class="badge react">React 19</span>
+      <span class="badge nest">NestJS</span>
+      <span class="badge rag">RAG System</span>
+      <span class="badge ts">TypeScript</span>
+    </div>
+  </div>
+
+  <div class="container">
+
+    <!-- Key Features -->
+    <div class="features-grid">
+      <div class="feature-card">
+        <div class="icon icon-purple"> </div>
+        <h3>Multi-Model Support</h3>
+        <p>OpenAI-compatible APIs (OpenAI, DeepSeek, Claude) + Google Gemini native SDK with configurable LLM, Embedding, and Rerank models.</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-blue">⚡</div>
+        <h3>Dual Processing Modes</h3>
+        <p>Fast Mode via Apache Tika for text extraction, and High-Precision Mode via Vision Pipeline for mixed image/text documents.</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-green"> </div>
+        <h3>Hybrid Search</h3>
+        <p>Vector + keyword search with Elasticsearch, source citation, similarity scoring, and configurable chunk size &amp; overlap.</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-orange"> </div>
+        <h3>User Isolation</h3>
+        <p>JWT authentication with per-user knowledge bases. Each user has isolated data and configurations.</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-pink"> </div>
+        <h3>Streaming Responses</h3>
+        <p>Real-time streaming via Server-Sent Events (SSE) for smooth, low-latency chat interactions.</p>
+      </div>
+      <div class="feature-card">
+        <div class="icon icon-yellow"> </div>
+        <h3>Multi-Language</h3>
+        <p>Interface supports Japanese, Chinese, and English with full internationalization for error and API response messages.</p>
+      </div>
+    </div>
+
+    <!-- Architecture -->
+    <section>
+      <h2 class="section-title"><span class="num">1</span> Architecture Overview</h2>
+
+      <div class="arch-diagram">
+        <div class="arch-label">Frontend Layer</div>
+        <div class="arch-row">
+          <div class="arch-box frontend">React 19 + Vite<br><small style="opacity:0.7">Port 13001 (dev) / 80 (prod)</small></div>
+        </div>
+        <div class="arch-arrow">↕</div>
+        <div class="arch-label">Backend Layer</div>
+        <div class="arch-row">
+          <div class="arch-box backend">NestJS API<br><small style="opacity:0.7">Port 3001</small></div>
+          <div class="arch-box backend">JWT Auth</div>
+          <div class="arch-box backend">Chat / RAG</div>
+          <div class="arch-box backend">Vision Pipeline</div>
+        </div>
+        <div class="arch-arrow">↕</div>
+        <div class="arch-label">AI &amp; Data Layer</div>
+        <div class="arch-row">
+          <div class="arch-box ai">OpenAI / Gemini<br><small style="opacity:0.7">LLM + Embedding</small></div>
+          <div class="arch-box infra">Elasticsearch<br><small style="opacity:0.7">Port 9200</small></div>
+          <div class="arch-box infra">Apache Tika<br><small style="opacity:0.7">Port 9998</small></div>
+          <div class="arch-box infra">LibreOffice<br><small style="opacity:0.7">Port 8100</small></div>
+          <div class="arch-box data">SQLite<br><small style="opacity:0.7">Metadata</small></div>
+        </div>
+      </div>
+
+      <!-- Processing Pipeline -->
+      <h4 style="margin-top:28px; margin-bottom:14px; color:#f1f5f9;">Dual Processing Pipeline</h4>
+      <div class="two-col">
+        <div class="card">
+          <h4>Fast Mode (Tika)</h4>
+          <div class="pipeline">
+            <div class="pipeline-step active">Upload</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">Tika Extract</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">Embed</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step active">Store</div>
+          </div>
+          <p style="font-size:0.85rem; color:var(--text-muted); text-align:center;">Quick text extraction, no API cost</p>
+        </div>
+        <div class="card">
+          <h4>High-Precision Mode (Vision)</h4>
+          <div class="pipeline">
+            <div class="pipeline-step active">Upload</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">LibreOffice</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">PDF→Image</div>
+            <span class="pipeline-arrow">→</span>
+            <div class="pipeline-step">Vision Model</div>
+          </div>
+          <p style="font-size:0.85rem; color:var(--text-muted); text-align:center;">Preserves layout, charts, and images</p>
+        </div>
+      </div>
+    </section>
+
+    <!-- Project Structure -->
+    <section>
+      <h2 class="section-title"><span class="num">2</span> Project Structure</h2>
+      <div class="file-tree">
+        <span class="dir">simple-kb/</span><br>
+        ├── <span class="dir">web/</span>                      <span class="comment"># React frontend (Vite)</span><br>
+        │   ├── <span class="dir">components/</span>              <span class="comment"># UI components (ChatInterface, ConfigPanel, etc.)</span><br>
+        │   ├── <span class="dir">contexts/</span>                <span class="comment"># React Context providers</span><br>
+        │   ├── <span class="dir">services/</span>                <span class="comment"># API client services</span><br>
+        │   └── <span class="dir">utils/</span>                   <span class="comment"># Utility functions</span><br>
+        ├── <span class="dir">server/</span>                     <span class="comment"># NestJS backend</span><br>
+        │   ├── <span class="dir">src/</span><br>
+        │   │   ├── <span class="dir">ai/</span>                  <span class="comment"># AI services (embedding, etc.)</span><br>
+        │   │   ├── <span class="dir">api/</span>                 <span class="comment"># API module</span><br>
+        │   │   ├── <span class="dir">auth/</span>                <span class="comment"># JWT authentication</span><br>
+        │   │   ├── <span class="dir">chat/</span>                <span class="comment"># Chat / RAG module</span><br>
+        │   │   ├── <span class="dir">elasticsearch/</span>        <span class="comment"># Elasticsearch integration</span><br>
+        │   │   ├── <span class="dir">import-task/</span>          <span class="comment"># Import task management</span><br>
+        │   │   ├── <span class="dir">knowledge-base/</span>       <span class="comment"># Knowledge base management</span><br>
+        │   │   ├── <span class="dir">libreoffice/</span>          <span class="comment"># LibreOffice integration</span><br>
+        │   │   ├── <span class="dir">model-config/</span>         <span class="comment"># Model configuration management</span><br>
+        │   │   ├── <span class="dir">vision/</span>              <span class="comment"># Vision model integration</span><br>
+        │   │   └── <span class="dir">vision-pipeline/</span>      <span class="comment"># Vision pipeline orchestration</span><br>
+        │   ├── <span class="dir">data/</span>                    <span class="comment"># SQLite database storage</span><br>
+        │   ├── <span class="dir">uploads/</span>                 <span class="comment"># Uploaded files storage</span><br>
+        │   └── <span class="dir">temp/</span>                    <span class="comment"># Temporary files</span><br>
+        ├── <span class="dir">docs/</span>                        <span class="comment"># Documentation (Japanese/Chinese)</span><br>
+        ├── <span class="dir">nginx/</span>                       <span class="comment"># Nginx configuration</span><br>
+        ├── <span class="dir">libreoffice-server/</span>           <span class="comment"># LibreOffice conversion service (Python/FastAPI)</span><br>
+        └── <span class="file">docker-compose.yml</span>            <span class="comment"># Docker orchestration</span>
+      </div>
+    </section>
+
+    <!-- Development Setup -->
+    <section>
+      <h2 class="section-title"><span class="num">3</span> Development Setup</h2>
+
+      <h4 style="margin-bottom:10px; color:#f1f5f9;">Prerequisites</h4>
+      <div class="card" style="margin-bottom:20px;">
+        <ul>
+          <li>Node.js 18+</li>
+          <li>Yarn package manager</li>
+          <li>Docker &amp; Docker Compose</li>
+        </ul>
+      </div>
+
+      <h4 style="margin-bottom:10px; color:#f1f5f9;">Quick Start</h4>
+      <div class="code-block">
+        <span class="comment"># Install dependencies</span><br>
+        <span class="cmd">yarn install</span><br><br>
+        <span class="comment"># Start infrastructure services</span><br>
+        <span class="cmd">docker-compose up -d elasticsearch tika libreoffice</span><br><br>
+        <span class="comment"># Configure environment</span><br>
+        <span class="cmd">cp server/.env.sample server/.env</span><br><br>
+        <span class="comment"># Start both frontend and backend</span><br>
+        <span class="cmd">yarn dev</span>
+      </div>
+
+      <h4 style="margin:20px 0 10px; color:#f1f5f9;">Development Commands</h4>
+      <div class="code-block">
+        <span class="comment"># Frontend only (port 13001)</span><br>
+        <span class="cmd">cd web && yarn dev</span><br><br>
+        <span class="comment"># Backend only (port 3001)</span><br>
+        <span class="cmd">cd server && yarn start:dev</span><br><br>
+        <span class="comment"># Run tests</span><br>
+        <span class="cmd">cd server && yarn test</span><br>
+        <span class="cmd">cd server && yarn test:e2e</span><br><br>
+        <span class="comment"># Lint and format</span><br>
+        <span class="cmd">cd server && yarn lint</span><br>
+        <span class="cmd">cd server && yarn format</span>
+      </div>
+    </section>
+
+    <!-- Docker Services -->
+    <section>
+      <h2 class="section-title"><span class="num">4</span> Docker Services &amp; Ports</h2>
+      <div class="card">
+        <table class="info-table">
+          <thead>
+            <tr><th>Service</th><th>Port</th><th>Purpose</th></tr>
+          </thead>
+          <tbody>
+            <tr><td>Elasticsearch</td><td class="port">9200</td><td>Vector storage &amp; hybrid search</td></tr>
+            <tr><td>Apache Tika</td><td class="port">9998</td><td>Document text extraction</td></tr>
+            <tr><td>LibreOffice Server</td><td class="port">8100</td><td>Document format conversion</td></tr>
+            <tr><td>Backend API</td><td class="port">3001</td><td>NestJS REST API</td></tr>
+            <tr><td>Frontend (dev)</td><td class="port">13001</td><td>Vite dev server</td></tr>
+            <tr><td>Frontend (prod)</td><td class="port">80 / 443</td><td>Nginx reverse proxy</td></tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <!-- Environment Configuration -->
+    <section>
+      <h2 class="section-title"><span class="num">5</span> Environment Configuration</h2>
+      <div class="card">
+        <p style="font-size:0.88rem; color:var(--text-muted); margin-bottom:14px;">Key environment variables in <code style="color:var(--accent-green); background:#0d1117; padding:2px 8px; border-radius:4px; font-size:0.83rem;">server/.env</code></p>
+        <table class="info-table">
+          <thead>
+            <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
+          </thead>
+          <tbody>
+            <tr><td class="env-key">OPENAI_API_KEY</td><td>&mdash;</td><td>OpenAI-compatible API key</td></tr>
+            <tr><td class="env-key">GEMINI_API_KEY</td><td>&mdash;</td><td>Google Gemini API key</td></tr>
+            <tr><td class="env-key">ELASTICSEARCH_HOST</td><td>http://localhost:9200</td><td>Elasticsearch URL</td></tr>
+            <tr><td class="env-key">TIKA_HOST</td><td>http://localhost:9998</td><td>Apache Tika URL</td></tr>
+            <tr><td class="env-key">LIBREOFFICE_URL</td><td>http://localhost:8100</td><td>LibreOffice server URL</td></tr>
+            <tr><td class="env-key">JWT_SECRET</td><td>&mdash;</td><td>JWT signing secret</td></tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <!-- Code Standards -->
+    <section>
+      <h2 class="section-title"><span class="num">6</span> Code Standards</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>Language Requirements</h4>
+          <ul>
+            <li>Code comments must be in English</li>
+            <li>Log messages must be in English</li>
+            <li>Error messages must support internationalization</li>
+            <li>API response messages must support i18n</li>
+            <li>Interface supports Japanese, Chinese, and English</li>
+          </ul>
+        </div>
+        <div class="card">
+          <h4>Code Quality</h4>
+          <ul>
+            <li>Backend uses Jest for unit and e2e tests</li>
+            <li>ESLint and Prettier configured for backend</li>
+            <li>Format: <code style="color:var(--accent-green);">cd server && yarn format</code></li>
+            <li>Lint: <code style="color:var(--accent-green);">cd server && yarn lint</code></li>
+          </ul>
+        </div>
+      </div>
+    </section>
+
+    <!-- Common Tasks -->
+    <section>
+      <h2 class="section-title"><span class="num">7</span> Common Development Tasks</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>Adding a New API Endpoint</h4>
+          <ol class="step-list">
+            <li>Create controller in appropriate module under <code style="color:var(--accent-blue);">server/src/</code></li>
+            <li>Add service methods with English comments</li>
+            <li>Update DTOs and validation</li>
+            <li>Add tests in <code style="color:var(--accent-blue);">*.spec.ts</code> files</li>
+          </ol>
+        </div>
+        <div class="card">
+          <h4>Adding a New Frontend Component</h4>
+          <ol class="step-list">
+            <li>Create component in <code style="color:var(--accent-blue);">web/components/</code></li>
+            <li>Add TypeScript interfaces in <code style="color:var(--accent-blue);">web/types.ts</code></li>
+            <li>Use Tailwind CSS for styling</li>
+            <li>Connect to backend services in <code style="color:var(--accent-blue);">web/services/</code></li>
+          </ol>
+        </div>
+      </div>
+    </section>
+
+    <!-- Deployment -->
+    <section>
+      <h2 class="section-title"><span class="num">8</span> Deployment</h2>
+      <div class="two-col">
+        <div class="card">
+          <h4>Development</h4>
+          <div class="code-block">
+            <span class="cmd">docker-compose up -d elasticsearch tika libreoffice</span><br>
+            <span class="cmd">yarn dev</span>
+          </div>
+        </div>
+        <div class="card">
+          <h4>Production</h4>
+          <div class="code-block">
+            <span class="comment"># Build and start all services</span><br>
+            <span class="cmd">docker-compose up -d</span>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- Troubleshooting -->
+    <section>
+      <h2 class="section-title"><span class="num">9</span> Troubleshooting</h2>
+      <div class="troubleshoot-item">
+        <strong>Elasticsearch not starting</strong>
+        <p>Check memory limits in docker-compose.yml</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>File upload failures</strong>
+        <p>Ensure <code style="color:var(--accent-green);">uploads/</code> and <code style="color:var(--accent-green);">temp/</code> directories exist with proper permissions</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>Vision pipeline errors</strong>
+        <p>Verify LibreOffice server is running and accessible at port 8100</p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>API key errors</strong>
+        <p>Check environment variables in <code style="color:var(--accent-green);">server/.env</code></p>
+      </div>
+      <div class="troubleshoot-item">
+        <strong>Database reset</strong>
+        <p>Delete <code style="color:var(--accent-green);">server/data/metadata.db</code> and Elasticsearch data volume</p>
+      </div>
+    </section>
+
+    <!-- Debugging -->
+    <section>
+      <h2 class="section-title"><span class="num">10</span> Debugging &amp; Health Checks</h2>
+      <div class="code-block">
+        <span class="comment"># Check Elasticsearch</span><br>
+        <span class="cmd">curl http://localhost:9200/_cat/indices</span><br><br>
+        <span class="comment"># Check Tika</span><br>
+        <span class="cmd">curl http://localhost:9998/tika</span><br><br>
+        <span class="comment"># Check LibreOffice</span><br>
+        <span class="cmd">curl http://localhost:8100/health</span>
+      </div>
+    </section>
+
+  </div>
+
+  <footer>
+    Simple Knowledge Base &mdash; Full-stack RAG Q&A System &mdash; React 19 + NestJS + Elasticsearch
+  </footer>
+
+</body>
+</html>