refactor(core): decouple actors and remove workflow templates (#67)
Removes the deprecated `workflow_template` concept entirely across both backend API routers, internal logic handling within the `supervisory_node` and `consciousness_node`, and front-end components. Enables `consciousness_node` to work autonomously. Also refactors core package structure to enforce the "one python package, one Ray Actor" architectural rule. `GlobalWorkflowManager`, `WorkflowRunningEngine`, `PostgresDatabase`, and `WorkerCluster` have been moved to their own top-level decoupled package directories with properly exported `__init__.py` modules. Test suites have been relocated and import paths updated across the system. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: zhaoxi826 <198742034+zhaoxi826@users.noreply.github.com>
This commit is contained in:
@@ -17,16 +17,20 @@ from pydantic import ValidationError
|
||||
from pretor.utils.error import UserNotExistError
|
||||
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('database_exception')
|
||||
|
||||
logger = get_logger("database_exception")
|
||||
|
||||
|
||||
def database_exception(func):
|
||||
"""执行与 database exception 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: func: 参与 database exception 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
|
||||
async def wrapper(*args, **kwargs):
|
||||
"""执行与 wrapper 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
except ValidationError as e:
|
||||
@@ -43,4 +47,5 @@ def database_exception(func):
|
||||
except Exception as e:
|
||||
logger.exception(f"未预期的数据库错误: {e}")
|
||||
raise e
|
||||
return wrapper
|
||||
|
||||
return wrapper
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import List, Optional
|
||||
from pretor.core.database.table.event import EventRecord
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker, AsyncSession
|
||||
|
||||
|
||||
class EventDatabase:
|
||||
def __init__(self, async_session_maker: async_sessionmaker[AsyncSession]):
|
||||
self.async_session_maker = async_session_maker
|
||||
|
||||
@@ -19,9 +19,11 @@ from pretor.core.database.database_exception import database_exception
|
||||
|
||||
from ulid import ULID
|
||||
|
||||
|
||||
class IndividualDatabase:
|
||||
"""IndividualDatabase 核心组件类。
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。 """
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。"""
|
||||
|
||||
def __init__(self, async_session_maker):
|
||||
self.async_session_maker = async_session_maker
|
||||
|
||||
@@ -29,7 +31,7 @@ class IndividualDatabase:
|
||||
async def add_worker_individual(self, **kwargs) -> WorkerIndividual:
|
||||
"""创建并持久化新的 worker individual 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Returns: (WorkerIndividual): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (WorkerIndividual): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
agent_id = str(ULID())
|
||||
individual = WorkerIndividual(agent_id=agent_id, **kwargs)
|
||||
@@ -43,9 +45,11 @@ class IndividualDatabase:
|
||||
"""检索并获取特定的 worker individual 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: (Optional[WorkerIndividual]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Optional[WorkerIndividual]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(WorkerIndividual).where(WorkerIndividual.agent_id == agent_id)
|
||||
statement = select(WorkerIndividual).where(
|
||||
WorkerIndividual.agent_id == agent_id
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
return results.scalar_one_or_none()
|
||||
|
||||
@@ -54,20 +58,26 @@ class IndividualDatabase:
|
||||
"""检索并获取特定的 worker individual list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: owner_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 owner 实例。
|
||||
Returns: (List[WorkerIndividual]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[WorkerIndividual]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(WorkerIndividual).where(WorkerIndividual.owner_id == owner_id)
|
||||
statement = select(WorkerIndividual).where(
|
||||
WorkerIndividual.owner_id == owner_id
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
return list(results.scalars().all())
|
||||
|
||||
@database_exception
|
||||
async def update_worker_individual(self, agent_id: str, **kwargs) -> Optional[WorkerIndividual]:
|
||||
async def update_worker_individual(
|
||||
self, agent_id: str, **kwargs
|
||||
) -> Optional[WorkerIndividual]:
|
||||
"""对现有的 worker individual 进行状态更新或属性覆盖。
|
||||
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: (Optional[WorkerIndividual]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Optional[WorkerIndividual]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(WorkerIndividual).where(WorkerIndividual.agent_id == agent_id)
|
||||
statement = select(WorkerIndividual).where(
|
||||
WorkerIndividual.agent_id == agent_id
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
individual = results.scalar_one_or_none()
|
||||
if not individual:
|
||||
@@ -85,9 +95,11 @@ class IndividualDatabase:
|
||||
"""安全地移除或注销 worker individual。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: (bool): 一个布尔型结果标志,明确返回 True 表示该操作成功应用或条件达成,False 则表示失败或被拒绝。 """
|
||||
Returns: (bool): 一个布尔型结果标志,明确返回 True 表示该操作成功应用或条件达成,False 则表示失败或被拒绝。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(WorkerIndividual).where(WorkerIndividual.agent_id == agent_id)
|
||||
statement = select(WorkerIndividual).where(
|
||||
WorkerIndividual.agent_id == agent_id
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
individual = results.scalar_one_or_none()
|
||||
if not individual:
|
||||
@@ -100,8 +112,8 @@ class IndividualDatabase:
|
||||
async def get_all_worker_individual(self) -> List[WorkerIndividual]:
|
||||
"""检索并获取特定的 all worker individual 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: (List[WorkerIndividual]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[WorkerIndividual]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(WorkerIndividual)
|
||||
results = await session.execute(statement)
|
||||
return list(results.scalars().all())
|
||||
return list(results.scalars().all())
|
||||
|
||||
@@ -18,9 +18,11 @@ from pretor.core.database.table.provider import Provider
|
||||
from sqlmodel import select
|
||||
from pretor.core.database.database_exception import database_exception
|
||||
|
||||
|
||||
class ProviderDatabase:
|
||||
"""ProviderDatabase 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
def __init__(self, async_session_maker):
|
||||
self.async_session_maker = async_session_maker
|
||||
|
||||
@@ -28,23 +30,28 @@ class ProviderDatabase:
|
||||
async def get_provider(self) -> List[Provider]:
|
||||
"""检索并获取特定的 provider 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: (List[Provider]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[Provider]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(Provider)
|
||||
results = await session.execute(statement)
|
||||
results = results.scalars().all()
|
||||
providers = [Provider(provider_title=provider.provider_title,
|
||||
provider_url=provider.provider_url,
|
||||
provider_apikey=provider.provider_apikey,
|
||||
provider_models=provider.provider_models,
|
||||
provider_type=provider.provider_type) for provider in results]
|
||||
providers = [
|
||||
Provider(
|
||||
provider_title=provider.provider_title,
|
||||
provider_url=provider.provider_url,
|
||||
provider_apikey=provider.provider_apikey,
|
||||
provider_models=provider.provider_models,
|
||||
provider_type=provider.provider_type,
|
||||
)
|
||||
for provider in results
|
||||
]
|
||||
return providers
|
||||
|
||||
@database_exception
|
||||
async def add_provider(self, **kwargs) -> None:
|
||||
"""创建并持久化新的 provider 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
provider = Provider(**kwargs)
|
||||
session.add(provider)
|
||||
@@ -55,7 +62,7 @@ class ProviderDatabase:
|
||||
"""安全地移除或注销 provider。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: provider_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider 实例。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
provider = await session.get(Provider, provider_id)
|
||||
if provider is not None:
|
||||
@@ -67,7 +74,7 @@ class ProviderDatabase:
|
||||
"""对现有的 provider 进行状态更新或属性覆盖。
|
||||
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
|
||||
Args: provider_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
provider = await session.get(Provider, provider_id)
|
||||
if provider is not None:
|
||||
@@ -77,4 +84,4 @@ class ProviderDatabase:
|
||||
await session.commit()
|
||||
await session.refresh(provider)
|
||||
return provider
|
||||
return None
|
||||
return None
|
||||
|
||||
@@ -17,20 +17,30 @@ from sqlmodel import select
|
||||
from typing import List, Optional
|
||||
from pretor.core.database.database_exception import database_exception
|
||||
|
||||
|
||||
class SystemNodeDatabase:
|
||||
"""SystemNodeDatabase 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
def __init__(self, async_session_maker):
|
||||
self.async_session_maker = async_session_maker
|
||||
|
||||
@database_exception
|
||||
async def upsert_system_node_config(self, node_name: str, provider_title: str, model_id: str, tools: Optional[List[str]] = None) -> SystemNodeConfig:
|
||||
async def upsert_system_node_config(
|
||||
self,
|
||||
node_name: str,
|
||||
provider_title: str,
|
||||
model_id: str,
|
||||
tools: Optional[List[str]] = None,
|
||||
) -> SystemNodeConfig:
|
||||
"""执行与 upsert system node config 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: node_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 provider_title (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。 model_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 model 实例。 tools (Optional[List[str]]): 控制逻辑流向的具体字符串参数,指定了期望的 tools 内容。
|
||||
Returns: (SystemNodeConfig): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (SystemNodeConfig): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(SystemNodeConfig).where(SystemNodeConfig.node_name == node_name)
|
||||
statement = select(SystemNodeConfig).where(
|
||||
SystemNodeConfig.node_name == node_name
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
config = results.scalar_one_or_none()
|
||||
if config:
|
||||
@@ -39,7 +49,12 @@ class SystemNodeDatabase:
|
||||
if tools is not None:
|
||||
config.tools = tools
|
||||
else:
|
||||
config = SystemNodeConfig(node_name=node_name, provider_title=provider_title, model_id=model_id, tools=tools)
|
||||
config = SystemNodeConfig(
|
||||
node_name=node_name,
|
||||
provider_title=provider_title,
|
||||
model_id=model_id,
|
||||
tools=tools,
|
||||
)
|
||||
session.add(config)
|
||||
await session.commit()
|
||||
await session.refresh(config)
|
||||
@@ -49,19 +64,23 @@ class SystemNodeDatabase:
|
||||
async def get_all_system_node_configs(self) -> List[SystemNodeConfig]:
|
||||
"""检索并获取特定的 all system node configs 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: (List[SystemNodeConfig]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[SystemNodeConfig]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(SystemNodeConfig)
|
||||
results = await session.execute(statement)
|
||||
return list(results.scalars().all())
|
||||
|
||||
@database_exception
|
||||
async def get_system_node_config(self, node_name: str) -> Optional[SystemNodeConfig]:
|
||||
async def get_system_node_config(
|
||||
self, node_name: str
|
||||
) -> Optional[SystemNodeConfig]:
|
||||
"""检索并获取特定的 system node config 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: node_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: (Optional[SystemNodeConfig]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Optional[SystemNodeConfig]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(SystemNodeConfig).where(SystemNodeConfig.node_name == node_name)
|
||||
statement = select(SystemNodeConfig).where(
|
||||
SystemNodeConfig.node_name == node_name
|
||||
)
|
||||
results = await session.execute(statement)
|
||||
return results.scalar_one_or_none()
|
||||
|
||||
@@ -19,9 +19,11 @@ from pretor.core.database.database_exception import database_exception
|
||||
from pretor.core.database.table.user import UserAuthority
|
||||
from pretor.utils.access import Accessor
|
||||
|
||||
|
||||
class AuthDatabase:
|
||||
"""AuthDatabase 核心组件类。
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。 """
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。"""
|
||||
|
||||
def __init__(self, async_session_maker):
|
||||
self.async_session_maker = async_session_maker
|
||||
|
||||
@@ -30,8 +32,9 @@ class AuthDatabase:
|
||||
"""创建并持久化新的 user 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 hashed_password (str): 控制逻辑流向的具体字符串参数,指定了期望的 hashed password 内容。
|
||||
Returns: (User): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (User): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
from ulid import ULID
|
||||
|
||||
async with self.async_session_maker() as session:
|
||||
# Check if any users exist
|
||||
statement = select(User).limit(1)
|
||||
@@ -46,7 +49,7 @@ class AuthDatabase:
|
||||
user_id=str(ULID()),
|
||||
user_name=user_name,
|
||||
hashed_password=hashed_password,
|
||||
user_authority=authority
|
||||
user_authority=authority,
|
||||
)
|
||||
session.add(user)
|
||||
await session.commit()
|
||||
@@ -58,7 +61,7 @@ class AuthDatabase:
|
||||
"""执行与 change password 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: user_name: 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 old_password: 参与 change password 逻辑运算或数据构建的上下文依赖对象。 new_password: 参与 change password 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (User): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (User): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(User).where(User.user_name == user_name)
|
||||
results = await session.execute(statement)
|
||||
@@ -78,7 +81,7 @@ class AuthDatabase:
|
||||
"""安全地移除或注销 user。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(User).where(User.user_name == user_name)
|
||||
results = await session.execute(statement)
|
||||
@@ -93,7 +96,7 @@ class AuthDatabase:
|
||||
"""安全地移除或注销 user by id。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
user = await session.get(User, user_id)
|
||||
if user is None:
|
||||
@@ -106,7 +109,7 @@ class AuthDatabase:
|
||||
"""执行与 login user 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。 """
|
||||
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(User).where(User.user_name == user_name)
|
||||
results = await session.execute(statement)
|
||||
@@ -119,7 +122,7 @@ class AuthDatabase:
|
||||
async def get_all_users(self) -> list[User]:
|
||||
"""检索并获取特定的 all users 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: (list[User]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (list[User]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
async with self.async_session_maker() as session:
|
||||
statement = select(User)
|
||||
results = await session.execute(statement)
|
||||
@@ -131,7 +134,7 @@ class AuthDatabase:
|
||||
"""检索并获取特定的 user authority 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。
|
||||
Returns: (UserAuthority): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (UserAuthority): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
async with self.async_session_maker() as session:
|
||||
user = await session.get(User, user_id)
|
||||
if user is None:
|
||||
@@ -139,7 +142,9 @@ class AuthDatabase:
|
||||
return user.user_authority
|
||||
|
||||
@database_exception
|
||||
async def change_user_authority(self, user_id: str, new_authority: UserAuthority) -> User:
|
||||
async def change_user_authority(
|
||||
self, user_id: str, new_authority: UserAuthority
|
||||
) -> User:
|
||||
"""
|
||||
Changes the authority level of a specific user.
|
||||
|
||||
@@ -161,4 +166,4 @@ class AuthDatabase:
|
||||
session.add(user)
|
||||
await session.commit()
|
||||
await session.refresh(user)
|
||||
return user
|
||||
return user
|
||||
|
||||
@@ -15,4 +15,5 @@
|
||||
from pretor.core.database.table.user import User
|
||||
from pretor.core.database.table.provider import Provider
|
||||
from pretor.core.database.table.individual import WorkerIndividual
|
||||
|
||||
__all__ = ["User", "Provider", "WorkerIndividual"]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from sqlmodel import SQLModel, Field
|
||||
|
||||
|
||||
class EventRecord(SQLModel, table=True):
|
||||
trace_id: str = Field(primary_key=True, description="The unique trace ID of the PretorEvent")
|
||||
trace_id: str = Field(
|
||||
primary_key=True, description="The unique trace ID of the PretorEvent"
|
||||
)
|
||||
event_data_json: str = Field(description="The JSON serialized PretorEvent data")
|
||||
|
||||
@@ -17,16 +17,20 @@ from typing import List, Optional
|
||||
from sqlalchemy import Column, JSON
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class AgentType(str, Enum):
|
||||
"""AgentType 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 AgentType 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 AgentType 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
SKILL_INDIVIDUAL = "skill_individual"
|
||||
ORDINARY_INDIVIDUAL = "ordinary_individual"
|
||||
SPECIAL_INDIVIDUAL = "special_individual"
|
||||
|
||||
|
||||
class WorkerIndividual(SQLModel, table=True):
|
||||
"""WorkerIndividual 核心组件类。
|
||||
这是一个具体的 Worker 智能体实体类,代表着具备特定人设、领域技能或长文本处理能力的数字员工。它可以被控制器动态拉起,并在安全沙箱内执行复杂的工作流指令与多步骤推理任务。 """
|
||||
这是一个具体的 Worker 智能体实体类,代表着具备特定人设、领域技能或长文本处理能力的数字员工。它可以被控制器动态拉起,并在安全沙箱内执行复杂的工作流指令与多步骤推理任务。"""
|
||||
|
||||
__tablename__ = "worker_individual"
|
||||
agent_id: str = Field(primary_key=True)
|
||||
agent_name: str = Field(index=True)
|
||||
@@ -35,8 +39,10 @@ class WorkerIndividual(SQLModel, table=True):
|
||||
provider_title: str
|
||||
model_id: str
|
||||
system_prompt: Optional[str]
|
||||
output_template: Optional[dict] = Field(sa_column=Column(JSON),description="输出模板标识")
|
||||
output_template: Optional[dict] = Field(
|
||||
sa_column=Column(JSON), description="输出模板标识"
|
||||
)
|
||||
bound_skill: Optional[str] = Field(sa_column=Column(JSON))
|
||||
workspace: Optional[List[str]] = Field(sa_column=Column(JSON))
|
||||
tools: Optional[List[str]] = Field(sa_column=Column(JSON), default=None)
|
||||
owner_id: str
|
||||
owner_id: str
|
||||
|
||||
@@ -17,9 +17,11 @@ from typing import List
|
||||
from sqlalchemy import Column, JSON
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class Provider(SQLModel, table=True):
|
||||
"""Provider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
__tablename__ = "provider"
|
||||
provider_id: str = Field(primary_key=True)
|
||||
provider_title: str = Field(index=True)
|
||||
@@ -31,4 +33,4 @@ class Provider(SQLModel, table=True):
|
||||
provider_models: List[str] = Field(sa_column=Column(JSON))
|
||||
|
||||
provider_owner: str
|
||||
is_active: bool = Field(default=True, description="该服务商节点是否在线/启用")
|
||||
is_active: bool = Field(default=True, description="该服务商节点是否在线/启用")
|
||||
|
||||
@@ -17,9 +17,11 @@ from sqlmodel import SQLModel, Field
|
||||
from typing import List, Optional
|
||||
from sqlalchemy import Column, JSON
|
||||
|
||||
|
||||
class SystemNodeConfig(SQLModel, table=True):
|
||||
"""SystemNodeConfig 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
__tablename__ = "system_node_config"
|
||||
node_name: str = Field(primary_key=True)
|
||||
provider_title: str
|
||||
|
||||
@@ -15,21 +15,24 @@
|
||||
from sqlmodel import SQLModel, Field
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
class UserAuthority(IntEnum):
|
||||
"""UserAuthority 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 UserAuthority 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 UserAuthority 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
SUPER_ADMINISTRATOR = 100
|
||||
ADMINISTRATOR = 50
|
||||
USER = 20
|
||||
UNAUTHORIZED_USER = 10
|
||||
GUEST = 0
|
||||
|
||||
|
||||
class User(SQLModel, table=True):
|
||||
"""User 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 User 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
__tablename__ = 'user'
|
||||
这是一个领域数据模型或功能封装类,承载了 User 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
__tablename__ = "user"
|
||||
user_id: str = Field(primary_key=True)
|
||||
user_name: str = Field(index=True)
|
||||
hashed_password: str
|
||||
user_authority: UserAuthority = Field(default=UserAuthority.USER)
|
||||
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
# Copyright 2026 zhaoxi826
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from pretor.core.global_state_machine.global_state_machine import GlobalStateMachine
|
||||
|
||||
__all__ = ["GlobalStateMachine"]
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
import ray
|
||||
from pretor.core.global_state_machine.provider_manager import ProviderManager
|
||||
from pretor.core.global_state_machine.tool_manager import GlobalToolManager
|
||||
from pretor.core.database.postgres import PostgresDatabase
|
||||
from pretor.core.workflow.workflow_template_manager import WorkflowManager
|
||||
from pretor.core.postgres_database import PostgresDatabase
|
||||
from pretor.core.global_state_machine.skill_manager import GlobalSkillManager
|
||||
from pretor.core.global_state_machine.individual_manager import GlobalIndividualManager
|
||||
|
||||
@@ -24,17 +23,17 @@ from pretor.core.global_state_machine.individual_manager import GlobalIndividual
|
||||
@ray.remote
|
||||
class GlobalStateMachine:
|
||||
"""GlobalStateMachine 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 GlobalStateMachine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 GlobalStateMachine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
def __init__(self, postgres_database: PostgresDatabase):
|
||||
import sys
|
||||
|
||||
print("GSM __init__ START", file=sys.stderr, flush=True)
|
||||
print(" event_dict done", file=sys.stderr, flush=True)
|
||||
self._global_provider_manager = ProviderManager(postgres_database)
|
||||
print(" provider_manager done", file=sys.stderr, flush=True)
|
||||
self._global_tool_manager = GlobalToolManager()
|
||||
print(" tool_manager done", file=sys.stderr, flush=True)
|
||||
self._global_workflow_template_manager = WorkflowManager()
|
||||
print(" workflow_template_manager done", file=sys.stderr, flush=True)
|
||||
self._global_skill_manager = GlobalSkillManager()
|
||||
print(" skill_manager done", file=sys.stderr, flush=True)
|
||||
self._global_individual_manager = GlobalIndividualManager()
|
||||
@@ -44,50 +43,63 @@ class GlobalStateMachine:
|
||||
|
||||
async def init_state_machine(self):
|
||||
"""完成 state machine 模块的启动与依赖初始化。
|
||||
在系统引导或服务拉起阶段被调用,负责建立网络连接、分配基础内存资源及注册核心服务组件。 """
|
||||
await self._global_provider_manager.init_provider_register(self.postgres_database)
|
||||
await self._global_individual_manager.init_individual_register(self.postgres_database)
|
||||
在系统引导或服务拉起阶段被调用,负责建立网络连接、分配基础内存资源及注册核心服务组件。"""
|
||||
await self._global_provider_manager.init_provider_register(
|
||||
self.postgres_database
|
||||
)
|
||||
await self._global_individual_manager.init_individual_register(
|
||||
self.postgres_database
|
||||
)
|
||||
|
||||
async def add_provider_wrap(self, provider_type, provider_title, provider_url, provider_apikey, provider_owner):
|
||||
async def add_provider_wrap(
|
||||
self,
|
||||
provider_type,
|
||||
provider_title,
|
||||
provider_url,
|
||||
provider_apikey,
|
||||
provider_owner,
|
||||
):
|
||||
"""创建并持久化新的 provider wrap 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: provider_type: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_type 实例。 provider_title: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。 provider_url: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_url 实例。 provider_apikey: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_apikey 实例。 provider_owner: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_owner 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return await self._global_provider_manager.add_provider(
|
||||
provider_type=provider_type,
|
||||
provider_title=provider_title,
|
||||
provider_url=provider_url,
|
||||
provider_apikey=provider_apikey,
|
||||
provider_owner=provider_owner,
|
||||
postgres_database=self.postgres_database
|
||||
postgres_database=self.postgres_database,
|
||||
)
|
||||
|
||||
# Provider Manager Methods
|
||||
def get_provider_list(self):
|
||||
"""检索并获取特定的 provider list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_provider_manager.get_provider_list()
|
||||
|
||||
def get_provider(self, provider_title):
|
||||
"""检索并获取特定的 provider 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: provider_title: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_provider_manager.get_provider(provider_title)
|
||||
|
||||
async def delete_provider(self, provider_title: str):
|
||||
"""安全地移除或注销 provider。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: provider_title (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return await self._global_provider_manager.delete_provider(provider_title, self.postgres_database)
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return await self._global_provider_manager.delete_provider(
|
||||
provider_title, self.postgres_database
|
||||
)
|
||||
|
||||
# Tool Manager Methods
|
||||
def get_tool_mapper(self):
|
||||
"""检索并获取特定的 tool mapper 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_tool_manager.tool_mapper
|
||||
|
||||
def get_tool_list(self, agent_name: str):
|
||||
@@ -96,60 +108,32 @@ class GlobalStateMachine:
|
||||
"""检索并获取特定的 tool list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: agent_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
tools = self._global_tool_manager.tool_mapper.get(agent_name, {})
|
||||
# also include default tools
|
||||
default_tools = self._global_tool_manager.tool_mapper.get("default", {})
|
||||
merged_tools = {**default_tools, **tools}
|
||||
return merged_tools
|
||||
|
||||
# Workflow Template Manager Methods
|
||||
def get_all_workflow_templates(self):
|
||||
"""检索并获取特定的 all workflow templates 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return self._global_workflow_template_manager.get_all_workflow_templates()
|
||||
|
||||
def add_workflow_template(self, template_name: str, workflow_template):
|
||||
"""创建并持久化新的 workflow template 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: template_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 workflow_template: 参与 add workflow template 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return self._global_workflow_template_manager.add_workflow_template(template_name, workflow_template)
|
||||
|
||||
def delete_workflow_template(self, template_name: str):
|
||||
"""安全地移除或注销 workflow template。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: template_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return self._global_workflow_template_manager.delete_workflow_template(template_name)
|
||||
|
||||
def generate_workflow_template(self, workflow_template):
|
||||
"""执行与 generate workflow template 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: workflow_template: 参与 generate workflow template 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return self._global_workflow_template_manager.generate_workflow_template(workflow_template)
|
||||
|
||||
# Skill Manager Methods
|
||||
def add_skill(self, skill_name: str):
|
||||
"""创建并持久化新的 skill 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: skill_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_skill_manager.add_skill(skill_name)
|
||||
|
||||
def get_skill_list(self):
|
||||
"""检索并获取特定的 skill list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_skill_manager.get_skill_list()
|
||||
|
||||
def remove_skill(self, skill_name: str):
|
||||
"""安全地移除或注销 skill。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: skill_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_skill_manager.remove_skill(skill_name)
|
||||
|
||||
# Individual Manager Methods
|
||||
@@ -157,26 +141,25 @@ class GlobalStateMachine:
|
||||
"""创建并持久化新的 individual 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。 config: 驱动该模块运行的核心配置字典或 Pydantic 数据模型,定义了重试策略、超时时间及模型参数等选项。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_individual_manager.add_individual(agent_id, config)
|
||||
|
||||
def get_individual(self, agent_id: str):
|
||||
"""检索并获取特定的 individual 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_individual_manager.get_individual(agent_id)
|
||||
|
||||
def remove_individual(self, agent_id: str):
|
||||
"""安全地移除或注销 individual。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_individual_manager.remove_individual(agent_id)
|
||||
|
||||
def list_individuals(self):
|
||||
"""执行与 list individuals 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self._global_individual_manager.list_individuals()
|
||||
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
|
||||
from typing import Dict, Any
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('individual_manager')
|
||||
|
||||
logger = get_logger("individual_manager")
|
||||
|
||||
|
||||
class GlobalIndividualManager:
|
||||
"""GlobalIndividualManager 核心组件类。
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalIndividual 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。 """
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalIndividual 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。"""
|
||||
|
||||
def __init__(self):
|
||||
self._individuals: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
@@ -26,21 +29,31 @@ class GlobalIndividualManager:
|
||||
"""完成 individual register 模块的启动与依赖初始化。
|
||||
在系统引导或服务拉起阶段被调用,负责建立网络连接、分配基础内存资源及注册核心服务组件。
|
||||
Args: postgres: 参与 init individual register 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
try:
|
||||
individuals = await postgres.get_all_worker_individual.remote()
|
||||
for ind in individuals:
|
||||
agent_id = getattr(ind, 'agent_id', None)
|
||||
agent_id = getattr(ind, "agent_id", None)
|
||||
if agent_id:
|
||||
self._individuals[agent_id] = ind.model_dump() if hasattr(ind, 'model_dump') else dict(ind)
|
||||
logger.info(f"成功从数据库拉取了 {len(self._individuals)} 个 Worker Individual 配置。")
|
||||
self._individuals[agent_id] = (
|
||||
ind.model_dump()
|
||||
if hasattr(ind, "model_dump")
|
||||
else dict(ind)
|
||||
)
|
||||
logger.info(
|
||||
f"成功从数据库拉取了 {len(self._individuals)} 个 Worker Individual 配置。"
|
||||
)
|
||||
except AttributeError:
|
||||
logger.warning("数据库中 get_all_worker_individual 方法未实现,跳过全量加载。可以在将来完善该接口。")
|
||||
logger.warning(
|
||||
"数据库中 get_all_worker_individual 方法未实现,跳过全量加载。可以在将来完善该接口。"
|
||||
)
|
||||
except Exception as e:
|
||||
# 捕获因 Ray 调用目标方法不存在引发的异常
|
||||
if "has no attribute 'get_all_worker_individual'" in str(e):
|
||||
logger.warning("数据库 individual_database 中缺少 get_all_worker_individual 方法,无法全量拉取。")
|
||||
logger.warning(
|
||||
"数据库 individual_database 中缺少 get_all_worker_individual 方法,无法全量拉取。"
|
||||
)
|
||||
else:
|
||||
raise e
|
||||
except Exception as e:
|
||||
@@ -64,12 +77,12 @@ class GlobalIndividualManager:
|
||||
"""安全地移除或注销 individual。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
if agent_id in self._individuals:
|
||||
del self._individuals[agent_id]
|
||||
|
||||
def list_individuals(self) -> Dict[str, Dict[str, Any]]:
|
||||
"""执行与 list individuals 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: (Dict[str, Dict[str, Any]]): 高度聚合的字典结构数据,将多维度的属性特征或统计指标组合后一并返回。 """
|
||||
Returns: (Dict[str, Dict[str, Any]]): 高度聚合的字典结构数据,将多维度的属性特征或统计指标组合后一并返回。"""
|
||||
return self._individuals
|
||||
|
||||
@@ -12,8 +12,24 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import Provider, ProviderArgs
|
||||
from pretor.core.global_state_machine.model_provider.openai_provider import OpenAIProvider
|
||||
from pretor.core.global_state_machine.model_provider.claude_provider import ClaudeProvider
|
||||
from pretor.core.global_state_machine.model_provider.deepseek_provider import DeepseekProvider
|
||||
__all__ = ["Provider", "ProviderArgs", "OpenAIProvider", "ClaudeProvider", "DeepseekProvider"]
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import (
|
||||
Provider,
|
||||
ProviderArgs,
|
||||
)
|
||||
from pretor.core.global_state_machine.model_provider.openai_provider import (
|
||||
OpenAIProvider,
|
||||
)
|
||||
from pretor.core.global_state_machine.model_provider.claude_provider import (
|
||||
ClaudeProvider,
|
||||
)
|
||||
from pretor.core.global_state_machine.model_provider.deepseek_provider import (
|
||||
DeepseekProvider,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Provider",
|
||||
"ProviderArgs",
|
||||
"OpenAIProvider",
|
||||
"ClaudeProvider",
|
||||
"DeepseekProvider",
|
||||
]
|
||||
|
||||
@@ -17,15 +17,19 @@ from pydantic import BaseModel
|
||||
from typing import List
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ProviderStatus(str, Enum):
|
||||
"""ProviderStatus 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
UP = "up"
|
||||
DOWN = "down"
|
||||
|
||||
|
||||
class Provider(BaseModel):
|
||||
"""Provider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
provider_title: str
|
||||
provider_url: str
|
||||
provider_apikey: str
|
||||
@@ -34,17 +38,21 @@ class Provider(BaseModel):
|
||||
provider_owner: str | None = None
|
||||
provider_status: ProviderStatus = ProviderStatus.UP
|
||||
|
||||
|
||||
class ProviderArgs(BaseModel):
|
||||
"""ProviderArgs 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
provider_title: str
|
||||
provider_url: str
|
||||
provider_apikey: str
|
||||
provider_owner: str
|
||||
|
||||
|
||||
class BaseProvider(ABC):
|
||||
"""BaseProvider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
async def create_provider(provider_args: ProviderArgs) -> Provider:
|
||||
@@ -83,7 +91,9 @@ class BaseProvider(ABC):
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def _return_provider(provider_args: ProviderArgs, provider_models: List[str]) -> Provider:
|
||||
def _return_provider(
|
||||
provider_args: ProviderArgs, provider_models: List[str]
|
||||
) -> Provider:
|
||||
"""
|
||||
包装Provider对象并返回
|
||||
将provider_args和_load_models获取的方法包装为provider对象
|
||||
@@ -100,5 +110,3 @@ class BaseProvider(ABC):
|
||||
返回一个Provider对象
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -14,21 +14,29 @@
|
||||
|
||||
from pretor.utils.retry import retry_on_retryable_error
|
||||
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import BaseProvider, Provider, ProviderArgs
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import (
|
||||
BaseProvider,
|
||||
Provider,
|
||||
ProviderArgs,
|
||||
)
|
||||
import httpx
|
||||
from typing import List
|
||||
|
||||
|
||||
class ClaudeProvider(BaseProvider):
|
||||
"""ClaudeProvider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
@staticmethod
|
||||
async def create_provider(provider_args: ProviderArgs) -> Provider:
|
||||
"""创建并持久化新的 provider 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
provider_models: List[str] = await ClaudeProvider._load_models(provider_args)
|
||||
provider: Provider = ClaudeProvider._return_provider(provider_args, provider_models)
|
||||
provider: Provider = ClaudeProvider._return_provider(
|
||||
provider_args, provider_models
|
||||
)
|
||||
return provider
|
||||
|
||||
@staticmethod
|
||||
@@ -38,11 +46,11 @@ class ClaudeProvider(BaseProvider):
|
||||
"""执行与 load models 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
headers = {
|
||||
"x-api-key": provider_args.provider_apikey,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"Content-Type": "application/json"
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
# 如果是官方 API,通常使用 /v1/models (如果支持)
|
||||
# 注意:很多时候 Anthropic 并不返回完整列表,如果请求失败,建议返回硬编码的常用模型
|
||||
@@ -57,19 +65,27 @@ class ClaudeProvider(BaseProvider):
|
||||
return sorted(model_ids)
|
||||
else:
|
||||
# 如果官方列表接口不可用,fallback 到已知常用模型
|
||||
return ["claude-3-5-sonnet-20240620", "claude-3-opus-20240229", "claude-3-haiku-20240307"]
|
||||
return [
|
||||
"claude-3-5-sonnet-20240620",
|
||||
"claude-3-opus-20240229",
|
||||
"claude-3-haiku-20240307",
|
||||
]
|
||||
except Exception as e:
|
||||
print(f"[{provider_args.provider_title}] 获取 Claude 模型列表错误: {e}")
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def _return_provider(provider_args: ProviderArgs, provider_models: List[str]) -> Provider:
|
||||
def _return_provider(
|
||||
provider_args: ProviderArgs, provider_models: List[str]
|
||||
) -> Provider:
|
||||
"""执行与 return provider 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。 provider_models (List[str]): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_models 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return Provider(provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="claude")
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return Provider(
|
||||
provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="claude",
|
||||
)
|
||||
|
||||
@@ -13,21 +13,29 @@
|
||||
# limitations under the License.
|
||||
|
||||
from pretor.utils.retry import retry_on_retryable_error
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import BaseProvider, Provider, ProviderArgs
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import (
|
||||
BaseProvider,
|
||||
Provider,
|
||||
ProviderArgs,
|
||||
)
|
||||
import httpx
|
||||
from typing import List
|
||||
|
||||
|
||||
class DeepseekProvider(BaseProvider):
|
||||
"""DeepseekProvider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
@staticmethod
|
||||
async def create_provider(provider_args: ProviderArgs) -> Provider:
|
||||
"""创建并持久化新的 provider 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
provider_models: List[str] = await DeepseekProvider._load_models(provider_args)
|
||||
provider: Provider = DeepseekProvider._return_provider(provider_args, provider_models)
|
||||
provider: Provider = DeepseekProvider._return_provider(
|
||||
provider_args, provider_models
|
||||
)
|
||||
return provider
|
||||
|
||||
@staticmethod
|
||||
@@ -36,17 +44,23 @@ class DeepseekProvider(BaseProvider):
|
||||
"""执行与 load models 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {provider_args.provider_apikey}",
|
||||
"Content-Type": "application/json"
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
url = f"{provider_args.provider_url}/models" if "/v1" in provider_args.provider_url else f"{provider_args.provider_url}/v1/models"
|
||||
url = (
|
||||
f"{provider_args.provider_url}/models"
|
||||
if "/v1" in provider_args.provider_url
|
||||
else f"{provider_args.provider_url}/v1/models"
|
||||
)
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
if response.status_code != 200:
|
||||
print(f"[{provider_args.provider_title}] 获取模型失败: {response.status_code}")
|
||||
print(
|
||||
f"[{provider_args.provider_title}] 获取模型失败: {response.status_code}"
|
||||
)
|
||||
return []
|
||||
data = response.json()
|
||||
raw_models = data.get("data", [])
|
||||
@@ -54,20 +68,27 @@ class DeepseekProvider(BaseProvider):
|
||||
return sorted(model_ids)
|
||||
except httpx.RequestError as e:
|
||||
from pretor.utils.error import RetryableError
|
||||
|
||||
print(f"[{provider_args.provider_title}] 网络请求异常: {e}")
|
||||
raise RetryableError(f"[{provider_args.provider_title}] 网络请求异常: {e}") from e
|
||||
raise RetryableError(
|
||||
f"[{provider_args.provider_title}] 网络请求异常: {e}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
print(f"[{provider_args.provider_title}] 解析模型列表时发生错误: {e}")
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def _return_provider(provider_args: ProviderArgs, provider_models: List[str]) -> Provider:
|
||||
def _return_provider(
|
||||
provider_args: ProviderArgs, provider_models: List[str]
|
||||
) -> Provider:
|
||||
"""执行与 return provider 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。 provider_models (List[str]): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_models 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return Provider(provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="deepseek")
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return Provider(
|
||||
provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="deepseek",
|
||||
)
|
||||
|
||||
@@ -13,21 +13,29 @@
|
||||
# limitations under the License.
|
||||
|
||||
from pretor.utils.retry import retry_on_retryable_error
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import BaseProvider, Provider, ProviderArgs
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import (
|
||||
BaseProvider,
|
||||
Provider,
|
||||
ProviderArgs,
|
||||
)
|
||||
import httpx
|
||||
from typing import List
|
||||
|
||||
|
||||
class OpenAIProvider(BaseProvider):
|
||||
"""OpenAIProvider 核心组件类。
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。 """
|
||||
这是一个模型/服务提供商适配器类,屏蔽了外部不同供应商(如 OpenAI、Anthropic 等)的底层 API 差异。它负责标准化参数组装、网络请求发送、鉴权处理以及响应结构的反序列化。"""
|
||||
|
||||
@staticmethod
|
||||
async def create_provider(provider_args: ProviderArgs) -> Provider:
|
||||
"""创建并持久化新的 provider 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
provider_models: List[str] = await OpenAIProvider._load_models(provider_args)
|
||||
provider: Provider = OpenAIProvider._return_provider(provider_args, provider_models)
|
||||
provider: Provider = OpenAIProvider._return_provider(
|
||||
provider_args, provider_models
|
||||
)
|
||||
return provider
|
||||
|
||||
@staticmethod
|
||||
@@ -36,17 +44,23 @@ class OpenAIProvider(BaseProvider):
|
||||
"""执行与 load models 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。 """
|
||||
Returns: (List[str]): 经过筛选、排序或分页处理后的实体对象列表集合。"""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {provider_args.provider_apikey}",
|
||||
"Content-Type": "application/json"
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
url = f"{provider_args.provider_url}/models" if "/v1" in provider_args.provider_url else f"{provider_args.provider_url}/v1/models"
|
||||
url = (
|
||||
f"{provider_args.provider_url}/models"
|
||||
if "/v1" in provider_args.provider_url
|
||||
else f"{provider_args.provider_url}/v1/models"
|
||||
)
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
if response.status_code != 200:
|
||||
print(f"[{provider_args.provider_title}] 获取模型失败: {response.status_code}")
|
||||
print(
|
||||
f"[{provider_args.provider_title}] 获取模型失败: {response.status_code}"
|
||||
)
|
||||
return []
|
||||
data = response.json()
|
||||
raw_models = data.get("data", [])
|
||||
@@ -54,20 +68,27 @@ class OpenAIProvider(BaseProvider):
|
||||
return sorted(model_ids)
|
||||
except httpx.RequestError as e:
|
||||
from pretor.utils.error import RetryableError
|
||||
|
||||
print(f"[{provider_args.provider_title}] 网络请求异常: {e}")
|
||||
raise RetryableError(f"[{provider_args.provider_title}] 网络请求异常: {e}") from e
|
||||
raise RetryableError(
|
||||
f"[{provider_args.provider_title}] 网络请求异常: {e}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
print(f"[{provider_args.provider_title}] 解析模型列表时发生错误: {e}")
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def _return_provider(provider_args: ProviderArgs, provider_models: List[str]) -> Provider:
|
||||
def _return_provider(
|
||||
provider_args: ProviderArgs, provider_models: List[str]
|
||||
) -> Provider:
|
||||
"""执行与 return provider 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: provider_args (ProviderArgs): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_args 实例。 provider_models (List[str]): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_models 实例。
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
return Provider(provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="openai")
|
||||
Returns: (Provider): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return Provider(
|
||||
provider_title=provider_args.provider_title,
|
||||
provider_apikey=provider_args.provider_apikey,
|
||||
provider_url=provider_args.provider_url,
|
||||
provider_models=provider_models,
|
||||
provider_type="openai",
|
||||
)
|
||||
|
||||
@@ -12,51 +12,73 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from pretor.core.global_state_machine.model_provider import Provider, OpenAIProvider, ClaudeProvider, DeepseekProvider
|
||||
from pretor.core.global_state_machine.model_provider import (
|
||||
Provider,
|
||||
OpenAIProvider,
|
||||
ClaudeProvider,
|
||||
DeepseekProvider,
|
||||
)
|
||||
from typing import Dict, Type
|
||||
|
||||
|
||||
class ProviderManager:
|
||||
"""
|
||||
模型供应商管理器 (ProviderManager)。
|
||||
负责维护不同的 LLM 协议适配器,提供从配置注册到 Agent 实例化的全生命周期管理。
|
||||
"""
|
||||
|
||||
# --- 类属性显式标注 (IDE 友好) ---
|
||||
provider_mapper: Dict[str, Type[Provider]]
|
||||
"""协议映射表:键为协议名(如 'openai'),值为对应的 Provider 类。"""
|
||||
|
||||
provider_register: Dict[str, Provider]
|
||||
"""供应商注册表:键为用户自定义别名,值为已实例化的 Provider 对象。"""
|
||||
|
||||
def __init__(self, postgres):
|
||||
self.provider_mapper = {"openai": OpenAIProvider,
|
||||
"claude": ClaudeProvider,
|
||||
"deepseek": DeepseekProvider}
|
||||
self.provider_mapper = {
|
||||
"openai": OpenAIProvider,
|
||||
"claude": ClaudeProvider,
|
||||
"deepseek": DeepseekProvider,
|
||||
}
|
||||
self.provider_register = {}
|
||||
|
||||
async def init_provider_register(self, postgres) -> None:
|
||||
"""完成 provider register 模块的启动与依赖初始化。
|
||||
在系统引导或服务拉起阶段被调用,负责建立网络连接、分配基础内存资源及注册核心服务组件。
|
||||
Args: postgres: 参与 init provider register 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
providers = await postgres.get_provider.remote()
|
||||
for provider in providers:
|
||||
self.provider_register[provider.provider_title] = provider
|
||||
|
||||
async def add_provider(self, provider_type, provider_title, provider_url, provider_apikey, provider_owner, postgres_database) -> None:
|
||||
async def add_provider(
|
||||
self,
|
||||
provider_type,
|
||||
provider_title,
|
||||
provider_url,
|
||||
provider_apikey,
|
||||
provider_owner,
|
||||
postgres_database,
|
||||
) -> None:
|
||||
"""创建并持久化新的 provider 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: provider_type: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_type 实例。 provider_title: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。 provider_url: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_url 实例。 provider_apikey: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_apikey 实例。 provider_owner: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_owner 实例。 postgres_database: 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
from pretor.core.global_state_machine.model_provider import ProviderArgs
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('provider_manager')
|
||||
|
||||
logger = get_logger("provider_manager")
|
||||
import httpx
|
||||
|
||||
provider_args: ProviderArgs = ProviderArgs(provider_title=provider_title,
|
||||
provider_url=provider_url,
|
||||
provider_apikey=provider_apikey,
|
||||
provider_owner=provider_owner)
|
||||
provider_args: ProviderArgs = ProviderArgs(
|
||||
provider_title=provider_title,
|
||||
provider_url=provider_url,
|
||||
provider_apikey=provider_apikey,
|
||||
provider_owner=provider_owner,
|
||||
)
|
||||
try:
|
||||
import ulid
|
||||
|
||||
provider_class = self.provider_mapper.get(provider_type, None)
|
||||
if provider_class is None:
|
||||
logger.warning(f"Provider type {provider_type} is not supported.")
|
||||
@@ -65,41 +87,49 @@ class ProviderManager:
|
||||
provider.provider_owner = provider_owner
|
||||
self.provider_register[provider_title] = provider
|
||||
await postgres_database.add_provider_db.remote(
|
||||
provider_id=str(ulid.ULID()),
|
||||
provider_title=provider.provider_title,
|
||||
provider_url=provider.provider_url,
|
||||
provider_apikey=provider.provider_apikey,
|
||||
provider_models=provider.provider_models,
|
||||
provider_type=provider.provider_type,
|
||||
provider_owner=provider.provider_owner)
|
||||
provider_id=str(ulid.ULID()),
|
||||
provider_title=provider.provider_title,
|
||||
provider_url=provider.provider_url,
|
||||
provider_apikey=provider.provider_apikey,
|
||||
provider_models=provider.provider_models,
|
||||
provider_type=provider.provider_type,
|
||||
provider_owner=provider.provider_owner,
|
||||
)
|
||||
|
||||
logger.info(f"已添加适配器{provider_title}")
|
||||
except httpx.RequestError as e:
|
||||
from pretor.utils.error import RetryableError
|
||||
|
||||
logger.warning(f"[{provider_args.provider_title}] 网络请求异常: {e}")
|
||||
raise RetryableError(f"[{provider_args.provider_title}] 网络请求异常: {e}") from e
|
||||
raise RetryableError(
|
||||
f"[{provider_args.provider_title}] 网络请求异常: {e}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
logger.warning(f"[{provider_args.provider_title}] 解析模型列表时发生错误: {e}")
|
||||
logger.warning(
|
||||
f"[{provider_args.provider_title}] 解析模型列表时发生错误: {e}"
|
||||
)
|
||||
|
||||
def get_provider_list(self):
|
||||
"""检索并获取特定的 provider list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self.provider_register
|
||||
|
||||
def get_provider(self, provider_title):
|
||||
"""检索并获取特定的 provider 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: provider_title: 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
return self.provider_register.get(provider_title)
|
||||
|
||||
async def delete_provider(self, provider_title: str, postgres_database) -> None:
|
||||
"""安全地移除或注销 provider。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: provider_title (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。 postgres_database: 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
if provider_title in self.provider_register:
|
||||
provider = self.provider_register[provider_title]
|
||||
await postgres_database.delete_provider_db.remote( provider_id=provider.provider_id)
|
||||
del self.provider_register[provider_title]
|
||||
await postgres_database.delete_provider_db.remote(
|
||||
provider_id=provider.provider_id
|
||||
)
|
||||
del self.provider_register[provider_title]
|
||||
|
||||
@@ -17,22 +17,29 @@ from collections import defaultdict
|
||||
import pathlib
|
||||
import json
|
||||
|
||||
|
||||
class GlobalSkillManager:
|
||||
"""GlobalSkillManager 核心组件类。
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalSkill 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。 """
|
||||
skill_mapper = Dict[str,Tuple[str]]
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalSkill 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。"""
|
||||
|
||||
skill_mapper = Dict[str, Tuple[str]]
|
||||
"""skill的存储表"""
|
||||
|
||||
def __init__(self):
|
||||
self.skill_mapper = defaultdict(tuple)
|
||||
|
||||
import os
|
||||
skill_plugin_dir = pathlib.Path(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "plugin", "skill")))
|
||||
|
||||
skill_plugin_dir = pathlib.Path(
|
||||
os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "..", "..", "plugin", "skill")
|
||||
)
|
||||
)
|
||||
if not skill_plugin_dir.exists() or not skill_plugin_dir.is_dir():
|
||||
return
|
||||
for item in skill_plugin_dir.iterdir():
|
||||
if item.is_dir() and not item.name.startswith((".", "__")):
|
||||
json_path = item / "skill.json" # 拼接文件路径
|
||||
json_path = item / "skill.json" # 拼接文件路径
|
||||
if json_path.exists():
|
||||
try:
|
||||
with open(json_path, "r", encoding="utf-8") as f:
|
||||
@@ -42,7 +49,7 @@ class GlobalSkillManager:
|
||||
if name:
|
||||
self.skill_mapper[name] = (
|
||||
skill.get("description", ""),
|
||||
skill.get("instructions", "")
|
||||
skill.get("instructions", ""),
|
||||
)
|
||||
except (json.JSONDecodeError, OSError) as e:
|
||||
print(f"警告: 加载插件 {item.name} 失败: {e}")
|
||||
@@ -50,7 +57,12 @@ class GlobalSkillManager:
|
||||
def add_skill(self, skill_name: str) -> None:
|
||||
"""Add a skill to the manager by reading its skill.json from the path"""
|
||||
import os
|
||||
skill_plugin_dir = pathlib.Path(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "plugin", "skill")))
|
||||
|
||||
skill_plugin_dir = pathlib.Path(
|
||||
os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "..", "..", "plugin", "skill")
|
||||
)
|
||||
)
|
||||
item = skill_plugin_dir / skill_name
|
||||
if item.is_dir() and not item.name.startswith((".", "__")):
|
||||
json_path = item / "skill.json"
|
||||
@@ -62,7 +74,7 @@ class GlobalSkillManager:
|
||||
if name:
|
||||
self.skill_mapper[name] = (
|
||||
skill.get("description", ""),
|
||||
skill.get("instructions", "")
|
||||
skill.get("instructions", ""),
|
||||
)
|
||||
except (json.JSONDecodeError, OSError) as e:
|
||||
print(f"警告: 加载插件 {item.name} 失败: {e}")
|
||||
|
||||
@@ -19,17 +19,22 @@ from collections import defaultdict
|
||||
from pretor.plugin.tool_plugin.base_tool import BaseToolData
|
||||
from typing import Dict, Type
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('tool_manager')
|
||||
|
||||
logger = get_logger("tool_manager")
|
||||
|
||||
|
||||
class GlobalToolManager:
|
||||
"""GlobalToolManager 核心组件类。
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalTool 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。 """
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 GlobalTool 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。"""
|
||||
|
||||
tool_mapper: Dict[str, Dict[str, Type[BaseToolData]]]
|
||||
|
||||
def __init__(self):
|
||||
self.tool_mapper = defaultdict(dict)
|
||||
|
||||
tool_plugin_dir = pathlib.Path(__file__).parent.parent.parent / "plugin" / "tool_plugin"
|
||||
tool_plugin_dir = (
|
||||
pathlib.Path(__file__).parent.parent.parent / "plugin" / "tool_plugin"
|
||||
)
|
||||
if not tool_plugin_dir.exists() or not tool_plugin_dir.is_dir():
|
||||
return
|
||||
|
||||
@@ -51,4 +56,4 @@ class GlobalToolManager:
|
||||
for scope in action_scopes:
|
||||
self.tool_mapper[scope][plugin_name] = obj
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to load tool plugin {plugin_name}: {e}")
|
||||
logger.warning(f"Failed to load tool plugin {plugin_name}: {e}")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from pretor.core.global_workflow_manager.global_workflow_manager import (
|
||||
GlobalWorkflowManager,
|
||||
)
|
||||
|
||||
__all__ = ["GlobalWorkflowManager"]
|
||||
+49
-24
@@ -6,6 +6,7 @@ from pretor.core.workflow.workflow import PretorWorkflow
|
||||
from pretor.utils.ray_hook import ray_actor_hook
|
||||
from pretor.utils.logger import get_logger
|
||||
|
||||
|
||||
@ray.remote
|
||||
class GlobalWorkflowManager:
|
||||
def __init__(self):
|
||||
@@ -31,7 +32,9 @@ class GlobalWorkflowManager:
|
||||
event_copy = event.model_copy()
|
||||
event_copy.pending_queue = None
|
||||
event_copy.receive_queue = None
|
||||
self.event_object_refs[event.trace_id] = ray.put(event_copy.model_dump_json())
|
||||
self.event_object_refs[event.trace_id] = ray.put(
|
||||
event_copy.model_dump_json()
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to load event {record.trace_id}: {e}")
|
||||
@@ -40,13 +43,22 @@ class GlobalWorkflowManager:
|
||||
# Trigger resumption of incomplete workflows
|
||||
workflow_running_engine = None
|
||||
for trace_id, event in self.event_dict.items():
|
||||
if event.workflow and event.workflow.status.status in ["waiting_llm_working", "waiting_tool_working", "llm_working", "tool_working"]:
|
||||
if event.workflow and event.workflow.status.status in [
|
||||
"waiting_llm_working",
|
||||
"waiting_tool_working",
|
||||
"llm_working",
|
||||
"tool_working",
|
||||
]:
|
||||
self.logger.info(f"Resuming incomplete workflow {trace_id}")
|
||||
if not workflow_running_engine:
|
||||
try:
|
||||
workflow_running_engine = ray_actor_hook("workflow_running_engine").workflow_running_engine
|
||||
workflow_running_engine = ray_actor_hook(
|
||||
"workflow_running_engine"
|
||||
).workflow_running_engine
|
||||
except AttributeError:
|
||||
self.logger.warning("workflow_running_engine not found, cannot resume workflow")
|
||||
self.logger.warning(
|
||||
"workflow_running_engine not found, cannot resume workflow"
|
||||
)
|
||||
break
|
||||
await workflow_running_engine.resume_workflow.remote(event)
|
||||
|
||||
@@ -64,12 +76,11 @@ class GlobalWorkflowManager:
|
||||
# Update cache
|
||||
self.event_object_refs[event.trace_id] = ray.put(event_json)
|
||||
|
||||
await self.postgres_database.upsert_event.remote(
|
||||
event.trace_id,
|
||||
event_json
|
||||
)
|
||||
await self.postgres_database.upsert_event.remote(event.trace_id, event_json)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to upsert event {event.trace_id} to database: {e}")
|
||||
self.logger.error(
|
||||
f"Failed to upsert event {event.trace_id} to database: {e}"
|
||||
)
|
||||
|
||||
async def add_event(self, event: PretorEvent) -> None:
|
||||
event.pending_queue = asyncio.Queue()
|
||||
@@ -98,7 +109,9 @@ class GlobalWorkflowManager:
|
||||
event_json = ray.get(self.event_object_refs[trace_id])
|
||||
return PretorEvent.model_validate_json(event_json)
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Failed to fetch event from cache for trace {trace_id}: {e}")
|
||||
self.logger.warning(
|
||||
f"Failed to fetch event from cache for trace {trace_id}: {e}"
|
||||
)
|
||||
|
||||
# Fallback to database
|
||||
try:
|
||||
@@ -119,11 +132,15 @@ class GlobalWorkflowManager:
|
||||
|
||||
return event
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to fetch event {trace_id} from database fallback: {e}")
|
||||
self.logger.error(
|
||||
f"Failed to fetch event {trace_id} from database fallback: {e}"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
async def update_attachment(self, trace_id: str, attachment: Dict[str, str]) -> None:
|
||||
async def update_attachment(
|
||||
self, trace_id: str, attachment: Dict[str, str]
|
||||
) -> None:
|
||||
if trace_id in self.event_dict:
|
||||
self.event_dict[trace_id].attachment = attachment
|
||||
await self._upsert_event_to_db(self.event_dict[trace_id])
|
||||
@@ -148,17 +165,25 @@ class GlobalWorkflowManager:
|
||||
try:
|
||||
event = PretorEvent.model_validate_json(record.event_data_json)
|
||||
workflow_title = event.workflow.title if event.workflow else None
|
||||
workflow_status = event.workflow.status.status if event.workflow and event.workflow.status else None
|
||||
result.append({
|
||||
"event_id": event.trace_id,
|
||||
"workflow_title": workflow_title,
|
||||
"status": workflow_status,
|
||||
"user_name": event.user_name,
|
||||
"message": event.message,
|
||||
"create_time": event.create_time,
|
||||
})
|
||||
workflow_status = (
|
||||
event.workflow.status.status
|
||||
if event.workflow and event.workflow.status
|
||||
else None
|
||||
)
|
||||
result.append(
|
||||
{
|
||||
"event_id": event.trace_id,
|
||||
"workflow_title": workflow_title,
|
||||
"status": workflow_status,
|
||||
"user_name": event.user_name,
|
||||
"message": event.message,
|
||||
"create_time": event.create_time,
|
||||
}
|
||||
)
|
||||
# Best-effort cache population
|
||||
self.event_object_refs[event.trace_id] = ray.put(record.event_data_json)
|
||||
self.event_object_refs[event.trace_id] = ray.put(
|
||||
record.event_data_json
|
||||
)
|
||||
except Exception:
|
||||
continue
|
||||
except Exception as e:
|
||||
@@ -173,7 +198,7 @@ class GlobalWorkflowManager:
|
||||
async def get_pending(self, trace_id) -> str:
|
||||
if trace_id in self.event_dict and self.event_dict[trace_id].pending_queue:
|
||||
return await self.event_dict[trace_id].pending_queue.get()
|
||||
await asyncio.sleep(1) # Prevent CPU spinning if not found
|
||||
await asyncio.sleep(1) # Prevent CPU spinning if not found
|
||||
return ""
|
||||
|
||||
async def put_received(self, trace_id, item) -> None:
|
||||
@@ -183,5 +208,5 @@ class GlobalWorkflowManager:
|
||||
async def get_received(self, trace_id) -> str:
|
||||
if trace_id in self.event_dict and self.event_dict[trace_id].receive_queue:
|
||||
return await self.event_dict[trace_id].receive_queue.get()
|
||||
await asyncio.sleep(1) # Prevent CPU spinning if not found
|
||||
await asyncio.sleep(1) # Prevent CPU spinning if not found
|
||||
return ""
|
||||
@@ -13,4 +13,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
from .consciousness_node import ConsciousnessNode
|
||||
|
||||
__all__ = ["ConsciousnessNode"]
|
||||
|
||||
@@ -15,8 +15,15 @@
|
||||
|
||||
import ray
|
||||
from typing import Union, overload
|
||||
from pretor.core.individual.consciousness_node.template import (ConsciousnessNodeDeps, ForSupervisoryNode, ForWorkflow,\
|
||||
ForWorkflowEngine, ForWorkflowInput, ForSupervisoryInput, ForWorkflowEngineInput)
|
||||
from pretor.core.individual.consciousness_node.template import (
|
||||
ConsciousnessNodeDeps,
|
||||
ForSupervisoryNode,
|
||||
ForWorkflow,
|
||||
ForWorkflowEngine,
|
||||
ForWorkflowInput,
|
||||
ForSupervisoryInput,
|
||||
ForWorkflowEngineInput,
|
||||
)
|
||||
from pydantic_ai import Agent, RunContext
|
||||
from pretor.core.global_state_machine.global_state_machine import GlobalStateMachine
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import Provider
|
||||
@@ -26,14 +33,21 @@ from pretor.adapter.model_adapter.agent_factory import AgentFactory
|
||||
@ray.remote
|
||||
class ConsciousnessNode:
|
||||
"""ConsciousnessNode 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
from pretor.utils.logger import get_logger
|
||||
self.logger = get_logger('consciousness_node')
|
||||
|
||||
self.logger = get_logger("consciousness_node")
|
||||
self.agent: None | Agent = None
|
||||
|
||||
|
||||
async def create_agent(self, global_state_machine: GlobalStateMachine, provider_title: str, model_id: str, tools_list: list[str] = None) -> None:
|
||||
async def create_agent(
|
||||
self,
|
||||
global_state_machine: GlobalStateMachine,
|
||||
provider_title: str,
|
||||
model_id: str,
|
||||
tools_list: list[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
create_agent方法,将agent对象装配到ConsciousnessNode的属性内
|
||||
该方法通过provider_title从global_state_machine中获取provider对象,然后从provider对象中取出供应商形象,装配为pydantic_ai的
|
||||
@@ -58,32 +72,35 @@ class ConsciousnessNode:
|
||||
)
|
||||
output_type = Union[ForSupervisoryNode, ForWorkflow, ForWorkflowEngine]
|
||||
from pretor.utils.get_tool import load_tools_from_list
|
||||
provider: Provider = await global_state_machine.get_provider.remote( provider_title)
|
||||
|
||||
provider: Provider = await global_state_machine.get_provider.remote(
|
||||
provider_title
|
||||
)
|
||||
agent_factory = AgentFactory()
|
||||
|
||||
callables = load_tools_from_list(tools_list)
|
||||
self.agent = agent_factory.create_agent(provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=ConsciousnessNodeDeps,
|
||||
agent_name="consciousness_node",
|
||||
tools=callables)
|
||||
self.agent = agent_factory.create_agent(
|
||||
provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=ConsciousnessNodeDeps,
|
||||
agent_name="consciousness_node",
|
||||
tools=callables,
|
||||
)
|
||||
|
||||
@self.agent.system_prompt
|
||||
async def dynamic_prompt(ctx: RunContext[ConsciousnessNodeDeps]):
|
||||
"""执行与 dynamic prompt 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: ctx (RunContext[ConsciousnessNodeDeps]): 参与 dynamic prompt 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
prompt = system_prompt + "\n\n"
|
||||
prompt += (
|
||||
f"=== 当前任务上下文 ===\n"
|
||||
f"- 当前指令 (Command): {ctx.deps.command}\n"
|
||||
f"- 原始用户命令 (Original Command): {ctx.deps.original_command}\n"
|
||||
)
|
||||
if ctx.deps.workflow_template:
|
||||
prompt += f"- 选定工作流模板 (Workflow Template): {ctx.deps.workflow_template}\n"
|
||||
if ctx.deps.available_skills:
|
||||
prompt += "\n=== 当前可用 Skill Individual ===\n"
|
||||
prompt += "你可以直接将以下 Skill Individual 安排进工作流的步骤中(设置 node 为 skill_individual,并将 agent_id 设置为对应 Skill Individual 的真实 agent_id,不要用名称!),作为可调用的工具。\n"
|
||||
@@ -92,30 +109,34 @@ class ConsciousnessNode:
|
||||
|
||||
return prompt
|
||||
|
||||
async def working(self, payload: Union[ForWorkflowEngineInput, ForWorkflowInput, ForSupervisoryInput]) -> Union[ForWorkflowEngine, ForWorkflow, ForSupervisoryNode, None]:
|
||||
async def working(
|
||||
self,
|
||||
payload: Union[ForWorkflowEngineInput, ForWorkflowInput, ForSupervisoryInput],
|
||||
) -> Union[ForWorkflowEngine, ForWorkflow, ForSupervisoryNode, None]:
|
||||
"""执行与 working 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: payload (Union[ForWorkflowEngineInput, ForWorkflowInput, ForSupervisoryInput]): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (Union[ForWorkflowEngine, ForWorkflow, ForSupervisoryNode, None]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Union[ForWorkflowEngine, ForWorkflow, ForSupervisoryNode, None]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
result = await self._run(payload)
|
||||
if isinstance(result, (ForWorkflowEngine, ForWorkflow, ForSupervisoryNode)):
|
||||
return result
|
||||
else:
|
||||
self.logger.error(f"ConsciousnessNode: 未知或不匹配的返回类型: {type(result)}")
|
||||
self.logger.error(
|
||||
f"ConsciousnessNode: 未知或不匹配的返回类型: {type(result)}"
|
||||
)
|
||||
return None
|
||||
except Exception:
|
||||
self.logger.exception("ConsciousnessNode在执行working时发生严重错误")
|
||||
return None
|
||||
|
||||
|
||||
@overload
|
||||
async def _run(self, payload: ForWorkflowEngineInput) -> ForWorkflowEngine:
|
||||
"""
|
||||
_run方法
|
||||
该分支应当在supervisory_node简单处理用户命令后,工作流创建前调用!
|
||||
Args:
|
||||
payload: 应当包含workflow_template和event对象
|
||||
payload: 应当包含原始命令和可用技能等信息
|
||||
|
||||
Returns:
|
||||
ForWorkflowEngine对象,将被放到全局状态机后丢入WorkflowEngine的异步队列
|
||||
@@ -148,45 +169,53 @@ class ConsciousnessNode:
|
||||
"""
|
||||
pass
|
||||
|
||||
async def _run(self, payload: Union[ForSupervisoryInput, ForWorkflowInput, ForWorkflowEngineInput]) -> Union[ForSupervisoryNode, ForWorkflow, ForWorkflowEngine]:
|
||||
async def _run(
|
||||
self,
|
||||
payload: Union[ForSupervisoryInput, ForWorkflowInput, ForWorkflowEngineInput],
|
||||
) -> Union[ForSupervisoryNode, ForWorkflow, ForWorkflowEngine]:
|
||||
"""执行与 run 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: payload (Union[ForSupervisoryInput, ForWorkflowInput, ForWorkflowEngineInput]): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (Union[ForSupervisoryNode, ForWorkflow, ForWorkflowEngine]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (Union[ForSupervisoryNode, ForWorkflow, ForWorkflowEngine]): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
self.agent.retries = 3
|
||||
if isinstance(payload, ForWorkflowEngineInput):
|
||||
deps = ConsciousnessNodeDeps(
|
||||
original_command=payload.original_command,
|
||||
workflow_template=payload.workflow_template,
|
||||
command="拆解原始命令变成一个工作流",
|
||||
available_skills=payload.available_skills
|
||||
command="自主分析并拆解原始命令,生成严密可执行的工作流",
|
||||
available_skills=payload.available_skills,
|
||||
)
|
||||
self.logger.debug("ConsciousnessNode: 开始生成工作流 (原生重试开启)")
|
||||
prompt = "根据original_command制定严密的可执行workflow"
|
||||
if payload.workflow_template:
|
||||
prompt += ",可以学习并参考workflow_template的设计理念"
|
||||
result = await self.agent.run(prompt, deps=deps)
|
||||
return result.output
|
||||
|
||||
elif isinstance(payload, ForWorkflowInput):
|
||||
deps = ConsciousnessNodeDeps(
|
||||
original_command=payload.original_command,
|
||||
command="完成workflow step中分配给意识节点的特定任务或指导"
|
||||
command="完成workflow step中分配给意识节点的特定任务或指导",
|
||||
)
|
||||
self.logger.debug(
|
||||
"ConsciousnessNode: 开始处理工作流节点任务 (原生重试开启)"
|
||||
)
|
||||
result = await self.agent.run(
|
||||
f"处理此工作流步骤信息:\n{payload.workflow_step.model_dump_json()}",
|
||||
deps=deps,
|
||||
)
|
||||
self.logger.debug("ConsciousnessNode: 开始处理工作流节点任务 (原生重试开启)")
|
||||
result = await self.agent.run(f"处理此工作流步骤信息:\n{payload.workflow_step.model_dump_json()}",
|
||||
deps=deps)
|
||||
return result.output
|
||||
|
||||
elif isinstance(payload, ForSupervisoryInput):
|
||||
deps = ConsciousnessNodeDeps(
|
||||
original_command=payload.original_command,
|
||||
command="对于工作流整体执行结果进行检查,并且生成一份专业的技术性总结报告"
|
||||
command="对于工作流整体执行结果进行检查,并且生成一份专业的技术性总结报告",
|
||||
)
|
||||
self.logger.debug(
|
||||
"ConsciousnessNode: 开始生成技术总结报告 (原生重试开启)"
|
||||
)
|
||||
result = await self.agent.run(
|
||||
f"基于以下工作流的执行记录,生成技术报告:\n{payload.workflow.model_dump_json()}",
|
||||
deps=deps,
|
||||
)
|
||||
self.logger.debug("ConsciousnessNode: 开始生成技术总结报告 (原生重试开启)")
|
||||
result = await self.agent.run(f"基于以下工作流的执行记录,生成技术报告:\n{payload.workflow.model_dump_json()}",
|
||||
deps=deps)
|
||||
return result.output
|
||||
except Exception as e:
|
||||
self.logger.exception(f"ConsciousnessNode 模型生成最终失败: {str(e)}")
|
||||
|
||||
@@ -18,60 +18,71 @@ from pretor.utils.agent_model import ResponseModel, DepsModel, InputModel
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
#意识节点回复类
|
||||
# 意识节点回复类
|
||||
class ConsciousnessNodeResponse(ResponseModel):
|
||||
"""Consciousness response model,是意识节点所有回复类型的父类"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ForWorkflowEngine(ConsciousnessNodeResponse):
|
||||
"""生成workflow并放入WorkflowEngine"""
|
||||
workflow: PretorWorkflow = Field(..., description="生成好的符合规范的完整工作流对象。")
|
||||
|
||||
workflow: PretorWorkflow = Field(
|
||||
..., description="生成好的符合规范的完整工作流对象。"
|
||||
)
|
||||
reasoning: str = Field(..., description="生成此工作流的原因和思路简述。")
|
||||
|
||||
|
||||
class ForWorkflow(ConsciousnessNodeResponse):
|
||||
"""处理workflow中需要ConsciousnessNode的工作"""
|
||||
|
||||
output: str = Field(..., description="对当前工作流步骤的具体处理结果或指导意见。")
|
||||
|
||||
|
||||
class ForSupervisoryNode(ConsciousnessNodeResponse):
|
||||
"""工作流完成后进行校验并返回给SupervisoryNode"""
|
||||
output: str = Field(..., description="为监控节点提供的全工作流执行情况的技术性总结报告。")
|
||||
|
||||
output: str = Field(
|
||||
..., description="为监控节点提供的全工作流执行情况的技术性总结报告。"
|
||||
)
|
||||
|
||||
|
||||
class ConsciousnessNodeDeps(DepsModel):
|
||||
"""ConsciousnessNodeDeps 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
original_command: str
|
||||
workflow_template: str | None = None
|
||||
command: str
|
||||
available_skills: list[dict] | None = None
|
||||
|
||||
|
||||
class ConsciousnessNodeInput(InputModel):
|
||||
"""ConsciousnessNodeInput 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ForWorkflowEngineInput(ConsciousnessNodeInput):
|
||||
"""ForWorkflowEngineInput 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowEngineInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
workflow_template: str | None = None
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowEngineInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
original_command: str
|
||||
available_skills: list[dict] | None = None
|
||||
|
||||
|
||||
class ForWorkflowInput(ConsciousnessNodeInput):
|
||||
"""ForWorkflowInput 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
workflow_step: WorkStep
|
||||
original_command: str
|
||||
|
||||
|
||||
class ForSupervisoryInput(ConsciousnessNodeInput):
|
||||
"""ForSupervisoryInput 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForSupervisoryInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 ForSupervisoryInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
workflow: PretorWorkflow
|
||||
original_command: str
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
from .control_node import ControlNode
|
||||
|
||||
__all__ = ["ControlNode"]
|
||||
|
||||
@@ -17,21 +17,31 @@ from pydantic_ai import Agent, RunContext
|
||||
from pretor.core.global_state_machine.global_state_machine import GlobalStateMachine
|
||||
from pretor.core.global_state_machine.model_provider.base_provider import Provider
|
||||
from pretor.adapter.model_adapter.agent_factory import AgentFactory
|
||||
from pretor.core.individual.control_node.template import ForWorkflow, ForWorkflowInput, ControlNodeDeps
|
||||
|
||||
from pretor.core.individual.control_node.template import (
|
||||
ForWorkflow,
|
||||
ForWorkflowInput,
|
||||
ControlNodeDeps,
|
||||
)
|
||||
|
||||
|
||||
@ray.remote
|
||||
class ControlNode:
|
||||
"""ControlNode 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
def __init__(self):
|
||||
from pretor.utils.logger import get_logger
|
||||
self.logger = get_logger('control_node')
|
||||
|
||||
self.logger = get_logger("control_node")
|
||||
self.agent: Agent | None = None
|
||||
|
||||
|
||||
async def create_agent(self, global_state_machine: GlobalStateMachine, provider_title: str, model_id: str, tools_list: list[str] = None) -> None:
|
||||
async def create_agent(
|
||||
self,
|
||||
global_state_machine: GlobalStateMachine,
|
||||
provider_title: str,
|
||||
model_id: str,
|
||||
tools_list: list[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
create_agent方法,将agent对象装配到Control的属性内
|
||||
该方法通过provider_title从global_state_machine中获取provider对象,然后从provider对象中取出供应商形象,装配为pydantic_ai的
|
||||
@@ -56,23 +66,29 @@ class ControlNode:
|
||||
)
|
||||
output_type = ForWorkflow
|
||||
from pretor.utils.get_tool import load_tools_from_list
|
||||
provider: Provider = await global_state_machine.get_provider.remote( provider_title)
|
||||
|
||||
provider: Provider = await global_state_machine.get_provider.remote(
|
||||
provider_title
|
||||
)
|
||||
agent_factory = AgentFactory()
|
||||
|
||||
callables = load_tools_from_list(tools_list)
|
||||
self.agent = agent_factory.create_agent(provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=ControlNodeDeps,
|
||||
agent_name="control_node",
|
||||
tools=callables)
|
||||
self.agent = agent_factory.create_agent(
|
||||
provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=ControlNodeDeps,
|
||||
agent_name="control_node",
|
||||
tools=callables,
|
||||
)
|
||||
|
||||
@self.agent.system_prompt
|
||||
async def dynamic_prompt(ctx: RunContext[ControlNodeDeps]):
|
||||
"""执行与 dynamic prompt 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: ctx (RunContext[ControlNodeDeps]): 参与 dynamic prompt 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
prompt = system_prompt + "\n\n"
|
||||
prompt += (
|
||||
f"=== 当前任务步骤上下文 ===\n"
|
||||
@@ -86,7 +102,7 @@ class ControlNode:
|
||||
"""执行与 working 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: payload (ForWorkflowInput): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。 """
|
||||
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。"""
|
||||
try:
|
||||
result: ForWorkflow = await self._run(payload)
|
||||
return result
|
||||
@@ -98,19 +114,21 @@ class ControlNode:
|
||||
"""执行与 run 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: payload (ForWorkflowInput): 从客户端传递过来或由上游组件生成的核心业务数据体,通常需要进一步的清洗和结构化解析。
|
||||
Returns: (ForWorkflow): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (ForWorkflow): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
self.agent.retries = 3
|
||||
deps = ControlNodeDeps(
|
||||
workflow_step=payload.workflow_step
|
||||
deps = ControlNodeDeps(workflow_step=payload.workflow_step)
|
||||
self.logger.debug(
|
||||
f"ControlNode: 开始执行工作流节点 [{payload.workflow_step.name}] (原生重试开启)"
|
||||
)
|
||||
self.logger.debug(f"ControlNode: 开始执行工作流节点 [{payload.workflow_step.name}] (原生重试开启)")
|
||||
|
||||
result = await self.agent.run(
|
||||
f"请根据提供的 workflow_step 上下文,执行此步骤并输出结果。\n详细指令或附加数据:{payload.workflow_step.model_dump_json()}",
|
||||
deps=deps
|
||||
deps=deps,
|
||||
)
|
||||
return result.output
|
||||
except Exception as e:
|
||||
self.logger.exception(f"ControlNode 在执行步骤 [{payload.workflow_step.name}] 时最终失败: {str(e)}")
|
||||
self.logger.exception(
|
||||
f"ControlNode 在执行步骤 [{payload.workflow_step.name}] 时最终失败: {str(e)}"
|
||||
)
|
||||
raise RuntimeError(f"ControlNode 执行步骤失败: {str(e)}") from e
|
||||
|
||||
@@ -17,31 +17,39 @@ from pydantic import Field
|
||||
from pretor.core.workflow.workflow import WorkStep
|
||||
from pretor.utils.agent_model import ResponseModel, InputModel, DepsModel
|
||||
|
||||
|
||||
class ControlNodeResponse(ResponseModel):
|
||||
"""控制节点回复的基类"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ControlNodeInput(InputModel):
|
||||
"""ControlNodeInput 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ControlNodeDeps(DepsModel):
|
||||
"""ControlNodeDeps 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
workflow_step: WorkStep
|
||||
# In the future, this can be dynamically populated with tools specific to the current task execution
|
||||
|
||||
|
||||
class ForWorkflow(ControlNodeResponse):
|
||||
"""ForWorkflow 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflow 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
output: str = Field(..., description="控制节点执行特定工作流步骤的结果。包含执行细节和输出数据。")
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflow 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
output: str = Field(
|
||||
..., description="控制节点执行特定工作流步骤的结果。包含执行细节和输出数据。"
|
||||
)
|
||||
|
||||
|
||||
class ForWorkflowInput(ControlNodeInput):
|
||||
"""ForWorkflowInput 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 ForWorkflowInput 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
workflow_step: WorkStep
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
from .supervisory_node import SupervisoryNode
|
||||
|
||||
__all__ = ["SupervisoryNode"]
|
||||
|
||||
@@ -19,7 +19,12 @@ from pretor.api.platform.event import PretorEvent
|
||||
from pretor.adapter.model_adapter.agent_factory import AgentFactory
|
||||
from pretor.core.global_state_machine.global_state_machine import GlobalStateMachine
|
||||
from pretor.core.global_state_machine.model_provider import Provider
|
||||
from pretor.core.individual.supervisory_node.template import ForConsciousnessNode, ForUser, SupervisoryNodeDeps, TerminationMessage
|
||||
from pretor.core.individual.supervisory_node.template import (
|
||||
ForConsciousnessNode,
|
||||
ForUser,
|
||||
SupervisoryNodeDeps,
|
||||
TerminationMessage,
|
||||
)
|
||||
from pydantic_ai import RunContext, Agent
|
||||
from pretor.utils.ray_hook import ray_actor_hook
|
||||
|
||||
@@ -27,14 +32,21 @@ from pretor.utils.ray_hook import ray_actor_hook
|
||||
@ray.remote
|
||||
class SupervisoryNode:
|
||||
"""SupervisoryNode 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
from pretor.utils.logger import get_logger
|
||||
self.logger = get_logger('supervisory_node')
|
||||
|
||||
self.logger = get_logger("supervisory_node")
|
||||
self.agent: None | Agent = None
|
||||
|
||||
|
||||
async def create_agent(self, global_state_machine: GlobalStateMachine, provider_title: str, model_id: str, tools_list: list[str] = None) -> None:
|
||||
async def create_agent(
|
||||
self,
|
||||
global_state_machine: GlobalStateMachine,
|
||||
provider_title: str,
|
||||
model_id: str,
|
||||
tools_list: list[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
create_agent方法,将agent对象装配到SupervisoryNode的属性内
|
||||
该方法通过provider_title从global_state_machine中获取provider对象,然后从provider对象中取出供应商形象,装配为pydantic_ai的Agent实例,
|
||||
@@ -53,43 +65,47 @@ class SupervisoryNode:
|
||||
"你的核心职责是进行【意图识别与路由】。请仔细阅读用户的请求:\n"
|
||||
"1. 如果用户只是进行简单的问候、闲聊或查询非常基础的信息,请直接生成友好的回复,使用 ForUser 格式。\n"
|
||||
"2. 如果用户提出的是复杂任务(如需要编写代码、多步骤规划、数据处理等),请务必将其判定为需要工作流处理的任务,"
|
||||
" 并使用 ForConsciousnessNode 格式。若提供的【可用模板列表】中有合适的模板请选用,若都不匹配则 workflow_template 设为 null。\n"
|
||||
" 并使用 ForConsciousnessNode 格式将其移交意识节点处理。\n"
|
||||
"3. 如果你收到的是 TerminationMessage(代表工作流已完成并生成了报告),请将报告内容转化为友好的面向用户的回复,使用 ForUser 格式。\n"
|
||||
"请保持冷静、专业,并严格遵循上述路由规则。"
|
||||
)
|
||||
output_type = Union[ForConsciousnessNode, ForUser]
|
||||
from pretor.utils.get_tool import load_tools_from_list
|
||||
provider: Provider = await global_state_machine.get_provider.remote( provider_title)
|
||||
|
||||
provider: Provider = await global_state_machine.get_provider.remote(
|
||||
provider_title
|
||||
)
|
||||
agent_factory = AgentFactory()
|
||||
|
||||
callables = load_tools_from_list(tools_list)
|
||||
self.agent = agent_factory.create_agent(provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=SupervisoryNodeDeps,
|
||||
agent_name="supervisory_node",
|
||||
tools=callables)
|
||||
self.agent = agent_factory.create_agent(
|
||||
provider=provider,
|
||||
model_id=model_id,
|
||||
output_type=output_type,
|
||||
system_prompt=system_prompt,
|
||||
deps_type=SupervisoryNodeDeps,
|
||||
agent_name="supervisory_node",
|
||||
tools=callables,
|
||||
)
|
||||
|
||||
@self.agent.system_prompt
|
||||
async def dynamic_prompt(ctx: RunContext[SupervisoryNodeDeps]):
|
||||
"""执行与 dynamic prompt 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: ctx (RunContext[SupervisoryNodeDeps]): 参与 dynamic prompt 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
prompt = system_prompt + "\n\n"
|
||||
prompt += (
|
||||
f"=== 当前上下文 ===\n"
|
||||
f"- 平台 (Platform): {ctx.deps.platform}\n"
|
||||
f"- 用户名 (User): {ctx.deps.user_name}\n"
|
||||
f"- 当前时间 (Time): {ctx.deps.time}\n"
|
||||
f"- 可用工作流模板 (Available Templates): {ctx.deps.available_templates}\n"
|
||||
)
|
||||
# 修改 system_prompt 变量
|
||||
prompt += (
|
||||
"\n\n注意:你必须调用且只能调用一个函数(工具)来输出结果。"
|
||||
"如果你想直接回复用户,请调用 ForUser;"
|
||||
"如果你想移交给工作流,请调用 ForConsciousnessNode(若没有合适的模板,workflow_template 填 null)。"
|
||||
"如果你想移交给工作流,请调用 ForConsciousnessNode。"
|
||||
"严禁返回纯文本,必须使用工具格式!"
|
||||
)
|
||||
if ctx.deps.error_history:
|
||||
@@ -113,16 +129,21 @@ class SupervisoryNode:
|
||||
try:
|
||||
result = await self._run(payload)
|
||||
if isinstance(result, ForConsciousnessNode):
|
||||
self.logger.info(f"SupervisoryNode: 任务已分配给工作流引擎处理,选用模板 [{result.workflow_template}]")
|
||||
self.logger.info("SupervisoryNode: 任务已分配给工作流引擎处理")
|
||||
if isinstance(payload, PretorEvent):
|
||||
payload.context["workflow_template"] = result.workflow_template
|
||||
try:
|
||||
global_workflow_manager = ray_actor_hook("global_workflow_manager").global_workflow_manager
|
||||
global_workflow_manager = ray_actor_hook(
|
||||
"global_workflow_manager"
|
||||
).global_workflow_manager
|
||||
await global_workflow_manager.add_event.remote(payload)
|
||||
workflow_running_engine = ray_actor_hook("workflow_running_engine").workflow_running_engine
|
||||
workflow_running_engine = ray_actor_hook(
|
||||
"workflow_running_engine"
|
||||
).workflow_running_engine
|
||||
await workflow_running_engine.put_event.remote(payload)
|
||||
except Exception as e:
|
||||
self.logger.error(f"SupervisoryNode: 无法将事件放入 WorkflowRunningEngine: {e}")
|
||||
self.logger.error(
|
||||
f"SupervisoryNode: 无法将事件放入 WorkflowRunningEngine: {e}"
|
||||
)
|
||||
return "抱歉,任务提交失败,系统内部错误。"
|
||||
return f"任务已创建,准备创建工作流。原因:{result.reasoning}"
|
||||
elif isinstance(result, ForUser):
|
||||
@@ -144,7 +165,7 @@ class SupervisoryNode:
|
||||
|
||||
Returns:
|
||||
ForUser对象,监控节点对于用户进行的简单回答
|
||||
ForConsciousnessNode对象,监控节点将用户的请求判断为复杂任务,将PretorEvent传递给意识节点,并且给选择好的工作流模板
|
||||
ForConsciousnessNode对象,监控节点将用户的请求判断为复杂任务,将PretorEvent传递给意识节点
|
||||
"""
|
||||
...
|
||||
|
||||
@@ -160,7 +181,9 @@ class SupervisoryNode:
|
||||
"""
|
||||
...
|
||||
|
||||
async def _run(self, payload: Union[PretorEvent, TerminationMessage]) -> Union[ForConsciousnessNode, ForUser]:
|
||||
async def _run(
|
||||
self, payload: Union[PretorEvent, TerminationMessage]
|
||||
) -> Union[ForConsciousnessNode, ForUser]:
|
||||
"""
|
||||
_run方法,将payload转化为对llm发送的消息并发送
|
||||
Args:
|
||||
@@ -175,23 +198,15 @@ class SupervisoryNode:
|
||||
message = payload.message
|
||||
time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
try:
|
||||
global_state_machine = ray_actor_hook("global_state_machine").global_state_machine
|
||||
workflow_template_dict = await global_state_machine.get_all_workflow_templates.remote()
|
||||
available_templates_str = "\n".join([f"- 名称: {k}, 描述/内容: {v}" for k, v in
|
||||
workflow_template_dict.items()]) if workflow_template_dict else "暂无注册的工作流模板"
|
||||
deps = SupervisoryNodeDeps(
|
||||
platform=platform,
|
||||
user_name=user_name,
|
||||
time=time_str,
|
||||
available_templates=available_templates_str
|
||||
platform=platform, user_name=user_name, time=time_str
|
||||
)
|
||||
self.logger.debug("SupervisoryNode 开始生成 (启用原生 Pydantic-AI 重试)")
|
||||
prompt_message = message
|
||||
if isinstance(payload, TerminationMessage):
|
||||
prompt_message = f"【工作流执行结束报告】\n请将以下技术报告转化为对用户的友好回复:\n{message}"
|
||||
self.agent.retries = 3
|
||||
result = await self.agent.run(prompt_message,
|
||||
deps=deps)
|
||||
result = await self.agent.run(prompt_message, deps=deps)
|
||||
return result.output
|
||||
except Exception as e:
|
||||
self.logger.exception(f"SupervisoryNode 模型生成或解析最终失败: {str(e)}")
|
||||
|
||||
@@ -16,35 +16,46 @@ from pydantic import Field
|
||||
from pretor.utils.agent_model import ResponseModel, DepsModel
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class SupervisoryNodeResponse(ResponseModel):
|
||||
"""SupervisoryNodeResponse 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ForUser(SupervisoryNodeResponse):
|
||||
"""ForUser 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 ForUser 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
context: str = Field(..., description="对用户的回复,应当使用和蔼的语气进行回复。用于直接解答简单问题或返回最终报告。")
|
||||
这是一个领域数据模型或功能封装类,承载了 ForUser 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
context: str = Field(
|
||||
...,
|
||||
description="对用户的回复,应当使用和蔼的语气进行回复。用于直接解答简单问题或返回最终报告。",
|
||||
)
|
||||
|
||||
|
||||
class ForConsciousnessNode(SupervisoryNodeResponse):
|
||||
"""ForConsciousnessNode 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
workflow_template: str | None = Field(default=None, description="选择的工作流模板的名称,用于处理复杂任务。若无需模板则为 None。")
|
||||
reasoning: str = Field(..., description="选择将任务移交意识节点并选用该模板的简短原因。")
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
reasoning: str = Field(..., description="选择将任务移交意识节点的简短原因。")
|
||||
|
||||
|
||||
class TerminationMessage(BaseModel):
|
||||
"""TerminationMessage 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 TerminationMessage 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 TerminationMessage 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
platform: str
|
||||
user_name: str
|
||||
message: str
|
||||
|
||||
|
||||
class SupervisoryNodeDeps(DepsModel):
|
||||
"""SupervisoryNodeDeps 核心组件类。
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。 """
|
||||
这是一个系统执行节点类,作为多智能体架构中的独立处理单元。它能够接收工作流上下文,根据内置的大模型策略进行意图理解和自主决策,从而驱动特定阶段的任务闭环。"""
|
||||
|
||||
platform: str
|
||||
user_name: str
|
||||
time: str
|
||||
retry_count: int = 0
|
||||
error_history: str = ""
|
||||
available_templates: str = "默认工作流 (default_workflow)"
|
||||
@@ -0,0 +1,3 @@
|
||||
from pretor.core.postgres_database.postgres import PostgresDatabase
|
||||
|
||||
__all__ = ["PostgresDatabase"]
|
||||
@@ -26,19 +26,25 @@ from pretor.core.database.module.user import AuthDatabase
|
||||
from pretor.core.database.module.provider import ProviderDatabase
|
||||
from pretor.core.database.module.system_node import SystemNodeDatabase
|
||||
|
||||
|
||||
@ray.remote
|
||||
class PostgresDatabase:
|
||||
"""PostgresDatabase 核心组件类。
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。 """
|
||||
这是一个数据库操作层 (DAO/Repository) 封装类,专注于处理实体模型与关系型数据库表之间的映射。它将复杂的 SQL 查询、跨表 Join 和事务回滚逻辑进行了高级抽象,向上层服务暴露简洁的数据读写接口。"""
|
||||
|
||||
def __init__(self):
|
||||
user = os.environ.get('POSTGRES_USER')
|
||||
password = os.environ.get('POSTGRES_PASSWORD')
|
||||
host = os.environ.get('POSTGRES_HOST')
|
||||
port = os.environ.get('POSTGRES_PORT')
|
||||
database = os.environ.get('POSTGRES_DB')
|
||||
database_url = f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{database}"
|
||||
user = os.environ.get("POSTGRES_USER")
|
||||
password = os.environ.get("POSTGRES_PASSWORD")
|
||||
host = os.environ.get("POSTGRES_HOST")
|
||||
port = os.environ.get("POSTGRES_PORT")
|
||||
database = os.environ.get("POSTGRES_DB")
|
||||
database_url = (
|
||||
f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{database}"
|
||||
)
|
||||
self.async_engine = create_async_engine(database_url, echo=True)
|
||||
self.async_session_maker = sessionmaker(self.async_engine, class_=AsyncSession, expire_on_commit=False)
|
||||
self.async_session_maker = sessionmaker(
|
||||
self.async_engine, class_=AsyncSession, expire_on_commit=False
|
||||
)
|
||||
|
||||
self._auth_database = AuthDatabase(self.async_session_maker)
|
||||
self._provider_database = ProviderDatabase(self.async_session_maker)
|
||||
@@ -51,7 +57,7 @@ class PostgresDatabase:
|
||||
async def init_db(self) -> None:
|
||||
"""完成 db 模块的启动与依赖初始化。
|
||||
在系统引导或服务拉起阶段被调用,负责建立网络连接、分配基础内存资源及注册核心服务组件。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
async with self.async_engine.begin() as conn:
|
||||
await conn.run_sync(SQLModel.metadata.create_all)
|
||||
@@ -67,7 +73,7 @@ class PostgresDatabase:
|
||||
"""创建并持久化新的 user 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 hashed_password (str): 控制逻辑流向的具体字符串参数,指定了期望的 hashed password 内容。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.add_user(user_name, hashed_password)
|
||||
|
||||
@@ -75,15 +81,17 @@ class PostgresDatabase:
|
||||
"""执行与 change password 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: user_name: 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 old_password: 参与 change password 逻辑运算或数据构建的上下文依赖对象。 new_password: 参与 change password 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.change_password(user_name, old_password, new_password)
|
||||
return await self._auth_database.change_password(
|
||||
user_name, old_password, new_password
|
||||
)
|
||||
|
||||
async def delete_user(self, user_name: str):
|
||||
"""安全地移除或注销 user。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.delete_user(user_name)
|
||||
|
||||
@@ -91,7 +99,7 @@ class PostgresDatabase:
|
||||
"""安全地移除或注销 user by id。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.delete_user_by_id(user_id)
|
||||
|
||||
@@ -99,14 +107,14 @@ class PostgresDatabase:
|
||||
"""执行与 login user 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: user_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.login_user(user_name)
|
||||
|
||||
async def get_all_users(self):
|
||||
"""检索并获取特定的 all users 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.get_all_users()
|
||||
|
||||
@@ -114,7 +122,7 @@ class PostgresDatabase:
|
||||
"""检索并获取特定的 user authority 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.get_user_authority(user_id)
|
||||
|
||||
@@ -122,7 +130,7 @@ class PostgresDatabase:
|
||||
"""执行与 change user authority 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: user_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 user 实例。 new_authority: 参与 change user authority 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._auth_database.change_user_authority(user_id, new_authority)
|
||||
|
||||
@@ -130,14 +138,14 @@ class PostgresDatabase:
|
||||
async def get_provider(self):
|
||||
"""检索并获取特定的 provider 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._provider_database.get_provider()
|
||||
|
||||
async def add_provider_db(self, **kwargs):
|
||||
"""创建并持久化新的 provider db 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._provider_database.add_provider(**kwargs)
|
||||
|
||||
@@ -145,7 +153,7 @@ class PostgresDatabase:
|
||||
"""安全地移除或注销 provider db。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: provider_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._provider_database.delete_provider(provider_id)
|
||||
|
||||
@@ -153,23 +161,31 @@ class PostgresDatabase:
|
||||
"""对现有的 provider db 进行状态更新或属性覆盖。
|
||||
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
|
||||
Args: provider_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._provider_database.update_provider(provider_id, **kwargs)
|
||||
|
||||
# System Node Database Methods
|
||||
async def upsert_system_node_config(self, node_name: str, provider_title: str, model_id: str, tools: list[str] = None):
|
||||
async def upsert_system_node_config(
|
||||
self,
|
||||
node_name: str,
|
||||
provider_title: str,
|
||||
model_id: str,
|
||||
tools: list[str] = None,
|
||||
):
|
||||
"""执行与 upsert system node config 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: node_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 provider_title (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 provider_title 实例。 model_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 model 实例。 tools (list[str]): 控制逻辑流向的具体字符串参数,指定了期望的 tools 内容。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._system_node_database.upsert_system_node_config(node_name, provider_title, model_id, tools)
|
||||
return await self._system_node_database.upsert_system_node_config(
|
||||
node_name, provider_title, model_id, tools
|
||||
)
|
||||
|
||||
async def get_all_system_node_configs(self):
|
||||
"""检索并获取特定的 all system node configs 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._system_node_database.get_all_system_node_configs()
|
||||
|
||||
@@ -177,7 +193,7 @@ class PostgresDatabase:
|
||||
async def add_worker_individual(self, **kwargs):
|
||||
"""创建并持久化新的 worker individual 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.add_worker_individual(**kwargs)
|
||||
|
||||
@@ -185,7 +201,7 @@ class PostgresDatabase:
|
||||
"""检索并获取特定的 worker individual 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.get_worker_individual(agent_id)
|
||||
|
||||
@@ -193,7 +209,7 @@ class PostgresDatabase:
|
||||
"""检索并获取特定的 worker individual list 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: owner_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 owner 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.get_worker_individual_list(owner_id)
|
||||
|
||||
@@ -201,24 +217,27 @@ class PostgresDatabase:
|
||||
"""对现有的 worker individual 进行状态更新或属性覆盖。
|
||||
基于增量变更原则,合并最新的配置或数据,并触发相关依赖组件的缓存刷新或事件通知。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.update_worker_individual(agent_id, **kwargs)
|
||||
return await self._individual_database.update_worker_individual(
|
||||
agent_id, **kwargs
|
||||
)
|
||||
|
||||
async def delete_worker_individual(self, agent_id: str):
|
||||
"""安全地移除或注销 worker individual。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: agent_id (str): 目标对象的唯一全局标识符 (UUID/ULID),用于在数据库表或缓存结构中精准匹配该 agent 实例。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.delete_worker_individual(agent_id)
|
||||
|
||||
async def get_all_worker_individual(self):
|
||||
"""检索并获取特定的 all worker individual 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: : 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.ready_event.wait()
|
||||
return await self._individual_database.get_all_worker_individual()
|
||||
|
||||
# Event Database Methods
|
||||
async def upsert_event(self, trace_id: str, event_data_json: str):
|
||||
await self.ready_event.wait()
|
||||
@@ -16,69 +16,88 @@ from typing import List, Optional, Union, Literal, Dict, Any
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('workflow')
|
||||
|
||||
logger = get_logger("workflow")
|
||||
NodeType = Literal[
|
||||
"consciousness_node", "control_node", "supervisory_node", "skill_individual"
|
||||
]
|
||||
|
||||
|
||||
class EventInfo(BaseModel):
|
||||
"""EventInfo 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 EventInfo 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 EventInfo 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
platform: str
|
||||
user_name: str
|
||||
|
||||
|
||||
class LogicGate(BaseModel):
|
||||
"""LogicGate 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 LogicGate 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 LogicGate 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
if_fail: str = Field(..., description="失败跳转目标,如 'jump_to_step_1'")
|
||||
if_pass: Literal["continue", "exit"] = Field(default="continue", description="成功后的动作")
|
||||
if_pass: Literal["continue", "exit"] = Field(
|
||||
default="continue", description="成功后的动作"
|
||||
)
|
||||
|
||||
|
||||
class WorkStep(BaseModel):
|
||||
"""WorkStep 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkStep 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkStep 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
step: int = Field(..., gt=0, description="步骤序号,严格自增")
|
||||
name: str = Field(..., description="步骤名称")
|
||||
node: NodeType = Field(..., description="负责执行的节点类型")
|
||||
action: str = Field(..., description="执行的原子动作")
|
||||
desc: str = Field(..., description="动作细节的自然语言描述,包含人工规范指导")
|
||||
inputs: Optional[Union[str, List[str]]] = Field(default=None, description="前置依赖输出")
|
||||
inputs: Optional[Union[str, List[str]]] = Field(
|
||||
default=None, description="前置依赖输出"
|
||||
)
|
||||
outputs: Optional[str] = Field(default=None, description="当前步骤产出物变量名")
|
||||
agent_id: Optional[str] = Field(default=None, description="分配给 skill_individual 的 Skill Individual 真实 agent_id,不可用名称代替")
|
||||
agent_id: Optional[str] = Field(
|
||||
default=None,
|
||||
description="分配给 skill_individual 的 Skill Individual 真实 agent_id,不可用名称代替",
|
||||
)
|
||||
logic_gate: Optional[LogicGate] = Field(default=None, description="逻辑跳转控制")
|
||||
status: Literal["waiting", "running", "completed", "failed"] = Field(
|
||||
default="waiting",
|
||||
description="执行状态 (LLM建议保留默认值)"
|
||||
default="waiting", description="执行状态 (LLM建议保留默认值)"
|
||||
)
|
||||
|
||||
|
||||
class WorkflowStatus(BaseModel):
|
||||
"""WorkflowStatus 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowStatus 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowStatus 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
step: int = Field(default=1, gt=0, description="当前运行到的工作流步数")
|
||||
status: Literal["waiting_llm_working", "waiting_tool_working", "llm_working", "tool_working"] = Field(
|
||||
default="waiting_llm_working",
|
||||
description="当前系统调度状态"
|
||||
)
|
||||
status: Literal[
|
||||
"waiting_llm_working", "waiting_tool_working", "llm_working", "tool_working"
|
||||
] = Field(default="waiting_llm_working", description="当前系统调度状态")
|
||||
|
||||
|
||||
class PretorWorkflow(BaseModel):
|
||||
"""PretorWorkflow 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 PretorWorkflow 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
这是一个领域数据模型或功能封装类,承载了 PretorWorkflow 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
title: str = Field(..., description="工作流的标题")
|
||||
work_link: List[WorkStep] = Field(..., description="工作链逻辑定义")
|
||||
# ---------------- 以下为系统级管控字段,LLM 无需关心 ---------------- #
|
||||
trace_id: str | None = Field(description="系统自动生成的追溯ID")
|
||||
version: str = Field(default="v1.0", description="系统协议版本号")
|
||||
command: Optional[str] = Field(default=None, description="触发此工作流的原始命令")
|
||||
output: Dict[str, Any] = Field(default_factory=dict, description="工作流最终产出结果")
|
||||
status: WorkflowStatus = Field(default_factory=WorkflowStatus, description="运行时状态对象")
|
||||
output: Dict[str, Any] = Field(
|
||||
default_factory=dict, description="工作流最终产出结果"
|
||||
)
|
||||
status: WorkflowStatus = Field(
|
||||
default_factory=WorkflowStatus, description="运行时状态对象"
|
||||
)
|
||||
event_info: EventInfo | None = Field(default=None)
|
||||
context_memory: Dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
@model_validator(mode='after')
|
||||
def validate_workflow_integrity(self) -> 'PretorWorkflow':
|
||||
@model_validator(mode="after")
|
||||
def validate_workflow_integrity(self) -> "PretorWorkflow":
|
||||
"""执行与 validate workflow integrity 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: ('PretorWorkflow'): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: ('PretorWorkflow'): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
steps = [s.step for s in self.work_link]
|
||||
expected = list(range(1, len(steps) + 1))
|
||||
if steps != expected:
|
||||
@@ -90,9 +109,11 @@ class PretorWorkflow(BaseModel):
|
||||
try:
|
||||
target = int(s.logic_gate.if_fail.split("_")[-1])
|
||||
if target > max_step or target < 1:
|
||||
raise ValueError(f"Step {s.step} 的跳转目标 Step {target} 越界了!")
|
||||
raise ValueError(
|
||||
f"Step {s.step} 的跳转目标 Step {target} 越界了!"
|
||||
)
|
||||
except ValueError as e:
|
||||
if "越界" in str(e):
|
||||
raise e
|
||||
raise ValueError(f"LogicGate 格式错误: {s.logic_gate.if_fail}")
|
||||
return self
|
||||
return self
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# Copyright 2026 zhaoxi826
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# Copyright 2026 zhaoxi826
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from pydantic import BaseModel, model_validator
|
||||
from typing import Dict,List
|
||||
|
||||
class WorkflowTemplateStep(BaseModel):
|
||||
"""WorkflowTemplateStep 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowTemplateStep 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
step: int
|
||||
node: str
|
||||
action: str
|
||||
desc: str
|
||||
input: List[str]
|
||||
output: List[str]
|
||||
logic_gate: Dict[str, str]
|
||||
|
||||
class WorkflowTemplate(BaseModel):
|
||||
"""WorkflowTemplate 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowTemplate 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
name: str
|
||||
desc: str
|
||||
work_link: list[WorkflowTemplateStep]
|
||||
|
||||
@model_validator(mode='after')
|
||||
def validate_steps(self) -> 'WorkflowTemplate':
|
||||
"""执行与 validate steps 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: ('WorkflowTemplate'): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
steps = [s.step for s in self.work_link]
|
||||
if len(steps) != len(set(steps)):
|
||||
raise ValueError("Step numbers in work_link must be unique")
|
||||
return self
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# Copyright 2026 zhaoxi826
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from pathlib import Path
|
||||
from pretor.core.workflow.workflow_template_generator.workflow_template import WorkflowTemplate
|
||||
|
||||
class WorkflowTemplateGenerator:
|
||||
"""WorkflowTemplateGenerator 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowTemplateGenerator 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
@staticmethod
|
||||
def generate_workflow_template(workflow_template: WorkflowTemplate) -> WorkflowTemplate:
|
||||
"""执行与 generate workflow template 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: workflow_template (WorkflowTemplate): 参与 generate workflow template 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (WorkflowTemplate): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
output_dir = Path("pretor") / "workflow_template"
|
||||
if not output_dir.exists():
|
||||
output_dir.mkdir(parents=True)
|
||||
output_file = output_dir / f"{workflow_template.name}_workflow_template.json"
|
||||
with output_file.open("w", encoding="utf-8") as f:
|
||||
f.write(workflow_template.model_dump_json(indent=4))
|
||||
@@ -1,76 +0,0 @@
|
||||
# Copyright 2026 zhaoxi826
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
from pretor.core.workflow.workflow_template_generator.workflow_template_generator import WorkflowTemplateGenerator
|
||||
from pathlib import Path
|
||||
from pretor.core.workflow.workflow_template_generator.workflow_template import WorkflowTemplate
|
||||
|
||||
from pretor.utils.logger import get_logger
|
||||
logger = get_logger('workflow_template_manager')
|
||||
|
||||
class WorkflowManager:
|
||||
"""WorkflowManager 核心组件类。
|
||||
这是一个管理器类,职责集中在维护整个系统内有关 Workflow 资源的全局生命周期。它提供了注册机制、状态同步以及跨组件的统一查询入口,确保系统中该类型资源的实例一致性与可控性。 """
|
||||
def __init__(self):
|
||||
self.workflow_template_generator = WorkflowTemplateGenerator()
|
||||
self.workflow_templates_registry = {}
|
||||
self.template_path = Path("pretor/workflow_template")
|
||||
self._load_workflow_template()
|
||||
|
||||
def _load_workflow_template(self) -> None:
|
||||
"""执行与 load workflow template 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
for workflow_template_file in self.template_path.glob("*_workflow_template.json"):
|
||||
with workflow_template_file.open("r",encoding="utf-8") as f:
|
||||
try:
|
||||
workflow_template = json.load(f)
|
||||
self.workflow_templates_registry[workflow_template.get("name")] = workflow_template.get("desc")
|
||||
except json.decoder.JSONDecodeError:
|
||||
logger.warning(f"{workflow_template_file}不是json文件或格式错误")
|
||||
except KeyError:
|
||||
logger.warning(f"{workflow_template_file}不符合workflow_template格式")
|
||||
|
||||
def generate_workflow_template(self, workflow_template: WorkflowTemplate) -> None:
|
||||
"""执行与 generate workflow template 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: workflow_template (WorkflowTemplate): 参与 generate workflow template 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
try:
|
||||
workflow_template = self.workflow_template_generator.generate_workflow_template(workflow_template=workflow_template)
|
||||
self.workflow_templates_registry[workflow_template.name] = workflow_template.desc
|
||||
except Exception:
|
||||
logger.exception("Failed to generate workflow template")
|
||||
|
||||
def add_workflow_template(self, template_name: str, workflow_template: WorkflowTemplate) -> None:
|
||||
"""创建并持久化新的 workflow template 实体。
|
||||
接收构建参数,执行必要的数据校验与默认值填充后,将新记录安全地写入底层存储或系统注册表中。
|
||||
Args: template_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。 workflow_template (WorkflowTemplate): 参与 add workflow template 逻辑运算或数据构建的上下文依赖对象。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
self.generate_workflow_template(workflow_template)
|
||||
|
||||
def get_all_workflow_templates(self) -> dict:
|
||||
"""检索并获取特定的 all workflow templates 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Returns: (dict): 高度聚合的字典结构数据,将多维度的属性特征或统计指标组合后一并返回。 """
|
||||
return self.workflow_templates_registry
|
||||
|
||||
def delete_workflow_template(self, template_name: str) -> None:
|
||||
"""安全地移除或注销 workflow template。
|
||||
执行物理删除或逻辑删除操作,并妥善清理相关的关联数据及占用资源。
|
||||
Args: template_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
if template_name in self.workflow_templates_registry:
|
||||
del self.workflow_templates_registry[template_name]
|
||||
@@ -0,0 +1,3 @@
|
||||
from pretor.core.workflow_running_engine.workflow_runner import WorkflowRunningEngine
|
||||
|
||||
__all__ = ["WorkflowRunningEngine"]
|
||||
+141
-85
@@ -19,44 +19,40 @@ from pretor.core.workflow.workflow import PretorWorkflow, WorkStep, EventInfo
|
||||
from typing import Optional, Dict, Union, Any, List
|
||||
from pretor.utils.error import WorkflowError, WorkflowExit
|
||||
from pretor.api.platform.event import PretorEvent
|
||||
from pretor.core.individual.control_node.template import ForWorkflowInput as ControlForWorkflowInput, \
|
||||
ForWorkflow as ControlForWorkflow
|
||||
from pretor.core.individual.control_node.template import (
|
||||
ForWorkflowInput as ControlForWorkflowInput,
|
||||
ForWorkflow as ControlForWorkflow,
|
||||
)
|
||||
from pretor.core.individual.consciousness_node.template import (
|
||||
ForWorkflowInput as ConsciousnessForWorkflowInput,
|
||||
ForSupervisoryInput,
|
||||
ForSupervisoryNode,
|
||||
ForWorkflow as ConsciousnessForWorkflow,
|
||||
ForWorkflowEngineInput,
|
||||
ForWorkflowEngine
|
||||
ForWorkflowEngine,
|
||||
)
|
||||
from pretor.core.individual.supervisory_node.template import TerminationMessage
|
||||
import pathlib
|
||||
|
||||
|
||||
def get_workflow_template(workflow_name: str) -> str:
|
||||
"""检索并获取特定的 workflow template 数据集合或实例对象。
|
||||
根据提供的查询条件或上下文凭证,从数据库、缓存或第三方服务中读取对应的资源状态。
|
||||
Args: workflow_name (str): 赋予该实体的人类可读名称或标题字符串,主要用于前端 UI 展示、日志记录或模糊检索。
|
||||
Returns: (str): 处理流程所输出的具体字符串产物,可能是新生成的 ID 序列、格式化好的文本片段或 LLM 推理的回答内容。 """
|
||||
workflow_template = pathlib.Path(__file__).parent.parent.parent / "workflow_template" / (workflow_name + "_workflow_template.json")
|
||||
with open(workflow_template, "r", encoding="utf-8") as workflow_template_file:
|
||||
workflow_template = workflow_template_file.read()
|
||||
return workflow_template
|
||||
|
||||
|
||||
class WorkflowEngine:
|
||||
"""WorkflowEngine 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowEngine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
def __init__(self,
|
||||
workflow: PretorWorkflow,
|
||||
consciousness_node=None,
|
||||
control_node=None,
|
||||
supervisory_node=None):
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowEngine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
workflow: PretorWorkflow,
|
||||
consciousness_node=None,
|
||||
control_node=None,
|
||||
supervisory_node=None,
|
||||
):
|
||||
from pretor.utils.logger import get_logger
|
||||
self.logger = get_logger('workflow_runner')
|
||||
|
||||
self.logger = get_logger("workflow_runner")
|
||||
self.workflow: PretorWorkflow = workflow
|
||||
"""工作流:当前WorkflowEngine待执行的workflow"""
|
||||
self._steps_by_id: Dict[int, WorkStep] = {step.step: step for step in self.workflow.work_link}
|
||||
self._steps_by_id: Dict[int, WorkStep] = {
|
||||
step.step: step for step in self.workflow.work_link
|
||||
}
|
||||
"""步骤表:将当前workflow的步骤序号和步骤内容存放"""
|
||||
self.consciousness_node = consciousness_node
|
||||
"""意识节点"""
|
||||
@@ -70,7 +66,7 @@ class WorkflowEngine:
|
||||
"""执行与 push sse 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: msg (str): 控制逻辑流向的具体字符串参数,指定了期望的 msg 内容。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
try:
|
||||
await self._gwm.put_pending.remote(self.workflow.trace_id, msg)
|
||||
except Exception:
|
||||
@@ -95,37 +91,55 @@ class WorkflowEngine:
|
||||
|
||||
async def run(self):
|
||||
"""
|
||||
run方法
|
||||
处理并执行workflow的方法
|
||||
run方法
|
||||
处理并执行workflow的方法
|
||||
|
||||
"""
|
||||
self.logger.info(f"🚀 工作流引擎启动: {self.workflow.title} [Trace ID: {self.workflow.trace_id}]")
|
||||
self.logger.info(
|
||||
f"🚀 工作流引擎启动: {self.workflow.title} [Trace ID: {self.workflow.trace_id}]"
|
||||
)
|
||||
await self._push_sse(f"[工作流启动] {self.workflow.title}")
|
||||
max_step = len(self.workflow.work_link)
|
||||
while 1 <= self.workflow.status.step <= max_step:
|
||||
current_step_id = self.workflow.status.step
|
||||
current_step = self._steps_by_id.get(current_step_id)
|
||||
if not current_step:
|
||||
self.logger.error(f"严重错误:找不到步骤 {current_step_id},工作流强制终止。")
|
||||
self.logger.error(
|
||||
f"严重错误:找不到步骤 {current_step_id},工作流强制终止。"
|
||||
)
|
||||
self.workflow.status.status = "failed"
|
||||
await self._push_sse(f"[工作流失败] 找不到步骤 {current_step_id}")
|
||||
break
|
||||
self.logger.info(f"▶️ 开始执行 Step {current_step_id}: [{current_step.node}] -> {current_step.action}")
|
||||
self.logger.info(
|
||||
f"▶️ 开始执行 Step {current_step_id}: [{current_step.node}] -> {current_step.action}"
|
||||
)
|
||||
current_step.status = "running"
|
||||
await self._push_sse(f"[Step {current_step_id}] {current_step.name}: {current_step.desc}")
|
||||
await self._push_sse(
|
||||
f"[Step {current_step_id}] {current_step.name}: {current_step.desc}"
|
||||
)
|
||||
try:
|
||||
step_input_data = self._prepare_inputs(current_step.inputs)
|
||||
step_result, is_success = await self._dispatch_to_node(current_step, step_input_data)
|
||||
step_result, is_success = await self._dispatch_to_node(
|
||||
current_step, step_input_data
|
||||
)
|
||||
if is_success:
|
||||
if current_step.outputs:
|
||||
self.workflow.context_memory[current_step.outputs] = step_result
|
||||
self.logger.debug(f"Step {current_step_id} 产出已保存至变量: '{current_step.outputs}'")
|
||||
self.logger.debug(
|
||||
f"Step {current_step_id} 产出已保存至变量: '{current_step.outputs}'"
|
||||
)
|
||||
current_step.status = "completed"
|
||||
await self._push_sse(f"[Step {current_step_id} 完成] {current_step.name}")
|
||||
await self._push_sse(
|
||||
f"[Step {current_step_id} 完成] {current_step.name}"
|
||||
)
|
||||
else:
|
||||
self.logger.warning(f"Step {current_step_id} 执行遇到业务失败/驳回。")
|
||||
self.logger.warning(
|
||||
f"Step {current_step_id} 执行遇到业务失败/驳回。"
|
||||
)
|
||||
current_step.status = "failed"
|
||||
await self._push_sse(f"[Step {current_step_id} 失败] {current_step.name}")
|
||||
await self._push_sse(
|
||||
f"[Step {current_step_id} 失败] {current_step.name}"
|
||||
)
|
||||
self._handle_logic_gate(current_step, is_success)
|
||||
except WorkflowExit:
|
||||
self.logger.info("命中 if_pass='exit',工作流被主动要求结束。")
|
||||
@@ -137,7 +151,10 @@ class WorkflowEngine:
|
||||
await self._push_sse(f"[工作流失败] {e}")
|
||||
break
|
||||
except Exception as e:
|
||||
self.logger.error(f"❌ Step {current_step_id} 发生系统级未捕获异常: {e}", exc_info=True)
|
||||
self.logger.error(
|
||||
f"❌ Step {current_step_id} 发生系统级未捕获异常: {e}",
|
||||
exc_info=True,
|
||||
)
|
||||
current_step.status = "failed"
|
||||
self.workflow.status.status = "failed"
|
||||
await self._push_sse(f"[工作流异常] {e}")
|
||||
@@ -163,9 +180,11 @@ class WorkflowEngine:
|
||||
if self.consciousness_node:
|
||||
supervisory_input = ForSupervisoryInput(
|
||||
workflow=self.workflow,
|
||||
original_command=self.workflow.command or "未知命令"
|
||||
original_command=self.workflow.command or "未知命令",
|
||||
)
|
||||
report_obj = await self.consciousness_node.working.remote(
|
||||
supervisory_input
|
||||
)
|
||||
report_obj = await self.consciousness_node.working.remote(supervisory_input)
|
||||
if isinstance(report_obj, ForSupervisoryNode):
|
||||
report = report_obj.output
|
||||
elif isinstance(report_obj, str):
|
||||
@@ -178,7 +197,7 @@ class WorkflowEngine:
|
||||
term_msg = TerminationMessage(
|
||||
platform=self.workflow.event_info.platform,
|
||||
user_name=self.workflow.event_info.user_name,
|
||||
message=f"工作流执行完毕。系统报告:{report}"
|
||||
message=f"工作流执行完毕。系统报告:{report}",
|
||||
)
|
||||
user_response = await self.supervisory_node.working.remote(term_msg)
|
||||
self.workflow.context_memory["_final_user_response"] = user_response
|
||||
@@ -188,7 +207,9 @@ class WorkflowEngine:
|
||||
except Exception:
|
||||
self.logger.exception("生成工作流执行汇报时发生错误")
|
||||
|
||||
async def _dispatch_to_node(self, step: WorkStep, input_data: Any) -> tuple[Any, bool]:
|
||||
async def _dispatch_to_node(
|
||||
self, step: WorkStep, input_data: Any
|
||||
) -> tuple[Any, bool]:
|
||||
"""
|
||||
分流器
|
||||
调用当前step的执行对象
|
||||
@@ -216,8 +237,7 @@ class WorkflowEngine:
|
||||
raise WorkflowError("未提供 consciousness_node 句柄!")
|
||||
original_cmd = self.workflow.command or ""
|
||||
payload = ConsciousnessForWorkflowInput(
|
||||
workflow_step=step,
|
||||
original_command=original_cmd
|
||||
workflow_step=step, original_command=original_cmd
|
||||
)
|
||||
result_obj = await self.consciousness_node.working.remote(payload)
|
||||
if isinstance(result_obj, ConsciousnessForWorkflow):
|
||||
@@ -225,9 +245,12 @@ class WorkflowEngine:
|
||||
return result_obj, True
|
||||
|
||||
elif step.node == "skill_individual":
|
||||
self.logger.info(f"正在通过 WorkerCluster 调度 skill_individual 执行 {step.action}。")
|
||||
self.logger.info(
|
||||
f"正在通过 WorkerCluster 调度 skill_individual 执行 {step.action}。"
|
||||
)
|
||||
try:
|
||||
from pretor.utils.ray_hook import ray_actor_hook
|
||||
|
||||
worker_cluster = ray_actor_hook("worker_cluster").worker_cluster
|
||||
task_id = f"{self.workflow.trace_id}_step_{step.step}"
|
||||
agent_id = step.agent_id or f"default_{step.node}"
|
||||
@@ -235,18 +258,24 @@ class WorkflowEngine:
|
||||
"action": step.action,
|
||||
"description": step.desc,
|
||||
"input_data": input_data,
|
||||
"context_memory": self.workflow.context_memory
|
||||
"context_memory": self.workflow.context_memory,
|
||||
}
|
||||
result_response = await worker_cluster.submit_task.remote(task_id, agent_id, task_event)
|
||||
result_response = await worker_cluster.submit_task.remote(
|
||||
task_id, agent_id, task_event
|
||||
)
|
||||
|
||||
if result_response.get("success"):
|
||||
return result_response.get("data"), True
|
||||
else:
|
||||
self.logger.error(f"WorkerCluster 执行 {step.node} 失败: {result_response.get('error')}")
|
||||
self.logger.error(
|
||||
f"WorkerCluster 执行 {step.node} 失败: {result_response.get('error')}"
|
||||
)
|
||||
return result_response.get("error"), False
|
||||
|
||||
except Exception as e:
|
||||
self.logger.exception(f"调度 WorkerCluster 执行 {step.node} 时发生异常: {e}")
|
||||
self.logger.exception(
|
||||
f"调度 WorkerCluster 执行 {step.node} 时发生异常: {e}"
|
||||
)
|
||||
raise WorkflowError(f"WorkerCluster 调度异常: {e}")
|
||||
else:
|
||||
raise WorkflowError(f"未知的节点类型:{step.node}")
|
||||
@@ -275,7 +304,9 @@ class WorkflowEngine:
|
||||
match gate.if_fail.split("_"):
|
||||
case ["jump", "to", "step", target] if target.isdigit():
|
||||
target_step = int(target)
|
||||
self.logger.warning(f"触发逻辑门分支!从 Step {step.step} 跳转至 Step {target_step}")
|
||||
self.logger.warning(
|
||||
f"触发逻辑门分支!从 Step {step.step} 跳转至 Step {target_step}"
|
||||
)
|
||||
self.workflow.status.step = target_step
|
||||
case _:
|
||||
raise WorkflowError(f"未知的 if_fail 格式: {gate.if_fail}")
|
||||
@@ -284,10 +315,14 @@ class WorkflowEngine:
|
||||
@ray.remote
|
||||
class WorkflowRunningEngine:
|
||||
"""WorkflowRunningEngine 核心组件类。
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowRunningEngine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。 """
|
||||
def __init__(self, consciousness_node=None, control_node=None, supervisory_node=None):
|
||||
这是一个领域数据模型或功能封装类,承载了 WorkflowRunningEngine 相关的内聚属性定义与状态维护。它的存在隔离了局部的业务复杂性,并对外提供了类型安全的访问接口。"""
|
||||
|
||||
def __init__(
|
||||
self, consciousness_node=None, control_node=None, supervisory_node=None
|
||||
):
|
||||
from pretor.utils.logger import get_logger
|
||||
self.logger = get_logger('workflow_runner')
|
||||
|
||||
self.logger = get_logger("workflow_runner")
|
||||
self.runner_engine = {}
|
||||
self.workflow_queue: asyncio.Queue[PretorEvent] = None
|
||||
self.consciousness_node = consciousness_node
|
||||
@@ -298,28 +333,31 @@ class WorkflowRunningEngine:
|
||||
async def run(self):
|
||||
# Move actor hook to async start so we don't race during __init__ across cluster
|
||||
"""执行与 run 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。 """
|
||||
self.global_state_machine = ray_actor_hook("global_state_machine").global_state_machine
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。"""
|
||||
self.global_state_machine = ray_actor_hook(
|
||||
"global_state_machine"
|
||||
).global_state_machine
|
||||
self.workflow_queue = asyncio.Queue()
|
||||
self.runner_engine = {
|
||||
f"runner_{i}": asyncio.create_task(self.runner(i))
|
||||
for i in range(10)
|
||||
f"runner_{i}": asyncio.create_task(self.runner(i)) for i in range(10)
|
||||
}
|
||||
|
||||
async def put_event(self, event: PretorEvent) -> None:
|
||||
"""执行与 put event 相关的核心业务流转操作。
|
||||
该方法封装了具体的算法策略或状态控制逻辑,确保操作能够在事务上下文中被原子且一致地执行。
|
||||
Args: event (PretorEvent): 由事件总线或工作流引擎分发过来的事件载荷,封装了触发此次调用的上下文快照与任务目标指令。
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。 """
|
||||
Returns: (None): 经由当前业务模型加工处理后所输出的具体数据实例或领域模型对象。"""
|
||||
await self.workflow_queue.put(event)
|
||||
|
||||
async def resume_workflow(self, event: PretorEvent) -> None:
|
||||
"""Resume an incomplete workflow that was loaded from the database."""
|
||||
self.logger.info(f"Resuming workflow {event.trace_id}")
|
||||
workflow_engine = WorkflowEngine(event.workflow,
|
||||
self.consciousness_node,
|
||||
self.control_node,
|
||||
self.supervisory_node)
|
||||
workflow_engine = WorkflowEngine(
|
||||
event.workflow,
|
||||
self.consciousness_node,
|
||||
self.control_node,
|
||||
self.supervisory_node,
|
||||
)
|
||||
# Assuming you want to schedule it via a task
|
||||
asyncio.create_task(workflow_engine.run())
|
||||
|
||||
@@ -333,33 +371,37 @@ class WorkflowRunningEngine:
|
||||
while True:
|
||||
try:
|
||||
event = await self.workflow_queue.get()
|
||||
self.logger.info(f"WorkflowRunningEngine: runner_{i} 接收到事件 {event.trace_id} 准备生成工作流。")
|
||||
self.logger.info(
|
||||
f"WorkflowRunningEngine: runner_{i} 接收到事件 {event.trace_id} 准备生成工作流。"
|
||||
)
|
||||
|
||||
if not self.consciousness_node:
|
||||
raise WorkflowError("未配置 consciousness_node,无法生成工作流")
|
||||
|
||||
workflow_template_name = event.context.get("workflow_template", "")
|
||||
workflow_template = get_workflow_template(workflow_template_name) if workflow_template_name else None
|
||||
|
||||
available_skills = None
|
||||
if self.global_state_machine:
|
||||
try:
|
||||
all_individuals = await self.global_state_machine.list_individuals.remote()
|
||||
all_individuals = (
|
||||
await self.global_state_machine.list_individuals.remote()
|
||||
)
|
||||
available_skills = []
|
||||
for agent_id, config in all_individuals.items():
|
||||
if config.get("agent_type") == "skill_individual" or config.get("type") == "skill_individual":
|
||||
available_skills.append({
|
||||
"agent_id": agent_id,
|
||||
"name": config.get("agent_name", "Unknown"),
|
||||
"description": config.get("description", "")
|
||||
})
|
||||
if (
|
||||
config.get("agent_type") == "skill_individual"
|
||||
or config.get("type") == "skill_individual"
|
||||
):
|
||||
available_skills.append(
|
||||
{
|
||||
"agent_id": agent_id,
|
||||
"name": config.get("agent_name", "Unknown"),
|
||||
"description": config.get("description", ""),
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
self.logger.warning(f"获取Skill Individual列表失败: {e}")
|
||||
|
||||
payload = ForWorkflowEngineInput(
|
||||
original_command=event.message,
|
||||
workflow_template=workflow_template,
|
||||
available_skills=available_skills
|
||||
original_command=event.message, available_skills=available_skills
|
||||
)
|
||||
|
||||
result_obj = await self.consciousness_node.working.remote(payload)
|
||||
@@ -369,25 +411,39 @@ class WorkflowRunningEngine:
|
||||
|
||||
workflow.trace_id = event.trace_id
|
||||
workflow.command = event.message
|
||||
workflow.event_info = EventInfo(platform=event.platform,
|
||||
user_name=event.user_name,)
|
||||
workflow.event_info = EventInfo(
|
||||
platform=event.platform,
|
||||
user_name=event.user_name,
|
||||
)
|
||||
|
||||
self.logger.info(
|
||||
f"WorkflowRunningEngine: runner_{i} 成功生成工作流 {workflow.trace_id}:{workflow.title}")
|
||||
f"WorkflowRunningEngine: runner_{i} 成功生成工作流 {workflow.trace_id}:{workflow.title}"
|
||||
)
|
||||
|
||||
global_workflow_manager = ray_actor_hook("global_workflow_manager").global_workflow_manager
|
||||
await global_workflow_manager.update_workflow.remote(event.trace_id, workflow)
|
||||
global_workflow_manager = ray_actor_hook(
|
||||
"global_workflow_manager"
|
||||
).global_workflow_manager
|
||||
await global_workflow_manager.update_workflow.remote(
|
||||
event.trace_id, workflow
|
||||
)
|
||||
|
||||
workflow_engine = WorkflowEngine(workflow,
|
||||
self.consciousness_node,
|
||||
self.control_node,
|
||||
self.supervisory_node)
|
||||
workflow_engine = WorkflowEngine(
|
||||
workflow,
|
||||
self.consciousness_node,
|
||||
self.control_node,
|
||||
self.supervisory_node,
|
||||
)
|
||||
await workflow_engine.run()
|
||||
else:
|
||||
self.logger.error(f"WorkflowRunningEngine: runner_{i} 无法生成工作流,返回类型为 {type(result_obj)}")
|
||||
self.logger.error(
|
||||
f"WorkflowRunningEngine: runner_{i} 无法生成工作流,返回类型为 {type(result_obj)}"
|
||||
)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
self.logger.info(f"WorkflowRunningEngine: runner_{i} 被取消。")
|
||||
raise
|
||||
except Exception as e:
|
||||
self.logger.error(f"WorkflowRunningEngine: runner_{i} 遇到未捕获的异常: {e}", exc_info=True)
|
||||
self.logger.error(
|
||||
f"WorkflowRunningEngine: runner_{i} 遇到未捕获的异常: {e}",
|
||||
exc_info=True,
|
||||
)
|
||||
Reference in New Issue
Block a user