[fix] Pydantic save json error

This commit is contained in:
Mark
2026-01-12 15:59:10 +08:00
parent 7a0746cf4e
commit f2390412d2
5 changed files with 105 additions and 22 deletions

25
api/app/base/type.py Normal file
View File

@@ -0,0 +1,25 @@
from pydantic import BaseModel, Field
from sqlalchemy import TypeDecorator, JSON
class PydanticType(TypeDecorator):
impl = JSON
def __init__(self, pydantic_model: type[BaseModel]):
super().__init__()
self.model = pydantic_model
def process_bind_param(self, value, dialect):
# 入库Model -> dict
if value is None:
return None
if isinstance(value, self.model):
return value.dict()
return value # 已经是 dict 也放行
def process_result_value(self, value, dialect):
# 出库dict -> Model
if value is None:
return None
# return self.model.parse_obj(value) # pydantic v1
return self.model.model_validate(value) # pydantic v2

View File

@@ -3,8 +3,9 @@ import uuid
from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSON
from sqlalchemy.orm import relationship
from app.base.type import PydanticType
from app.db import Base
from app.models.multi_agent_model import PydanticType
from app.schemas import ModelParameters

View File

@@ -8,6 +8,7 @@ from sqlalchemy import Column, String, Boolean, DateTime, Integer, Float, Text,
from sqlalchemy.dialects.postgresql import UUID, JSON
from sqlalchemy.orm import relationship
from app.base.type import PydanticType
from app.db import Base
from app.schemas import ModelParameters
@@ -23,27 +24,27 @@ class AggregationStrategy(StrEnum):
VOTE = "vote"
PRIORITY = "priority"
class PydanticType(TypeDecorator):
impl = JSON
# class PydanticType(TypeDecorator):
# impl = JSON
def __init__(self, pydantic_model: type[BaseModel]):
super().__init__()
self.model = pydantic_model
# def __init__(self, pydantic_model: type[BaseModel]):
# super().__init__()
# self.model = pydantic_model
def process_bind_param(self, value, dialect):
# 入库Model -> dict
if value is None:
return None
if isinstance(value, self.model):
return value.dict()
return value # 已经是 dict 也放行
# def process_bind_param(self, value, dialect):
# # 入库Model -> dict
# if value is None:
# return None
# if isinstance(value, self.model):
# return value.dict()
# return value # 已经是 dict 也放行
def process_result_value(self, value, dialect):
# 出库dict -> Model
if value is None:
return None
# return self.model.parse_obj(value) # pydantic v1
return self.model.model_validate(value) # pydantic v2
# def process_result_value(self, value, dialect):
# # 出库dict -> Model
# if value is None:
# return None
# # return self.model.parse_obj(value) # pydantic v1
# return self.model.model_validate(value) # pydantic v2
class MultiAgentConfig(Base):
"""多 Agent 配置表"""

View File

@@ -33,6 +33,7 @@ from app.services.agent_config_converter import AgentConfigConverter
from app.models import AppShare, Workspace
from app.services.model_service import ModelApiKeyService
from app.services.workflow_service import WorkflowService
from app.utils.app_config_utils import model_parameters_to_dict
# 获取业务日志器
logger = get_business_logger()
@@ -1175,7 +1176,7 @@ class AppService:
config = {
"system_prompt": agent_cfg.system_prompt,
"model_parameters": agent_cfg.model_parameters,
"model_parameters": model_parameters_to_dict(agent_cfg.model_parameters),
"knowledge_retrieval": agent_cfg.knowledge_retrieval,
"memory": agent_cfg.memory,
"variables": agent_cfg.variables or [],
@@ -1204,8 +1205,10 @@ class AppService:
default_model_config_id = multi_agent_cfg.default_model_config_id
# 4. 构建配置快照
config = {
"model_parameters":multi_agent_cfg.model_parameters,
"model_parameters": model_parameters_to_dict(multi_agent_cfg.model_parameters),
"master_agent_id": str(multi_agent_cfg.master_agent_id),
"orchestration_mode": multi_agent_cfg.orchestration_mode,
"sub_agents": multi_agent_cfg.sub_agents,

View File

@@ -5,13 +5,66 @@ Utility functions for converting between dict and model objects for different ap
"""
import uuid
from typing import Dict, Any, Optional
from typing import Dict, Any, Optional, Union
from datetime import datetime
from app.models import AppRelease, WorkflowConfig
from app.models.agent_app_config_model import AgentConfig
from app.models.multi_agent_model import MultiAgentConfig
def model_parameters_to_dict(model_parameters: Any) -> Optional[Dict[str, Any]]:
"""将 ModelParameters 对象转换为字典
Args:
model_parameters: ModelParameters 对象、字典或 None
Returns:
字典格式的模型参数,如果输入为 None 则返回 None
"""
if model_parameters is None:
return None
if isinstance(model_parameters, dict):
return model_parameters
# Pydantic v2
if hasattr(model_parameters, 'model_dump'):
return model_parameters.model_dump()
# Pydantic v1
if hasattr(model_parameters, 'dict'):
return model_parameters.dict()
# 其他情况尝试转换
try:
return dict(model_parameters)
except (TypeError, ValueError):
return None
def dict_to_model_parameters(data: Optional[Dict[str, Any]]) -> Optional[Any]:
"""将字典转换为 ModelParameters 对象
Args:
data: 字典格式的模型参数或 None
Returns:
ModelParameters 对象,如果输入为 None 则返回 None
"""
if data is None:
return None
from app.schemas import ModelParameters
if isinstance(data, ModelParameters):
return data
if isinstance(data, dict):
return ModelParameters(**data)
return None
class AgentConfigProxy:
"""Proxy class for AgentConfig (legacy compatibility)"""