diff --git a/Makefile b/Makefile index 8b743474..f2dd20b9 100644 --- a/Makefile +++ b/Makefile @@ -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)" diff --git a/backend/package/yuxi/knowledge/__init__.py b/backend/package/yuxi/knowledge/__init__.py index e0dc6a0a..abbd3401 100644 --- a/backend/package/yuxi/knowledge/__init__.py +++ b/backend/package/yuxi/knowledge/__init__.py @@ -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"] diff --git a/backend/package/yuxi/knowledge/graphs/adapters/base.py b/backend/package/yuxi/knowledge/graphs/adapters/base.py index bf2d4ad6..9bdf8916 100644 --- a/backend/package/yuxi/knowledge/graphs/adapters/base.py +++ b/backend/package/yuxi/knowledge/graphs/adapters/base.py @@ -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): diff --git a/backend/server/routers/__init__.py b/backend/server/routers/__init__.py index a148c318..7399cf4d 100644 --- a/backend/server/routers/__init__.py +++ b/backend/server/routers/__init__.py @@ -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/* + diff --git a/backend/server/utils/lifespan.py b/backend/server/utils/lifespan.py index afc21140..e1655b5b 100644 --- a/backend/server/utils/lifespan.py +++ b/backend/server/utils/lifespan.py @@ -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}") # 预热 Redis(run 队列) try: diff --git a/docker-compose.yml b/docker-compose.yml index 9bf074ca..42341bc2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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"] diff --git a/docs/intro/quick-start.md b/docs/intro/quick-start.md index 4e10a059..b0e1c39a 100644 --- a/docs/intro/quick-start.md +++ b/docs/intro/quick-start.md @@ -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`。 +::: + ### 步骤四:访问系统 服务启动后,访问以下地址: diff --git a/scripts/init.sh b/scripts/init.sh index ee6b67fc..9a5dfe1a 100644 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -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}" diff --git a/web/src/layouts/AppLayout.vue b/web/src/layouts/AppLayout.vue index ad35e9a6..88abd222 100644 --- a/web/src/layouts/AppLayout.vue +++ b/web/src/layouts/AppLayout.vue @@ -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({ diff --git a/web/src/views/LoginView.vue b/web/src/views/LoginView.vue index d17f5561..77c5ec66 100644 --- a/web/src/views/LoginView.vue +++ b/web/src/views/LoginView.vue @@ -40,9 +40,9 @@
欢迎登录
欢迎登录