跳转至

openKMS 架构

docker/docker-compose.yml 运行完整栈(Postgres/pgvector、MinIO、本体图存储用 Neo4j、backend、scheduler(中央 cron)、带 openkms-cli 解析的 procrastinate worker、nginx 前端 http://localhost:8082)。worker 镜像为 platform: linux/amd64(Apple Silicon 经模拟运行 Paddle wheel),并安装 libgl1(OpenCV/PaddleX)及 LibreOffice(writer + impress)(DOCX/PPTX)与 mupdf-tools(mutool,EPUB → PDF 再解析)。Postgres、MinIO、backend 不发布到主机;服务经 Docker DNS(postgres、minio、backend:8102)互访,浏览器经 8082 由 nginx 代理 /api、/internal-api、认证路由与 /buckets/...。镜像:docker/Dockerfile(backend、worker)、docker/Dockerfile.frontend。仓库根目录:docker compose -f docker/docker-compose.yml 用于 build、up -d --build、down(docker/README.md)。

高层架构图

flowchart TB
  subgraph Frontend["前端 (React/Vite)"]
    FE["首页(有 knowledge_map:read 时展示知识地图力导向图)、知识地图、文档、文章、知识库、维基空间、术语表、流水线、任务运行、模型"]
  end

  subgraph Backend["后端 (FastAPI)"]
    API["knowledge-map (/api/knowledge-map,含 map-html 快照)、home、document-channels、article-channels、articles、documents、knowledge-bases、wiki-spaces、glossaries、pipelines、jobs、models、object-types、link-types、data-sources、datasets、feature-toggles"]
  end

  subgraph Storage["数据与处理"]
    PG[("PostgreSQL + pgvector")]
    S3[(S3/MinIO)]
    Worker["procrastinate worker"]
  end

  subgraph WorkerDetail["Worker 执行"]
    CLI["openkms-cli pipeline run (doc-parse, kb-index)"]
    VLM["mlx-vlm-server"]
  end

  subgraph QAAgent["QA Agent (FastAPI + LangGraph)"]
    Agent["RAG Agent: retrieve + generate"]
  end

  subgraph External["外部服务"]
    LLM["OpenAI 兼容 Service Provider"]
  end

  Frontend -->|"HTTP 经代理 (Vite :5173→8102; Docker UI :8082 nginx→backend)"| Backend
  Backend --> PG
  Backend --> S3
  Backend --> Worker
  Backend -->|元数据抽取、模型测试、FAQ 生成| LLM
  Backend -->|代理 /ask| Agent
  Agent -->|search| Backend
  Agent --> LLM
  Worker --> S3
  Worker --> CLI
  CLI --> VLM
  CLI -->|元数据抽取、embedding| LLM
  CLI -->|kb-index: chunks、FAQ embedding| Backend
  CLI -->|wiki put/sync/upload-file| Backend
层 作用
PostgreSQL + pgvector 系统记录 — 元数据、权限与向量 embedding。领域:认证与 ACL(用户、角色、组、资源 ACL)、通道与内容(文档、文章、版本、关系)、知识(知识库、分块、FAQ、维基、术语表)、本体(对象/链接类型与实例、数据集)、运维(流水线、任务、模型、评测、知识地图)、系统(设置、功能开关)。权威表清单是 backend/app/models/(以及 alembic/versions/ 里某个库实际存在的东西)。
S3/MinIO 大文件 — 文档原件({file_hash}/…)、文章包、维基 vault 镜像与临时文件、维基链接图缓存 JSON。浏览器经 API presigned 重定向访问。
Worker procrastinate worker 执行延迟任务(文档解析、知识库索引等),拉起 openkms-cli;在 PostgreSQL 中更新状态。
LLM 提供商 外部 OpenAI 兼容 API,配置为 api_providers / api_models — 元数据抽取、FAQ 生成、embedding、模型 playground。
QA Agent 按知识库配置的独立 FastAPI + LangGraph 服务;仅经后端 API 检索(不直连数据库)。
应用内 Agent 运行在主 API 进程内:Deep Agents 项目工作区(backend/app/services/deep_agents/)与知识地图设计器。与 QA Agent 不同。

前端结构

flowchart TB
  subgraph Providers["Provider 层级"]
    Auth["AuthContext + permission-catalog 并集, canAccessPath"]
    FT[FeatureTogglesContext]
    DC[DocumentChannelsContext]
    AC[ArticleChannelsContext]
    Auth --> FT
    FT --> DC
    FT --> AC
  end

  subgraph Pages["路由"]
    Home[首页]
    KnowledgeMapPage[知识地图]
    Docs["DocumentsIndex, DocumentChannel, DocumentDetail"]
    Articles["ArticlesIndex, ArticleChannel, ArticleChannels, ArticleChannelSettings, ArticleDetail"]
    KB["KnowledgeBaseList, KnowledgeBaseDetail"]
    Wiki["WikiSpaceList, WikiSpaceSettings, WikiWorkspace"]
    Eval["EvaluationDatasetList, EvaluationDatasetDetail"]
    Glossaries["GlossaryList, GlossaryDetail"]
    Pipelines[Pipelines]
    JobRuns["JobRuns, JobDetail"]
    Models["Models, ModelDetail"]
    Ontology["OntologyList, Datasets, ObjectTypes, Objects, Links, ObjectExplorer"]
    Console["Console Overview, Permissions, Data security, DataSources, Connectors, Settings, Users, FeatureToggles"]
    UserSettings["Profile, UserSettings, API keys"]
  end

  Providers --> Pages

本体论相关 SPA 源码位于 frontend/src/pages/ontology/。Console 管理页位于 frontend/src/pages/console/。

目录布局(frontend/src/)

区域 作用
App.tsx 路由表、Provider 嵌套(见上图)、ErrorBoundary、懒加载页面
pages/ 每个路由一个页面,按领域分子目录(documents/、articles/、wiki/、ontology/、console/ 等)。与上图对应即可,不必在此罗列每个文件名
components/ 跨路由复用的 UI(布局壳、markdown、图、错误边界)。仅单页使用的组件放在对应 pages/ 旁
data/ 按 API 领域划分的 HTTP 客户端;域模块用 request() / requestRaw()(apiClient.ts 内封装 authAwareFetch)
hooks/ 跨页 React 逻辑(useIsMobile、useListFetch、useDebouncedValue 等)
contexts/ 跨页 React 状态(认证、功能开关、通道列表、ConfirmProvider、本体论移动端侧栏)
config/ API 根路径与供 UI 门控用的 PERM_* 镜像
styles/ 全局设计系统 — 细则见 design-system.md
i18n/ 语言包与 namespace(见下文)
graph/ 2D/3D 或 wiki/首页共用同一图模型时的类型与构建逻辑
frontend/src/
├── App.tsx, main.tsx, index.scss
├── pages/
│   ├── documents/, articles/, wiki/, knowledge-bases/, knowledge-map/
│   ├── evaluation/, glossaries/, ontology/, console/
│   ├── agents/, pipelines/, jobs/, models/, auth/, connectors/
│   └── Home.tsx, Profile.tsx, UserSettings.tsx, GlobalSearch.tsx
├── components/
│   ├── Layout/                 # 外壳:侧栏、顶栏、路由门控
│   ├── markdown/, wiki/, agents/, knowledge-bases/, jobs/, ui/
│   │   # markdown/:共享 **RichMarkdown**(GFM、KaTeX+mhchem、AI 公式定界符规范化、Mermaid)
│   └── KnowledgeMapForceGraph*.tsx, ErrorBoundary, …
├── data/                       # 按后端领域划分的 *Api.ts(+ apiClient.ts)
├── hooks/                      # useIsMobile、useListFetch、useDebouncedValue 等
├── contexts/                   # Auth、FeatureToggles、通道、ConfirmProvider 等
├── config/                     # API 地址、PERM_* 镜像
├── styles/
│   ├── design-system/          # token、Dialog/EmptyState — 见 design-system.md
│   └── account-page.scss
├── i18n/locales/{en,zh-CN}/    # 按界面划分的 namespace
├── graph/                      # 知识地图共用图模型
└── utils/                      # permissionPatterns 等工具

数据层与 hooks

  • API 调用 — data/*Api.ts 使用 request<T>(path, { query, …init }):合并 auth/locale、credentials: 'include'、query 序列化、统一错误、204 返回 undefined。需 header 或非 JSON 时用 requestRaw / requestText。authAwareFetch 仅在 apiClient.ts 内(401 静默重试、session 过期)。例外: 登录前页面(Login、Signup、OidcCallback)用裸 fetch。
  • 列表页 — 搜索防抖:useDebouncedValue;分页列表:useListFetch(筛选变化自动重置页码)。文档/文章/媒体通道与 glossary 详情已接入。
  • Shell Provider — ConfirmProvider(MainLayout)提供 useConfirm();OntologyMobileRailContext 仅用于本体论侧栏,不用于通道。

约定

  • 新功能页 — pages/<领域>/Feature.tsx + Feature.scss;App.tsx 懒加载路由;data/ 经 request() 发请求;分页列表优先 useListFetch。
  • 样式与布局 — design-system.md;改共享样式或 shell 时跑 check:styles / check:app-layout。
  • 导航与权限 — canAccessPath + 功能开关;以后端权限为准。
  • 命名 — *List / *Detail / *Settings;文档与文章共用通道模式。
  • 去哪查 — 路由 App.tsx;API data/*Api.ts;外壳 components/Layout/;token design-system.md。

国际化(SPA)

SPA 使用 i18next + react-i18next(frontend/src/i18n/):locale en 与 zh-CN,按表面划分 namespace(如 layout、knowledgeBase、wikiSpace),在 frontend/src/i18n/config.ts 注册。登录后语言经 PATCH /api/auth/me 写入 user_preferences(JWT sub),GET /api/auth/me 时恢复;localStorage(openkms_locale)缓存当前 locale 供 Accept-Language(getAuthHeaders)与 profile 加载前首屏。核心 shell 字符串使用翻译键。

后端结构

目录布局(backend/)

层级 作用
app/main.py FastAPI 应用、路由注册、lifespan
app/api/ HTTP 路由 — 按领域分模块(或 admin/ 包);与前端 data/*Api.ts 对应
app/models/ SQLAlchemy ORM — 按表簇分模块
app/schemas/ API 请求/响应的 Pydantic 类型
app/services/ 业务逻辑、LLM、S3、权限与守卫 — 路由保持精简
app/jobs/ procrastinate 应用与延迟任务(run_pipeline、run_kb_index 等)
app/i18n/ 多语言 API 错误目录 + Accept-Language
app/middleware/ 可选的严格权限模式校验
scheduler.py / worker.py 定时调度(单实例)与任务 worker(可扩展)— 见下文
scripts/ 启动辅助(ensure_pgvector.py 等)
backend/
├── app/
│   ├── main.py, config.py, database.py
│   ├── api/
│   │   ├── auth.py, channels.py, documents.py, articles.py, …
│   │   ├── admin/              # 控制台:用户组、安全角色、健康检查
│   │   └── internal/           # 仅 worker / openkms-cli
│   ├── models/                 # document、wiki、knowledge_base、evaluation 等
│   ├── schemas/                # 与 api 领域配对
│   ├── services/
│   │   ├── acl/, documents/, knowledge_bases/, wiki/, ontology/, deep_agents/, connectors/, …  # 每个领域一个包
│   │   └── *.py                # 横切:storage、feature_toggles、chunked_upload、openkms_cli_subprocess
│   ├── jobs/tasks.py
│   ├── i18n/
│   └── middleware/
├── scripts/
├── scheduler.py
└── worker.py

约定

  • 新 HTTP 功能 — 增加 api/<领域>.py 路由、schemas/<领域>.py、新表则改 models/(Alembic 迁移),逻辑放在 services/;在 main.py 注册路由。
  • 权限 — 路由上 require_permission;通道/文档/文章用 context_guard / resource_acl_service 做资源 ACL;目录在 services/permission_*。
  • 分层 — services/、jobs/、schemas/、models/ 不得 import app.api;共享逻辑放在 services/,由 API 模块调用。
  • Channel 树 — 文档、文章、媒体 channel 路由由 api/channel_tree_router.py(ChannelTreeSpec)统一构建;前端共用 ChannelTreeManager、ChannelIndexPage、createChannelTreeContext 与 createChannelTreeApi。
  • 长任务 — API 中 defer 到 jobs/tasks.py;worker 按需拉起 openkms-cli 子进程。
  • 仅内部 — CLI 默认值与凭据在 api/internal/(不对浏览器暴露)。
  • 去哪查 — 路由列表 → app/api/;表结构 → app/models/;副作用 → app/services/;异步任务 → app/jobs/tasks.py。

后台进程: API(uvicorn)提供 HTTP 并维护进程心跳注册表。Scheduler(scheduler.py,单副本)每分钟读取 scheduled_triggers 并 defer 任务。Worker(worker.py,可扩展)只执行 procrastinate 任务,不扫 cron。

公开(无认证)API 布局: 只读无 session 端点(除 auth bootstrap)使用 /api/public/<resource>(如 GET /api/public/system)。启用严格模式时须列入 strict_permission_patterns._UNAUTH_EXACT。

openkms-cli

独立 CLI,供文档解析与后端集成;开发者为流水线步骤添加子命令。

openkms-cli/
├── pyproject.toml           # typer;可选 [parse], [pipeline], [metadata], [kb], [dev]
├── tests/
├── schemas/                 # document_parse_result.schema.json
├── openkms_cli/
│   ├── app.py, settings.py, auth.py, backend_defaults.py
│   ├── baidu_parser.py, parse_result.py, extract.py, parse_cli.py, parser.py
│   ├── office_convert.py    # LibreOffice + mutool → PDF
│   ├── pipeline_cli.py, kb_indexer.py
└── README.md
  • 目的:解析与后端解耦;worker/任务上下文经 subprocess 运行
  • 测试:在 openkms-cli/ 运行 pip install -e ".[dev]" && pytest tests/
  • 配置:settings.py 显式映射环境变量;加载 openkms-cli/.env 与 cwd .env;CLI flag 优先
  • 命令:parse run、pipeline list、pipeline run
  • Pipeline run:S3 下载 →(可选 Office/EPUB 转 PDF)→ 解析 → 上传 S3;通道有 extraction 时 worker 传 --extract-metadata;解析成功后抽取失败仅记日志不失败任务
  • 输出:result.json、markdown.md、layout 等(与 openKMS backend 兼容)
  • KB 索引:kb-index 流水线;wiki 可按 space 重索引
  • 扩展:在 app.py 注册新 Typer 子应用

openkms-skill(Agent Skill + CLI)

可选目录 openkms-skill/(不在 Docker 栈)按 agentskills.io 打包 Python CLI + SKILL.md,调用与 SPA 相同的 /api/...,使用个人 API 密钥(Settings → API keys)。安装:./install.sh(Claude Code / OpenCode)或 ./package.sh 上传到 Agents → Skills。

完整说明:openkms-skill。与 openkms-cli(worker 子进程、internal + public API 环境认证)不同。

QA Agent 服务

qa-agent/
├── pyproject.toml
├── qa_agent/
│   ├── main.py              # /ask、/ask/stream (NDJSON)
│   ├── config.py, agent.py, retriever.py, ontology_client.py, tools.py, schemas.py
├── .env.example
└── README.md
  • 目的:独立 RAG + 本体服务,供知识库问答;经 KB 的 agent_url 配置
  • 架构:LangGraph:retrieve → generate ⇄ tools(本体)。RAG 经 POST /api/knowledge-bases/{id}/search;本体经 object-types、link-types、ontology/explore(Cypher)。不直连数据库。
  • 本体技能:覆盖类问题先 get_ontology_schema_tool 再 run_cypher_tool 查 Neo4j。
  • 集成:后端代理 POST …/ask 与 …/ask/stream 到 qa-agent,转发用户 token;持久化线程经 agent-conversations/.../messages 存 PostgreSQL 并转发 NDJSON。SPA 全页 Q&A 与项目 Agent 共用 delta / tool_* / done 形状。
  • 端口:默认 8103

数据流

文档上传(解耦)

sequenceDiagram
  participant U as 用户
  participant FE as 前端
  participant BE as 后端
  participant S3 as S3/MinIO
  participant DB as PostgreSQL
  participant Q as procrastinate

  U->>FE: 选文件、选通道
  FE->>BE: POST /api/documents/upload
  BE->>S3: 存 {file_hash}/original.{ext}
  BE->>DB: 创建 Document (status=uploaded)
  alt channel.auto_process && pipeline_id
    BE->>Q: defer run_pipeline
    BE->>DB: status=pending
  end
  BE-->>FE: DocumentResponse
  1. 前端在通道页打开上传;POST /api/documents/upload(multipart:file + channel_id)
  2. 后端存 S3 {file_hash}/original.{ext};创建 status=uploaded 的 Document(上传时不解析)
  3. 通道 auto_process=true 且有关联 pipeline 时自动 defer 任务(status=pending)
  4. 返回 DocumentResponse

文档处理(任务队列)

sequenceDiagram
  participant Q as procrastinate worker
  participant DB as PostgreSQL
  participant CLI as openkms-cli
  participant S3 as S3/MinIO
  participant VLM as mlx-vlm-server
  participant BE as Backend API

  Q->>DB: 领取任务, status=running
  Q->>CLI: spawn pipeline run
  CLI->>S3: 下载原件
  CLI->>VLM: 解析 (PaddleOCR-VL)
  VLM-->>CLI: Markdown, layout
  CLI->>S3: 上传 result.json, markdown.md, images
  alt 启用 extraction
    CLI->>BE: PUT metadata / markdown
  end
  Q->>S3: 读 result.json
  Q->>DB: status=completed
  1. 任务来源:POST /api/jobs 或上传时自动(auto_process)
  2. 任务引用 Pipeline(命令模板、{variable}、default_args、可选 model)
  3. Worker 渲染命令、设 status=running
  4. 有 extraction 时 worker 追加 --extract-metadata 等参数
  5. Worker spawn 命令(如 openkms-cli pipeline run --pipeline-name paddleocr-doc-parse …)
  6. CLI 认证(OIDC client credentials 或 local Basic)→ 解析 → 上传 S3;经 PUT /internal-api/documents/{id}/markdown、metadata 同步(internal 服务客户端;无通道写 ACL)
  7. Worker 读 result.json,更新 Document(status=completed)
  8. 失败:status=failed;可 POST /api/jobs/{id}/retry

文档详情

  1. GET /api/documents/{id} — 含 parsing_result、markdown、status
  2. 文件经 GET /api/documents/{id}/files/... → presigned 302
  3. uploaded/failed 显示「Process」;pending/failed 且无活跃任务可「Reset」
  4. 元数据:统一 METADATA;POST extract-metadata;PUT metadata 手工编辑
  5. 名称 PUT /api/documents/{id};markdown 编辑/保存/从 S3 恢复
  6. 版本:显式快照 POST .../versions;列表、预览、恢复

通道树

  1. DocumentChannelsContext → GET /api/document-channels
  2. 嵌套 ChannelNode[]
  3. Sidebar 与文档页用 channelUtils

按通道文档列表

  • GET /api/documents?channel_id=;可选 search;limit 默认 200
  • 返回通道及子孙(或无 channel 时全部)

认证(OPENKMS_AUTH_MODE)

两种模式(默认 oidc)。部署须保持 backend OPENKMS_AUTH_MODE 与 frontend 一致:SPA 调用 GET /api/auth/public-config(无 auth)取 auth_mode、allow_signup。openkms-cli 与 qa-agent 仅用 internal service auth 访问 /internal-api/models/...(sub=local-cli 的 Basic,或 azp 在 OPENKMS_INTERNAL_SERVICE_CLIENT_IDS 的 OIDC client credentials);人类 SPA token 拒绝。/internal-api 不在可选严格 permission 中间件内(仅查 /api/...)。SPA 可 GET /api/public/system 取 system_name。应用据 API 在 OIDC(Authorization Code + PKCE,oidc-client-ts) 与本地表单间切换;VITE_AUTH_MODE 仅 API 失败时回退,且与 backend 不一致时横幅提示。

OIDC 模式

flowchart LR
  subgraph UserFlow["用户认证流"]
    U[用户] -->|"kc.login()"| KC[OIDC IdP]
    KC -->|"Auth Code + PKCE"| FE[前端]
    FE -->|"Bearer JWT"| BE[后端 API]
    FE -->|"POST /sync-session"| BE
  end

  subgraph BackendAuth["后端接受"]
    BE
    BE -->|"JWT 或 session cookie"| JWKS[IdP JWKS]
  end

  subgraph CLIAuth["openkms-cli (worker)"]
    CLI[openkms-cli] -->|"Client credentials"| KC
    CLI -->|"Bearer token"| BE
  end
  • 后端:解析 issuer、discovery、JWKS 校验 JWT;可选 session cookie(POST /sync-session)
  • 前端:oidc-client-ts;redirect /auth/callback、/auth/silent-renew
  • GET /login、OAuth callback、GET /logout 等

Local 模式

  • 后端:users 表、bcrypt、HS256 JWT(OPENKMS_SECRET_KEY)
  • 端点:register、login、me、logout、sync-session
  • CLI:OPENKMS_CLI_BASIC_* → Basic(仅可信网络)
  • 前端:/login、/signup;allow_signup 控制注册
  • OIDC 路由在 local 模式重定向到 /login?notice=local_auth

共用

  • API 上无效 JWT:authAwareFetch 对 session 类 401 先静默重试(OIDC signinSilent + sync-session;local 查 me);仍失败则清 session、toast、跳转登录;返回合成 401(SESSION_EXPIRED_API_DETAIL)
  • 路由保护:/ 对访客公开;其余 MainLayout 页需认证
  • Console:OIDC admin 或 local is_admin / user_security_roles
  • POST /clear-session 清 cookie

配置

层 配置
Backend .env / OPENKMS_* — 数据库、OPENKMS_VLM_URL(mlx-vlm;非 embedding 网关)、Paddle 默认、OPENKMS_PIPELINE_TIMEOUT_SECONDS 等。不用: OPENKMS_VLM_API_KEY、OPENKMS_EMBEDDING_MODEL_*(CLI/KB 模型)
Backend OPENKMS_DEBUG、OPENKMS_SQL_ECHO、OPENKMS_PERMISSION_CATALOG_CACHE_SECONDS
Backend OPENKMS_AUTH_MODE、OPENKMS_ALLOW_SIGNUP、OPENKMS_CLI_BASIC_*、OPENKMS_LOCAL_JWT_EXP_HOURS
Backend OPENKMS_OIDC_*、OPENKMS_FRONTEND_URL、AWS_*(S3/MinIO)
Frontend config/index.ts — apiUrl、authMode 回退、oidc(VITE_OIDC_*);运行时来自 public-config
Vite dev 代理 /api、/internal-api、session 路由 → 8102;/buckets/openkms → MinIO 9000
Alembic alembic.ini — settings.database_url_sync
AI agents 仓库根目录 AGENTS.md — 编码、提交前文档、Alembic、前端验证规则