From c3707f543c079ac92f91f96c4ad4ed8ebf2f4802 Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Thu, 5 Mar 2026 18:59:23 +0800 Subject: [PATCH] [changes] From the perspective of logical judgment, to determine the situation of duplicate names --- .../controllers/memory_storage_controller.py | 13 +++++++++++ .../controllers/ontology_secondary_routes.py | 23 +++++++++++++++---- api/app/models/memory_config_model.py | 5 +--- api/app/models/ontology_class.py | 5 +--- api/app/services/memory_storage_service.py | 11 +++++++++ 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/api/app/controllers/memory_storage_controller.py b/api/app/controllers/memory_storage_controller.py index 9708b3a5..ee45fb83 100644 --- a/api/app/controllers/memory_storage_controller.py +++ b/api/app/controllers/memory_storage_controller.py @@ -100,6 +100,19 @@ def create_config( svc = DataConfigService(db) result = svc.create(payload) return success(data=result, msg="创建成功") + except ValueError as e: + err_str = str(e) + if err_str.startswith("DUPLICATE_CONFIG_NAME:"): + config_name = err_str.split(":", 1)[1] + api_logger.warning(f"重复的配置名称 '{config_name}' 在工作空间 {workspace_id}") + lang = get_language_from_header(x_language_type) + if lang == "en": + msg = fail(BizCode.BAD_REQUEST, "Config name already exists", f"A config named \"{config_name}\" already exists in the current workspace. Please use a different name.") + else: + msg = fail(BizCode.BAD_REQUEST, "配置名称已存在", f"当前工作空间下已存在名为「{config_name}」的记忆配置,请使用其他名称") + return JSONResponse(status_code=400, content=msg) + api_logger.error(f"Create config failed: {err_str}") + return fail(BizCode.INTERNAL_ERROR, "创建配置失败", err_str) except Exception as e: from sqlalchemy.exc import IntegrityError if isinstance(e, IntegrityError) and "uq_workspace_config_name" in str(getattr(e, 'orig', '')): diff --git a/api/app/controllers/ontology_secondary_routes.py b/api/app/controllers/ontology_secondary_routes.py index 0d752006..2aea77a4 100644 --- a/api/app/controllers/ontology_secondary_routes.py +++ b/api/app/controllers/ontology_secondary_routes.py @@ -265,8 +265,11 @@ async def create_class_handler( ] if count == 1: - # 单个创建 + # 单个创建 - 先检查重名 class_data = classes_data[0] + existing = OntologyClassRepository(db).get_by_name(class_data["class_name"], request.scene_id) + if existing: + raise ValueError(f"DUPLICATE_CLASS_NAME:{class_data['class_name']}") ontology_class = service.create_class( scene_id=request.scene_id, class_name=class_data["class_name"], @@ -324,9 +327,21 @@ async def create_class_handler( return success(data=response.model_dump(mode='json'), msg="批量创建完成") except ValueError as e: - api_logger.warning(f"Validation error in class creation: {str(e)}") - return fail(BizCode.BAD_REQUEST, "请求参数无效", str(e)) - + err_str = str(e) + if err_str.startswith("DUPLICATE_CLASS_NAME:"): + class_name = err_str.split(":", 1)[1] + api_logger.warning(f"Duplicate class name '{class_name}' in scene {request.scene_id}") + from app.core.language_utils import get_language_from_header + from fastapi.responses import JSONResponse + lang = get_language_from_header(x_language_type) + if lang == "en": + msg = fail(BizCode.BAD_REQUEST, "Class name already exists", f"A class named \"{class_name}\" already exists in this scene. Please use a different name.") + else: + msg = fail(BizCode.BAD_REQUEST, "类型名称已存在", f"当前场景下已存在名为「{class_name}」的类型,请使用其他名称") + return JSONResponse(status_code=400, content=msg) + api_logger.warning(f"Validation error in class creation: {err_str}") + return fail(BizCode.BAD_REQUEST, "请求参数无效", err_str) + except RuntimeError as e: err_str = str(e) if "UniqueViolation" in err_str or "uq_scene_class_name" in err_str: diff --git a/api/app/models/memory_config_model.py b/api/app/models/memory_config_model.py index b4b441d5..1095a386 100644 --- a/api/app/models/memory_config_model.py +++ b/api/app/models/memory_config_model.py @@ -1,6 +1,6 @@ import datetime -from sqlalchemy import Boolean, Column, DateTime, Float, Integer, String, UniqueConstraint +from sqlalchemy import Boolean, Column, DateTime, Float, Integer, String from sqlalchemy.dialects.postgresql import UUID from app.db import Base @@ -9,9 +9,6 @@ from app.db import Base class MemoryConfig(Base): """记忆配置表 - 用于存储记忆系统的配置参数""" __tablename__ = "memory_config" - __table_args__ = ( - UniqueConstraint('workspace_id', 'config_name', name='uq_workspace_config_name'), - ) # 主键 config_id = Column(UUID(as_uuid=True), primary_key=True, comment="配置ID") diff --git a/api/app/models/ontology_class.py b/api/app/models/ontology_class.py index eb38d06f..a8468090 100644 --- a/api/app/models/ontology_class.py +++ b/api/app/models/ontology_class.py @@ -9,7 +9,7 @@ Classes: import datetime import uuid -from sqlalchemy import Column, String, DateTime, Text, ForeignKey, Boolean, UniqueConstraint +from sqlalchemy import Column, String, DateTime, Text, ForeignKey, Boolean from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from app.db import Base @@ -18,9 +18,6 @@ from app.db import Base class OntologyClass(Base): """本体类型表 - 用于存储某个场景提取出来的本体类型信息""" __tablename__ = "ontology_class" - __table_args__ = ( - UniqueConstraint('scene_id', 'class_name', name='uq_scene_class_name'), - ) # 主键 class_id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True, comment="类型ID") diff --git a/api/app/services/memory_storage_service.py b/api/app/services/memory_storage_service.py index beedaae9..02fd1051 100644 --- a/api/app/services/memory_storage_service.py +++ b/api/app/services/memory_storage_service.py @@ -115,6 +115,17 @@ class DataConfigService: # 数据配置服务类(PostgreSQL) # --- Create --- def create(self, params: ConfigParamsCreate) -> Dict[str, Any]: # 创建配置参数(仅名称与描述) + # 业务层检查同一工作空间下是否已存在同名配置 + if params.workspace_id and params.config_name: + from app.models.memory_config_model import MemoryConfig + existing = ( + self.db.query(MemoryConfig) + .filter_by(workspace_id=params.workspace_id, config_name=params.config_name) + .first() + ) + if existing: + raise ValueError(f"DUPLICATE_CONFIG_NAME:{params.config_name}") + # 如果workspace_id存在且模型字段未全部指定,则自动获取 if params.workspace_id and not all([params.llm_id, params.embedding_id, params.rerank_id]): configs = self._get_workspace_configs(params.workspace_id)