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,73 @@
from sqlalchemy import select
from ulid import ULID
from kilostar.core.postgres_database.model.persona_template import PersonaTemplate
from kilostar.core.postgres_database.database_exception import database_exception
class PersonaTemplateDatabase:
def __init__(self, async_session_maker):
self.async_session_maker = async_session_maker
@database_exception
async def add_template(self, **kwargs) -> PersonaTemplate:
async with self.async_session_maker() as session:
tpl = PersonaTemplate(template_id=str(ULID()), **kwargs)
session.add(tpl)
await session.commit()
await session.refresh(tpl)
return tpl
@database_exception
async def get_template(self, template_id: str):
async with self.async_session_maker() as session:
result = await session.execute(
select(PersonaTemplate).where(PersonaTemplate.template_id == template_id)
)
return result.scalar_one_or_none()
@database_exception
async def list_templates(self, owner_id: str = None, include_builtin: bool = True):
async with self.async_session_maker() as session:
stmt = select(PersonaTemplate)
if owner_id and include_builtin:
from sqlalchemy import or_
stmt = stmt.where(
or_(PersonaTemplate.owner_id == owner_id, PersonaTemplate.is_builtin == True)
)
elif owner_id:
stmt = stmt.where(PersonaTemplate.owner_id == owner_id)
elif include_builtin:
stmt = stmt.where(PersonaTemplate.is_builtin == True)
result = await session.execute(stmt)
return list(result.scalars().all())
@database_exception
async def update_template(self, template_id: str, **kwargs):
async with self.async_session_maker() as session:
result = await session.execute(
select(PersonaTemplate).where(PersonaTemplate.template_id == template_id)
)
tpl = result.scalar_one_or_none()
if not tpl:
return None
for k, v in kwargs.items():
if v is not None:
setattr(tpl, k, v)
session.add(tpl)
await session.commit()
await session.refresh(tpl)
return tpl
@database_exception
async def delete_template(self, template_id: str) -> bool:
async with self.async_session_maker() as session:
result = await session.execute(
select(PersonaTemplate).where(PersonaTemplate.template_id == template_id)
)
tpl = result.scalar_one_or_none()
if not tpl:
return False
await session.delete(tpl)
await session.commit()
return True