Revert "fix(graph): 增加知识图谱禁用模式与降级路径"

This reverts commit 835f0786b2.
This commit is contained in:
肖泽涛 2026-03-01 17:53:40 +08:00
parent 76e247052e
commit 97cea83285
8 changed files with 11 additions and 106 deletions

View File

@ -5,8 +5,6 @@ RUN_EVENTS_STREAM_TTL_SECONDS=7200
RUN_CANCEL_KEY_TTL_SECONDS=1800 RUN_CANCEL_KEY_TTL_SECONDS=1800
LANGGRAPH_CHECKPOINTER_BACKEND=postgres LANGGRAPH_CHECKPOINTER_BACKEND=postgres
VITE_USE_RUNS_API=false VITE_USE_RUNS_API=false
YUXI_ENABLE_LIGHTRAG=true
YUXI_ENABLE_KNOWLEDGE_GRAPH=true
# region model_provider # region model_provider
SILICONFLOW_API_KEY= # 推荐使用硅基流动免费服务 https://cloud.siliconflow.cn/i/Eo5yTHGJ SILICONFLOW_API_KEY= # 推荐使用硅基流动免费服务 https://cloud.siliconflow.cn/i/Eo5yTHGJ

View File

@ -30,11 +30,6 @@ cp .env.template .env.prod
- `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY`: 修改默认密钥 - `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY`: 修改默认密钥
- `SILICONFLOW_API_KEY` 等模型密钥 - `SILICONFLOW_API_KEY` 等模型密钥
如果希望以最小资源模式运行(禁用 LightRAG 和知识图谱),可额外设置:
- `YUXI_ENABLE_LIGHTRAG=false`
- `YUXI_ENABLE_KNOWLEDGE_GRAPH=false`
### 2. 启动服务 ### 2. 启动服务
使用 `docker-compose.prod.yml` 文件启动生产环境: 使用 `docker-compose.prod.yml` 文件启动生产环境:
@ -47,13 +42,6 @@ docker compose -f docker-compose.prod.yml up -d --build
docker compose -f docker-compose.prod.yml --profile all up -d --build docker compose -f docker-compose.prod.yml --profile all up -d --build
``` ```
最小资源模式(不启动 Neo4j 图数据库)可使用:
```bash
docker compose -f docker-compose.prod.yml up -d --build \
api worker web postgres redis etcd minio milvus
```
### 3. 验证部署 ### 3. 验证部署
- **Web 访问**: `http://localhost` (直接通过 80 端口访问,无需 :5173) - **Web 访问**: `http://localhost` (直接通过 80 端口访问,无需 :5173)

View File

@ -13,14 +13,6 @@ from src.utils.logging_config import logger
graph = APIRouter(prefix="/graph", tags=["graph"]) graph = APIRouter(prefix="/graph", tags=["graph"])
def _is_graph_feature_enabled() -> bool:
return bool(getattr(graph_base, "feature_enabled", True))
def _graph_disabled_detail() -> str:
return str(getattr(graph_base, "reason", "知识图谱功能已禁用"))
# ============================================================================= # =============================================================================
# === 统一图谱接口 (Unified Graph API) === # === 统一图谱接口 (Unified Graph API) ===
# ============================================================================= # =============================================================================
@ -36,9 +28,6 @@ async def _get_graph_adapter(db_id: str) -> GraphAdapter:
Returns: Returns:
GraphAdapter: 对应的图谱适配器实例 GraphAdapter: 对应的图谱适配器实例
""" """
if not _is_graph_feature_enabled():
raise HTTPException(status_code=503, detail=_graph_disabled_detail())
# 检查图数据库服务状态 (仅对 Upload 类型需要) # 检查图数据库服务状态 (仅对 Upload 类型需要)
if not graph_base.is_running(): if not graph_base.is_running():
# 先尝试检测图谱类型,如果是不需要 graph_base 的类型则允许 # 先尝试检测图谱类型,如果是不需要 graph_base 的类型则允许
@ -69,9 +58,6 @@ async def get_graphs(current_user: User = Depends(get_admin_user)):
包含所有图谱信息的列表 (包括 Neo4j LightRAG)以及每个类型的 capability 信息 包含所有图谱信息的列表 (包括 Neo4j LightRAG)以及每个类型的 capability 信息
""" """
try: try:
if not _is_graph_feature_enabled():
return {"success": True, "data": []}
graphs = [] graphs = []
# 1. 获取默认 Neo4j 图谱信息 (Upload 类型) # 1. 获取默认 Neo4j 图谱信息 (Upload 类型)
@ -249,9 +235,6 @@ async def get_neo4j_node(
async def get_neo4j_info(current_user: User = Depends(get_admin_user)): async def get_neo4j_info(current_user: User = Depends(get_admin_user)):
"""获取Neo4j图数据库信息""" """获取Neo4j图数据库信息"""
try: try:
if not _is_graph_feature_enabled():
raise HTTPException(status_code=503, detail=_graph_disabled_detail())
graph_info = graph_base.get_graph_info() graph_info = graph_base.get_graph_info()
if graph_info is None: if graph_info is None:
raise HTTPException(status_code=400, detail="图数据库获取出错") raise HTTPException(status_code=400, detail="图数据库获取出错")
@ -265,9 +248,6 @@ async def get_neo4j_info(current_user: User = Depends(get_admin_user)):
async def index_neo4j_entities(data: dict = Body(default={}), current_user: User = Depends(get_admin_user)): async def index_neo4j_entities(data: dict = Body(default={}), current_user: User = Depends(get_admin_user)):
"""为Neo4j图谱节点添加嵌入向量索引""" """为Neo4j图谱节点添加嵌入向量索引"""
try: try:
if not _is_graph_feature_enabled():
raise HTTPException(status_code=503, detail=_graph_disabled_detail())
if not graph_base.is_running(): if not graph_base.is_running():
raise HTTPException(status_code=400, detail="图数据库未启动") raise HTTPException(status_code=400, detail="图数据库未启动")
@ -295,9 +275,6 @@ async def add_neo4j_entities(
): ):
"""通过JSONL文件添加图谱实体到Neo4j只接受 MinIO URL""" """通过JSONL文件添加图谱实体到Neo4j只接受 MinIO URL"""
try: try:
if not _is_graph_feature_enabled():
raise HTTPException(status_code=503, detail=_graph_disabled_detail())
# 服务层会验证 URL 并从 MinIO 下载文件 # 服务层会验证 URL 并从 MinIO 下载文件
await graph_base.jsonl_file_add_entity(file_path, kgdb_name, embed_model_name, batch_size) await graph_base.jsonl_file_add_entity(file_path, kgdb_name, embed_model_name, batch_size)
return {"success": True, "message": "实体添加成功", "status": "success"} return {"success": True, "message": "实体添加成功", "status": "success"}

View File

@ -4,6 +4,7 @@ from fastapi import FastAPI
from src.services.task_service import tasker from src.services.task_service import tasker
from src.services.mcp_service import init_mcp_servers from src.services.mcp_service import init_mcp_servers
from src.services.skill_service import init_skills_cache
from src.services.run_queue_service import close_queue_clients, get_redis_client from src.services.run_queue_service import close_queue_clients, get_redis_client
from src.storage.postgres.manager import pg_manager from src.storage.postgres.manager import pg_manager
from src.knowledge import knowledge_base from src.knowledge import knowledge_base

View File

@ -342,10 +342,12 @@ def gen_tool_info(tools) -> list[dict[str, Any]]:
def get_buildin_tools() -> list: def get_buildin_tools() -> list:
"""注册静态工具""" """注册静态工具"""
static_tools = [get_approved_user_goal, calculator, text_to_img_demo] static_tools = [
query_knowledge_graph,
if bool(getattr(graph_base, "feature_enabled", True)): get_approved_user_goal,
static_tools.insert(0, query_knowledge_graph) calculator,
text_to_img_demo,
]
# subagents 工具 # subagents 工具
from .subagents import calc_agent_tool from .subagents import calc_agent_tool

View File

@ -3,49 +3,24 @@ import os
from ..config import config from ..config import config
from .factory import KnowledgeBaseFactory from .factory import KnowledgeBaseFactory
from .implementations.dify import DifyKB from .implementations.dify import DifyKB
from .implementations.lightrag import LightRagKB
from .implementations.milvus import MilvusKB from .implementations.milvus import MilvusKB
from .manager import KnowledgeBaseManager from .manager import KnowledgeBaseManager
from .services.disabled_graph_service import DisabledGraphService
from .services.upload_graph_service import UploadGraphService from .services.upload_graph_service import UploadGraphService
from src.utils import logger
def _env_enabled(name: str, default: bool = True) -> bool:
value = os.getenv(name)
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}
LIGHTRAG_ENABLED = _env_enabled("YUXI_ENABLE_LIGHTRAG", default=True)
KNOWLEDGE_GRAPH_ENABLED = _env_enabled("YUXI_ENABLE_KNOWLEDGE_GRAPH", default=True)
# 注册知识库类型 # 注册知识库类型
KnowledgeBaseFactory.register("milvus", MilvusKB, {"description": "基于 Milvus 的生产级向量知识库,适合高性能部署"}) KnowledgeBaseFactory.register("milvus", MilvusKB, {"description": "基于 Milvus 的生产级向量知识库,适合高性能部署"})
KnowledgeBaseFactory.register("lightrag", LightRagKB, {"description": "基于图检索的知识库,支持实体关系构建和复杂查询"})
KnowledgeBaseFactory.register("dify", DifyKB, {"description": "连接 Dify Dataset 的只读检索知识库"}) KnowledgeBaseFactory.register("dify", DifyKB, {"description": "连接 Dify Dataset 的只读检索知识库"})
if LIGHTRAG_ENABLED:
from .implementations.lightrag import LightRagKB
KnowledgeBaseFactory.register("lightrag", LightRagKB, {"description": "基于图检索的知识库,支持实体关系构建和复杂查询"})
else:
logger.info("LightRAG feature disabled by YUXI_ENABLE_LIGHTRAG=false")
# 创建知识库管理器 # 创建知识库管理器
work_dir = os.path.join(config.save_dir, "knowledge_base_data") work_dir = os.path.join(config.save_dir, "knowledge_base_data")
knowledge_base = KnowledgeBaseManager(work_dir) knowledge_base = KnowledgeBaseManager(work_dir)
# 创建图数据库实例 # 创建图数据库实例
if KNOWLEDGE_GRAPH_ENABLED: graph_base = UploadGraphService()
try:
graph_base = UploadGraphService()
except Exception as e:
logger.warning(f"Knowledge graph init failed, fallback to disabled mode: {e}")
graph_base = DisabledGraphService(reason=f"知识图谱服务不可用: {e}")
else:
graph_base = DisabledGraphService(reason="知识图谱功能已禁用YUXI_ENABLE_KNOWLEDGE_GRAPH=false")
# 向后兼容:让 GraphDatabase 指向 UploadGraphService # 向后兼容:让 GraphDatabase 指向 UploadGraphService
GraphDatabase = UploadGraphService if KNOWLEDGE_GRAPH_ENABLED else DisabledGraphService GraphDatabase = UploadGraphService
__all__ = ["GraphDatabase", "UploadGraphService", "knowledge_base", "graph_base"] __all__ = ["GraphDatabase", "UploadGraphService", "knowledge_base", "graph_base"]

View File

@ -55,9 +55,6 @@ class KnowledgeBaseManager:
kb_types_in_use = set() kb_types_in_use = set()
for row in rows: for row in rows:
kb_type = row.kb_type or "lightrag" kb_type = row.kb_type or "lightrag"
if not KnowledgeBaseFactory.is_type_supported(kb_type):
logger.warning(f"[InitializeKB] 跳过未启用的知识库类型: {kb_type}")
continue
kb_types_in_use.add(kb_type) kb_types_in_use.add(kb_type)
logger.info(f"[InitializeKB] 发现 {len(kb_types_in_use)} 种知识库类型: {kb_types_in_use}") logger.info(f"[InitializeKB] 发现 {len(kb_types_in_use)} 种知识库类型: {kb_types_in_use}")
@ -182,9 +179,6 @@ class KnowledgeBaseManager:
metadata_reloaded_types: set[str] = set() metadata_reloaded_types: set[str] = set()
for row in rows: for row in rows:
kb_type = row.kb_type or "lightrag" kb_type = row.kb_type or "lightrag"
if not KnowledgeBaseFactory.is_type_supported(kb_type):
logger.warning(f"Skip database due to unsupported kb_type: db_id={row.db_id}, kb_type={kb_type}")
continue
kb_instance = self._get_or_create_kb_instance(kb_type) kb_instance = self._get_or_create_kb_instance(kb_type)
db_info = kb_instance.get_database_info(row.db_id) db_info = kb_instance.get_database_info(row.db_id)
if not db_info and kb_type not in metadata_reloaded_types: if not db_info and kb_type not in metadata_reloaded_types:

View File

@ -1,30 +0,0 @@
class DisabledGraphService:
"""禁用态图谱服务,占位实现。"""
feature_enabled = False
def __init__(self, reason: str = "知识图谱功能已禁用"):
self.reason = reason
def start(self):
return None
def close(self):
return None
def is_running(self):
return False
def get_graph_info(self, graph_name="neo4j"):
return None
def query_node(self, keyword, threshold=0.9, kgdb_name="neo4j", hops=2, max_entities=8, return_format="graph", **kwargs):
if return_format == "triples":
return {"triples": [], "message": self.reason}
return {"nodes": [], "edges": [], "message": self.reason}
async def add_embedding_to_nodes(self, node_names=None, kgdb_name="neo4j", batch_size=None):
raise RuntimeError(self.reason)
async def jsonl_file_add_entity(self, file_path, kgdb_name="neo4j", embed_model_name=None, batch_size=None):
raise RuntimeError(self.reason)