feat(memory-config): add V1 emotion and reflection engine config endpoints
Add read/update endpoints for emotion engine config (read_config_emotion, update_config_emotion) Add read/update endpoints for reflection engine config (read_config_reflection, update_config_reflection) Add EmotionConfigUpdateRequest and ReflectionConfigUpdateRequest schemas Reuse emotion_config_controller and memory_reflection_controller with ownership verification
This commit is contained in:
@@ -10,7 +10,11 @@ from sqlalchemy.orm import Session
|
||||
from app.controllers import memory_storage_controller
|
||||
from app.controllers import memory_forget_controller
|
||||
from app.controllers import ontology_controller
|
||||
from app.controllers import emotion_config_controller
|
||||
from app.controllers import memory_reflection_controller
|
||||
from app.schemas.memory_storage_schema import ForgettingConfigUpdateRequest
|
||||
from app.controllers.emotion_config_controller import EmotionConfigUpdate
|
||||
from app.schemas.memory_reflection_schemas import Memory_Reflection
|
||||
from app.core.api_key_auth import require_api_key
|
||||
from app.core.error_codes import BizCode
|
||||
from app.core.exceptions import BusinessException
|
||||
@@ -25,6 +29,8 @@ from app.schemas.memory_api_schema import (
|
||||
ListConfigsResponse,
|
||||
ConfigCreateRequest,
|
||||
ConfigUpdateForgettingRequest,
|
||||
EmotionConfigUpdateRequest,
|
||||
ReflectionConfigUpdateRequest,
|
||||
)
|
||||
from app.schemas.memory_storage_schema import (
|
||||
ConfigUpdate,
|
||||
@@ -79,28 +85,28 @@ def _verify_config_ownership(config_id:str, workspace_id:uuid.UUID, db:Session):
|
||||
code=BizCode.MEMORY_CONFIG_NOT_FOUND,
|
||||
)
|
||||
|
||||
@router.get("/configs")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def list_memory_configs(
|
||||
request: Request,
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
List all memory configs for the workspace.
|
||||
# @router.get("/configs")
|
||||
# @require_api_key(scopes=["memory"])
|
||||
# async def list_memory_configs(
|
||||
# request: Request,
|
||||
# api_key_auth: ApiKeyAuth = None,
|
||||
# db: Session = Depends(get_db),
|
||||
# ):
|
||||
# """
|
||||
# List all memory configs for the workspace.
|
||||
|
||||
Returns all available memory configurations associated with the authorized workspace.
|
||||
"""
|
||||
logger.info(f"List configs request - workspace_id: {api_key_auth.workspace_id}")
|
||||
# Returns all available memory configurations associated with the authorized workspace.
|
||||
# """
|
||||
# logger.info(f"List configs request - workspace_id: {api_key_auth.workspace_id}")
|
||||
|
||||
memory_api_service = MemoryAPIService(db)
|
||||
# memory_api_service = MemoryAPIService(db)
|
||||
|
||||
result = memory_api_service.list_memory_configs(
|
||||
workspace_id=api_key_auth.workspace_id,
|
||||
)
|
||||
# result = memory_api_service.list_memory_configs(
|
||||
# workspace_id=api_key_auth.workspace_id,
|
||||
# )
|
||||
|
||||
logger.info(f"Listed {result['total']} configs for workspace: {api_key_auth.workspace_id}")
|
||||
return success(data=ListConfigsResponse(**result).model_dump(), msg="Configs listed successfully")
|
||||
# logger.info(f"Listed {result['total']} configs for workspace: {api_key_auth.workspace_id}")
|
||||
# return success(data=ListConfigsResponse(**result).model_dump(), msg="Configs listed successfully")
|
||||
|
||||
@router.get("/read_all_config")
|
||||
@require_api_key(scopes=["memory"])
|
||||
@@ -171,6 +177,85 @@ async def read_config_extracted(
|
||||
db = db,
|
||||
)
|
||||
|
||||
@router.get("/read_config_forgetting")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def read_config_forgetting(
|
||||
request: Request,
|
||||
config_id: str = Query(..., description="config_id"),
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Get forgetting settings for a specific memory config.
|
||||
|
||||
Only configs belonging to the authorized workspace can be queried.
|
||||
"""
|
||||
logger.info(f"V1 read forgetting config - config_id: {config_id}, workspace: {api_key_auth.workspace_id}")
|
||||
|
||||
_verify_config_ownership(config_id, api_key_auth.workspace_id, db)
|
||||
|
||||
current_user = _get_current_user(api_key_auth, db)
|
||||
|
||||
result = await memory_forget_controller.read_forgetting_config(
|
||||
config_id = config_id,
|
||||
current_user = current_user,
|
||||
db = db,
|
||||
)
|
||||
return jsonable_encoder(result)
|
||||
|
||||
|
||||
|
||||
@router.get("/read_config_emotion")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def read_config_emotion(
|
||||
request: Request,
|
||||
config_id: str = Query(..., description="config_id"),
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Get emotion engine config details for a specific config.
|
||||
|
||||
Only configs belonging to the authorized workspace can be queried.
|
||||
"""
|
||||
logger.info(f"V1 read emotion config - config_id: {config_id}, workspace: {api_key_auth.workspace_id}")
|
||||
|
||||
_verify_config_ownership(config_id, api_key_auth.workspace_id, db)
|
||||
|
||||
current_user = _get_current_user(api_key_auth, db)
|
||||
|
||||
return jsonable_encoder(emotion_config_controller.get_emotion_config(
|
||||
config_id=config_id,
|
||||
db=db,
|
||||
current_user=current_user,
|
||||
))
|
||||
|
||||
@router.get("/read_config_reflection")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def read_config_reflection(
|
||||
request: Request,
|
||||
config_id: str = Query(..., description="config_id"),
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Get reflection engine config details for a specific config.
|
||||
|
||||
Only configs belonging to the authorized workspace can be queried.
|
||||
"""
|
||||
logger.info(f"V1 read reflection config - config_id: {config_id}, workspace: {api_key_auth.workspace_id}")
|
||||
|
||||
_verify_config_ownership(config_id, api_key_auth.workspace_id, db)
|
||||
|
||||
current_user = _get_current_user(api_key_auth, db)
|
||||
|
||||
return jsonable_encoder(await memory_reflection_controller.start_reflection_configs(
|
||||
config_id=config_id,
|
||||
current_user=current_user,
|
||||
db=db,
|
||||
))
|
||||
|
||||
|
||||
@router.post("/create_config")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def create_memory_config(
|
||||
@@ -278,6 +363,7 @@ async def update_memory_config_extracted(
|
||||
current_user = current_user,
|
||||
db = db,
|
||||
)
|
||||
|
||||
@router.put("/update_config_forgetting")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def update_memory_config_forgetting(
|
||||
@@ -312,6 +398,66 @@ async def update_memory_config_forgetting(
|
||||
)
|
||||
return jsonable_encoder(result)
|
||||
|
||||
@router.put("/update_config_emotion")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def update_config_emotion(
|
||||
request: Request,
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
message: str = Body(None, description="Request body"),
|
||||
):
|
||||
"""
|
||||
Update emotion engine config (full update).
|
||||
|
||||
All fields except emotion_model_id are required.
|
||||
Only configs belonging to the authorized workspace can be updated.
|
||||
"""
|
||||
body = await request.json()
|
||||
payload = EmotionConfigUpdateRequest(**body)
|
||||
|
||||
logger.info(f"V1 update emotion config - config_id: {payload.config_id}, workspace: {api_key_auth.workspace_id}")
|
||||
|
||||
_verify_config_ownership(payload.config_id, api_key_auth.workspace_id, db)
|
||||
|
||||
current_user = _get_current_user(api_key_auth, db)
|
||||
update_fields = payload.model_dump(exclude_unset=True)
|
||||
mgmt_payload = EmotionConfigUpdate(**update_fields)
|
||||
return jsonable_encoder(emotion_config_controller.update_emotion_config(
|
||||
config=mgmt_payload,
|
||||
db=db,
|
||||
current_user=current_user,
|
||||
))
|
||||
|
||||
@router.put("/update_config_reflection")
|
||||
@require_api_key(scopes=["memory"])
|
||||
async def update_config_reflection(
|
||||
request: Request,
|
||||
api_key_auth: ApiKeyAuth = None,
|
||||
db: Session = Depends(get_db),
|
||||
message: str = Body(None, description="Request body"),
|
||||
):
|
||||
"""
|
||||
Update reflection engine config (full update).
|
||||
|
||||
All fields are required.
|
||||
Only configs belonging to the authorized workspace can be updated.
|
||||
"""
|
||||
body = await request.json()
|
||||
payload = ReflectionConfigUpdateRequest(**body)
|
||||
|
||||
logger.info(f"V1 update reflection config - config_id: {payload.config_id}, workspace: {api_key_auth.workspace_id}")
|
||||
|
||||
_verify_config_ownership(payload.config_id, api_key_auth.workspace_id, db)
|
||||
|
||||
current_user = _get_current_user(api_key_auth, db)
|
||||
update_fields = payload.model_dump(exclude_unset=True)
|
||||
mgmt_payload = Memory_Reflection(**update_fields)
|
||||
|
||||
return jsonable_encoder(await memory_reflection_controller.save_reflection_config(
|
||||
request=mgmt_payload,
|
||||
current_user=current_user,
|
||||
db=db,
|
||||
))
|
||||
|
||||
@router.delete("/delete_config")
|
||||
@require_api_key(scopes=["memory"])
|
||||
|
||||
@@ -328,7 +328,7 @@ class MemoryConfigRepository:
|
||||
if not db_config:
|
||||
db_logger.warning(f"记忆配置不存在: config_id={update.config_id}")
|
||||
return None
|
||||
|
||||
#TODO:部分更新没有用patch请求,是在Repository层中用先查再部分更新的方式实现的,后续可以考虑改成patch请求更符合RESTful设计原则
|
||||
update_data = update.model_dump(exclude_unset=True)
|
||||
update_data.pop("config_id", None)
|
||||
|
||||
|
||||
@@ -388,4 +388,58 @@ class ConfigUpdateForgettingRequest(BaseModel):
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
return v.strip()
|
||||
|
||||
class EmotionConfigUpdateRequest(BaseModel):
|
||||
"""Request schema for updating memory config emotion parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
emotion_enabled: Whether to enable emotion extraction
|
||||
emotion_model_id: Emotion analysis model ID
|
||||
emotion_extract_keywords: Whether to extract emotion keywords
|
||||
emotion_min_intensity: Minimum emotion intensity threshold (0.0-1.0)
|
||||
emotion_enable_subject: Whether to enable subject classification for emotions
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
emotion_enabled: bool = Field(..., description="Whether to enable emotion extraction")
|
||||
emotion_model_id: Optional[str] = Field(None, description="Emotion analysis model ID")
|
||||
emotion_extract_keywords: bool = Field(..., description="Whether to extract emotion keywords")
|
||||
emotion_min_intensity: float = Field(..., ge=0.0, le=1.0, description="Minimum emotion intensity threshold")
|
||||
emotion_enable_subject: bool = Field(..., description="Whether to enable subject classification for emotions")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class ReflectionConfigUpdateRequest(BaseModel):
|
||||
"""Request schema for updating memory config reflection parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
reflection_enabled: Whether to enable self-reflection
|
||||
reflection_period_in_hours: Reflection iteration period in hours
|
||||
reflexion_range: Reflection range (partial or all)
|
||||
baseline: Baseline for reflection (TIME/FACT/TIME-FACT)
|
||||
reflection_model_id: Reflection model ID
|
||||
memory_verify: Whether to enable memory verification
|
||||
quality_assessment: Whether to enable quality assessment
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
reflection_enabled: bool = Field(..., description="Whether to enable self-reflection")
|
||||
reflection_period_in_hours: str = Field(..., description="Reflection iteration period in hours")
|
||||
reflexion_range: Literal["partial", "all"] = Field(..., description="Reflection range: partial/all")
|
||||
baseline: Literal["TIME", "FACT", "TIME-FACT"] = Field(..., description="Baseline: TIME/FACT/TIME-FACT")
|
||||
reflection_model_id: str = Field(..., description="Reflection model ID")
|
||||
memory_verify: bool = Field(..., description="Whether to enable memory verification")
|
||||
quality_assessment: bool = Field(..., description="Whether to enable quality assessment")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
@@ -291,7 +291,7 @@ class ConfigUpdateExtracted(BaseModel): # 更新记忆萃取引擎配置参数
|
||||
pruning_threshold: Optional[float] = Field(
|
||||
None, ge=0.0, le=0.9, description="智能语义剪枝阈值(0-0.9)"
|
||||
)
|
||||
|
||||
#TODO:萃取引擎的更新的更新会带有反思引擎的参数,需判断业务是否需要,不需要可以重构
|
||||
# 反思配置
|
||||
enable_self_reflexion: Optional[bool] = Field(None, description="是否启用自我反思")
|
||||
iteration_period: Optional[Literal["1", "3", "6", "12", "24"]] = Field(
|
||||
|
||||
Reference in New Issue
Block a user