feat: 引入 LITE_MODE 以有条件地启用/禁用知识图谱和向量数据库组件,更新 Docker Compose、后端路由器和前端 UI。

This commit is contained in:
Wenjie Zhang 2026-03-19 04:11:30 +08:00
parent 62bb928064
commit 6a30936a49
10 changed files with 108 additions and 44 deletions

View File

@ -1,5 +1,5 @@
.PHONY: up down logs lint format
.PHONY: up up-lite down logs lint format
PYTEST_ARGS ?=
@ -13,6 +13,13 @@ up:
down:
docker compose down
up-lite:
@if [ ! -f .env ]; then \
echo "Error: .env file not found. Please create it from .env.template"; \
exit 1; \
fi
LITE_MODE=true docker compose up -d postgres redis minio api worker web
logs:
@docker logs --tail=50 api-dev
@echo "\n\nBranch: $$(git branch --show-current)"

View File

@ -2,15 +2,20 @@ import os
from ..config import config
from .factory import KnowledgeBaseFactory
from .graphs.upload_graph_service import UploadGraphService
from .implementations.dify import DifyKB
from .implementations.lightrag import LightRagKB
from .implementations.milvus import MilvusKB
from .manager import KnowledgeBaseManager
# 注册知识库类型
KnowledgeBaseFactory.register("milvus", MilvusKB, {"description": "基于 Milvus 的生产级向量知识库,适合高性能部署"})
KnowledgeBaseFactory.register("lightrag", LightRagKB, {"description": "基于图检索的知识库,支持实体关系构建和复杂查询"})
_LITE_MODE = os.environ.get("LITE_MODE", "").lower() in ("true", "1")
if not _LITE_MODE:
from .graphs.upload_graph_service import UploadGraphService
from .implementations.lightrag import LightRagKB
from .implementations.milvus import MilvusKB
# 注册知识库类型
KnowledgeBaseFactory.register("milvus", MilvusKB, {"description": "基于 Milvus 的生产级向量知识库,适合高性能部署"})
KnowledgeBaseFactory.register("lightrag", LightRagKB, {"description": "基于图检索的知识库,支持实体关系构建和复杂查询"})
KnowledgeBaseFactory.register("dify", DifyKB, {"description": "连接 Dify Dataset 的只读检索知识库"})
# 创建知识库管理器
@ -18,9 +23,25 @@ work_dir = os.path.join(config.save_dir, "knowledge_base_data")
knowledge_base = KnowledgeBaseManager(work_dir)
# 创建图数据库实例
graph_base = UploadGraphService()
if _LITE_MODE:
from ..utils import logger
# 向后兼容:让 GraphDatabase 指向 UploadGraphService
GraphDatabase = UploadGraphService
class _LiteGraphStub:
"""Lite 模式下的图数据库占位实例,所有操作报告为不可用"""
__all__ = ["GraphDatabase", "UploadGraphService", "knowledge_base", "graph_base"]
def is_running(self):
return False
def get_graph_info(self, *args, **kwargs):
return None
graph_base = _LiteGraphStub()
# 向后兼容
GraphDatabase = _LiteGraphStub
logger.info("LITE_MODE enabled, knowledge graph services disabled")
else:
graph_base = UploadGraphService()
# 向后兼容:让 GraphDatabase 指向 UploadGraphService
GraphDatabase = UploadGraphService
__all__ = ["GraphDatabase", "knowledge_base", "graph_base"]

View File

@ -155,6 +155,9 @@ class Neo4jConnectionManager:
def __init__(self):
self.driver = None
self.status = "closed"
if os.environ.get("LITE_MODE", "").lower() in ("true", "1"):
logger.info("LITE_MODE enabled, skipping Neo4j connection")
return
self._connect()
def _connect(self):

View File

@ -1,20 +1,20 @@
import os
from fastapi import APIRouter
from server.routers.auth_router import auth
from server.routers.chat_router import chat
from server.routers.dashboard_router import dashboard
from server.routers.department_router import department
from server.routers.graph_router import graph
from server.routers.knowledge_router import knowledge
from server.routers.evaluation_router import evaluation
from server.routers.mcp_router import mcp
from server.routers.mindmap_router import mindmap
from server.routers.skill_router import skills
from server.routers.subagent_router import subagents_router
from server.routers.system_router import system
from server.routers.task_router import tasks
from server.routers.tool_router import tools
_LITE_MODE = os.environ.get("LITE_MODE", "").lower() in ("true", "1")
router = APIRouter()
# 注册路由结构
@ -23,12 +23,20 @@ router.include_router(auth) # /api/auth/*
router.include_router(chat) # /api/chat/*
router.include_router(dashboard) # /api/dashboard/*
router.include_router(department) # /api/departments/*
router.include_router(knowledge) # /api/knowledge/*
router.include_router(evaluation) # /api/evaluation/*
router.include_router(mindmap) # /api/mindmap/*
router.include_router(graph) # /api/graph/*
router.include_router(tasks) # /api/tasks/*
router.include_router(mcp) # /api/system/mcp-servers/*
router.include_router(skills) # /api/system/skills/*
router.include_router(subagents_router) # /api/system/subagents/*
router.include_router(tools) # /api/system/tools/*
if not _LITE_MODE:
from server.routers.graph_router import graph
from server.routers.knowledge_router import knowledge
from server.routers.evaluation_router import evaluation
from server.routers.mindmap_router import mindmap
router.include_router(knowledge) # /api/knowledge/*
router.include_router(evaluation) # /api/evaluation/*
router.include_router(mindmap) # /api/mindmap/*
router.include_router(graph) # /api/graph/*

View File

@ -37,10 +37,14 @@ async def lifespan(app: FastAPI):
raise
# 初始化知识库管理器
try:
await knowledge_base.initialize()
except Exception as e:
logger.error(f"Failed to initialize knowledge base manager: {e}")
import os
if os.environ.get("LITE_MODE", "").lower() in ("true", "1"):
logger.info("LITE_MODE enabled, skipping knowledge base initialization")
else:
try:
await knowledge_base.initialize()
except Exception as e:
logger.error(f"Failed to initialize knowledge base manager: {e}")
# 预热 Redisrun 队列)
try:

View File

@ -58,8 +58,6 @@ services:
condition: service_healthy
redis:
condition: service_healthy
milvus:
condition: service_healthy
minio:
condition: service_healthy
@ -88,6 +86,7 @@ services:
- .env
environment:
- HOST_IP=${HOST_IP:-}
- LITE_MODE=${LITE_MODE:-}
- POSTGRES_URL=${POSTGRES_URL:-postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-yuxi_know}}
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
- RUN_EVENTS_STREAM_TTL_SECONDS=${RUN_EVENTS_STREAM_TTL_SECONDS:-7200}
@ -114,8 +113,6 @@ services:
condition: service_healthy
redis:
condition: service_healthy
milvus:
condition: service_healthy
minio:
condition: service_healthy
@ -141,11 +138,14 @@ services:
- NODE_ENV=development
- VITE_API_URL=http://api:5050
- VITE_USE_RUNS_API=${VITE_USE_RUNS_API:-false}
- VITE_LITE_MODE=${LITE_MODE:-}
command: pnpm run server
restart: unless-stopped
# region neo4j
graph:
profiles:
- full
image: neo4j:5.26
container_name: graph
ports:
@ -171,6 +171,8 @@ services:
# endregion neo4j
etcd:
profiles:
- full
container_name: milvus-etcd-dev
image: quay.io/coreos/etcd:v3.5.5
environment:
@ -215,6 +217,8 @@ services:
restart: unless-stopped
milvus:
profiles:
- full
image: milvusdb/milvus:v2.5.6
container_name: milvus
command: ["milvus", "run", "standalone"]

View File

@ -72,6 +72,16 @@ docker compose up --build -d
服务首次启动需要等待镜像拉取和编译,请耐心等待 2-3 分钟。
::: tip 轻量模式Lite Mode
如果你不需要知识库和知识图谱功能,可以使用轻量模式启动,跳过 Milvus、Neo4j、etcd 等服务,节省系统资源:
```bash
make up-lite
```
轻量模式仅启动核心服务前端、后端、PostgreSQL、Redis、MinIO前端侧边栏会自动隐藏知识库和图谱入口。切换回完整模式只需运行 `make up`
:::
### 步骤四:访问系统
服务启动后,访问以下地址:

View File

@ -71,7 +71,7 @@ images=(
# Pull each image
for image in "${images[@]}"; do
echo "🔄 Pulling ${image}..."
if bash docker/pull_image.sh "$image"; then
if bash scripts/pull_image.sh "$image"; then
echo "✅ Successfully pulled ${image}"
else
echo "❌ Failed to pull ${image}"

View File

@ -99,6 +99,8 @@ console.log(route)
const activeTaskCount = computed(() => activeCountRef.value || 0)
//
const isLiteMode = import.meta.env.VITE_LITE_MODE === 'true'
const mainList = computed(() => {
const items = [
{
@ -110,20 +112,22 @@ const mainList = computed(() => {
]
if (userStore.isAdmin) {
items.push(
{
name: '图谱',
path: '/graph',
icon: Waypoints,
activeIcon: Waypoints
},
{
name: '知识库',
path: '/database',
icon: LibraryBig,
activeIcon: LibraryBig
}
)
if (!isLiteMode) {
items.push(
{
name: '图谱',
path: '/graph',
icon: Waypoints,
activeIcon: Waypoints
},
{
name: '知识库',
path: '/database',
icon: LibraryBig,
activeIcon: LibraryBig
}
)
}
if (userStore.isSuperAdmin) {
items.push({

View File

@ -40,9 +40,9 @@
<div class="card-side is-form">
<div class="form-wrapper">
<header class="form-header">
<p class="welcome-text">欢迎登录</p>
<!-- 如果是在初始化显示特定标题 -->
<h2 v-if="isFirstRun" class="init-title">系统初始化请创建超级管理员</h2>
<p v-else class="welcome-text">欢迎登录</p>
</header>
<div class="login-content" :class="{ 'is-initializing': isFirstRun }">
@ -651,7 +651,6 @@ onUnmounted(() => {
width: 900px;
max-width: 95vw;
height: 560px;
max-height: 80vh;
background: var(--gray-0);
border-radius: 16px;
box-shadow: 0 0px 40px var(--shadow-1);
@ -729,6 +728,10 @@ onUnmounted(() => {
}
}
.login-form.login-form--init :deep(.ant-form-item) {
margin-bottom: 14px;
}
.third-party-login {
margin-top: 16px;
.divider {