feat: 人设模板系统、节点调度标签、pydantic-settings收敛、错误处理增强

新增persona_template表和CRUD API,BaseIndividualModel增加node_affinity和template_origin_id字段,
WorkerCluster支持多集群Ray资源调度,环境变量收敛到pydantic-settings统一校验,
数据库异常转换为结构化BusinessError/RetryableError,系统节点支持custom_system_prompt。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 06:07:46 +00:00
parent f3a92a793e
commit 8f1398c591
23 changed files with 582 additions and 48 deletions
@@ -0,0 +1,69 @@
"""add persona_template table, node_affinity and template_origin_id to base_individual
Revision ID: 0003_persona_template
Revises: 0002_graph_and_logs
Create Date: 2026-06-04 00:00:00
"""
from typing import Sequence, Union
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from alembic import op
revision: str = "0003_persona_template"
down_revision: Union[str, None] = "0002_graph_and_logs"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.create_table(
"persona_template",
sa.Column("template_id", sa.String(64), primary_key=True),
sa.Column("name", sa.String(100), nullable=False),
sa.Column("description", sa.Text(), nullable=False, server_default=""),
sa.Column("system_prompt", sa.Text(), nullable=False, server_default=""),
sa.Column("agent_type", sa.String(32), nullable=False, server_default="ordinary"),
sa.Column("provider_title", sa.String(50), nullable=True),
sa.Column("model_id", sa.String(100), nullable=True),
sa.Column("tools", postgresql.JSONB(), nullable=True, server_default="'[]'::jsonb"),
sa.Column("tags", postgresql.JSONB(), nullable=True, server_default="'[]'::jsonb"),
sa.Column("is_builtin", sa.Boolean(), nullable=False, server_default="false"),
sa.Column("owner_id", sa.String(64), nullable=True),
)
op.create_index("ix_persona_template_name", "persona_template", ["name"])
op.create_index("ix_persona_template_owner_id", "persona_template", ["owner_id"])
op.add_column(
"base_individual",
sa.Column("node_affinity", sa.String(32), nullable=False, server_default="cpu"),
)
op.add_column(
"base_individual",
sa.Column("template_origin_id", sa.String(64), nullable=True),
)
op.create_foreign_key(
"fk_base_individual_template_origin",
"base_individual",
"persona_template",
["template_origin_id"],
["template_id"],
ondelete="SET NULL",
)
op.create_index(
"ix_base_individual_template_origin_id",
"base_individual",
["template_origin_id"],
)
def downgrade() -> None:
op.drop_index("ix_base_individual_template_origin_id", "base_individual")
op.drop_constraint("fk_base_individual_template_origin", "base_individual", type_="foreignkey")
op.drop_column("base_individual", "template_origin_id")
op.drop_column("base_individual", "node_affinity")
op.drop_index("ix_persona_template_owner_id", "persona_template")
op.drop_index("ix_persona_template_name", "persona_template")
op.drop_table("persona_template")
@@ -0,0 +1,27 @@
"""add custom_system_prompt to system_node_config
Revision ID: 0004_system_node_custom_prompt
Revises: 0003_persona_template
Create Date: 2026-06-04 00:01:00
"""
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
revision: str = "0004_system_node_custom_prompt"
down_revision: Union[str, None] = "0003_persona_template"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.add_column(
"system_node_config",
sa.Column("custom_system_prompt", sa.Text(), nullable=True),
)
def downgrade() -> None:
op.drop_column("system_node_config", "custom_system_prompt")