fix: sdk
This commit is contained in:
parent
5f6a302dfd
commit
3c247b2d3b
|
|
@ -0,0 +1,328 @@
|
|||
use anyhow::{Result, anyhow};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::{info, warn, error, debug};
|
||||
|
||||
use crate::config::ComfyUISettings;
|
||||
use crate::business::services::comfyui_service::ComfyUIService;
|
||||
use crate::business::services::comfyui_sdk_service::{ComfyUISDKService, WorkflowExecutionResult, SDKExecutionConfig};
|
||||
use crate::data::models::outfit_photo_generation::{WorkflowProgress, WorkflowNodeReplacement};
|
||||
|
||||
/// ComfyUI 集成服务
|
||||
/// 提供统一的接口,可以选择使用原生实现或 SDK 实现
|
||||
pub struct ComfyUIIntegrationService {
|
||||
legacy_service: Arc<ComfyUIService>,
|
||||
sdk_service: Option<Arc<ComfyUISDKService>>,
|
||||
use_sdk: bool,
|
||||
settings: ComfyUISettings,
|
||||
}
|
||||
|
||||
/// 集成服务配置
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IntegrationConfig {
|
||||
pub prefer_sdk: bool,
|
||||
pub fallback_to_legacy: bool,
|
||||
pub timeout: Duration,
|
||||
pub retry_attempts: u32,
|
||||
}
|
||||
|
||||
impl Default for IntegrationConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
prefer_sdk: true,
|
||||
fallback_to_legacy: true,
|
||||
timeout: Duration::from_secs(300),
|
||||
retry_attempts: 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 统一的工作流执行结果
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UnifiedWorkflowResult {
|
||||
pub prompt_id: String,
|
||||
pub outputs: HashMap<String, Vec<String>>,
|
||||
pub execution_time: Duration,
|
||||
pub node_outputs: HashMap<String, Value>,
|
||||
pub used_sdk: bool,
|
||||
}
|
||||
|
||||
impl ComfyUIIntegrationService {
|
||||
/// 创建新的集成服务实例
|
||||
pub async fn new(settings: ComfyUISettings, config: IntegrationConfig) -> Result<Self> {
|
||||
// 创建传统服务
|
||||
let legacy_service = Arc::new(ComfyUIService::new(settings.clone()).await?);
|
||||
|
||||
// 尝试创建 SDK 服务
|
||||
let sdk_service = if config.prefer_sdk {
|
||||
match ComfyUISDKService::new(settings.clone()) {
|
||||
Ok(service) => {
|
||||
info!("ComfyUI SDK 服务初始化成功");
|
||||
Some(Arc::new(service))
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("ComfyUI SDK 服务初始化失败: {}, 将使用传统服务", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let use_sdk = sdk_service.is_some() && config.prefer_sdk;
|
||||
|
||||
Ok(Self {
|
||||
legacy_service,
|
||||
sdk_service,
|
||||
use_sdk,
|
||||
settings,
|
||||
})
|
||||
}
|
||||
|
||||
/// 检查服务健康状态
|
||||
pub async fn check_health(&self) -> Result<bool> {
|
||||
if self.use_sdk {
|
||||
if let Some(sdk_service) = &self.sdk_service {
|
||||
match sdk_service.check_health().await {
|
||||
Ok(healthy) => return Ok(healthy),
|
||||
Err(e) => {
|
||||
warn!("SDK 健康检查失败,尝试传统服务: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 回退到传统服务
|
||||
self.legacy_service.check_health().await
|
||||
}
|
||||
|
||||
/// 执行工作流(统一接口)
|
||||
pub async fn execute_workflow(
|
||||
&self,
|
||||
workflow: Value,
|
||||
replacements: Vec<WorkflowNodeReplacement>,
|
||||
config: IntegrationConfig,
|
||||
) -> Result<UnifiedWorkflowResult> {
|
||||
// 应用节点替换
|
||||
let processed_workflow = self.apply_replacements(workflow, replacements)?;
|
||||
|
||||
// 优先使用 SDK
|
||||
if self.use_sdk {
|
||||
if let Some(sdk_service) = &self.sdk_service {
|
||||
match self.execute_with_sdk(sdk_service.clone(), processed_workflow.clone(), &config).await {
|
||||
Ok(result) => {
|
||||
info!("使用 SDK 成功执行工作流");
|
||||
return Ok(UnifiedWorkflowResult {
|
||||
prompt_id: result.prompt_id,
|
||||
outputs: result.outputs,
|
||||
execution_time: result.execution_time,
|
||||
node_outputs: result.node_outputs,
|
||||
used_sdk: true,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("SDK 执行失败: {}", e);
|
||||
if !config.fallback_to_legacy {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 回退到传统服务
|
||||
info!("使用传统服务执行工作流");
|
||||
let result = self.execute_with_legacy(processed_workflow, &config).await?;
|
||||
|
||||
Ok(UnifiedWorkflowResult {
|
||||
prompt_id: result.prompt_id,
|
||||
outputs: result.outputs,
|
||||
execution_time: result.execution_time,
|
||||
node_outputs: result.node_outputs,
|
||||
used_sdk: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// 使用 SDK 执行工作流
|
||||
async fn execute_with_sdk(
|
||||
&self,
|
||||
sdk_service: Arc<ComfyUISDKService>,
|
||||
workflow: Value,
|
||||
config: &IntegrationConfig,
|
||||
) -> Result<WorkflowExecutionResult> {
|
||||
let sdk_config = SDKExecutionConfig {
|
||||
timeout: config.timeout,
|
||||
retry_attempts: config.retry_attempts,
|
||||
progress_callback: None, // 可以根据需要添加进度回调
|
||||
};
|
||||
|
||||
sdk_service.execute_workflow(workflow, sdk_config).await
|
||||
}
|
||||
|
||||
/// 使用传统服务执行工作流
|
||||
async fn execute_with_legacy(
|
||||
&self,
|
||||
workflow: Value,
|
||||
config: &IntegrationConfig,
|
||||
) -> Result<LegacyWorkflowResult> {
|
||||
// 这里需要调用传统服务的执行方法
|
||||
// 由于原始的 ComfyUIService 可能没有统一的执行接口,我们需要适配
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
|
||||
// 提交工作流
|
||||
let prompt_id = self.legacy_service.submit_workflow(workflow).await?;
|
||||
|
||||
// 等待完成(这里需要根据实际的传统服务接口来实现)
|
||||
let outputs = self.legacy_service.wait_for_completion(&prompt_id, config.timeout).await?;
|
||||
|
||||
let execution_time = start_time.elapsed();
|
||||
|
||||
Ok(LegacyWorkflowResult {
|
||||
prompt_id,
|
||||
outputs,
|
||||
execution_time,
|
||||
node_outputs: HashMap::new(), // 传统服务可能不提供详细的节点输出
|
||||
})
|
||||
}
|
||||
|
||||
/// 应用节点替换
|
||||
fn apply_replacements(
|
||||
&self,
|
||||
mut workflow: Value,
|
||||
replacements: Vec<WorkflowNodeReplacement>,
|
||||
) -> Result<Value> {
|
||||
for replacement in replacements {
|
||||
if let Some(node) = workflow.get_mut(&replacement.node_id) {
|
||||
if let Some(inputs) = node.get_mut("inputs") {
|
||||
if let Some(inputs_obj) = inputs.as_object_mut() {
|
||||
inputs_obj.insert(replacement.field_name, replacement.new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(workflow)
|
||||
}
|
||||
|
||||
/// 获取队列状态
|
||||
pub async fn get_queue_status(&self) -> Result<QueueStatusInfo> {
|
||||
if self.use_sdk {
|
||||
if let Some(sdk_service) = &self.sdk_service {
|
||||
match sdk_service.get_queue_status().await {
|
||||
Ok(status) => {
|
||||
return Ok(QueueStatusInfo {
|
||||
running: status.running,
|
||||
pending: status.pending,
|
||||
from_sdk: true,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("SDK 获取队列状态失败: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 回退到传统服务
|
||||
let status = self.legacy_service.get_queue_status().await?;
|
||||
Ok(QueueStatusInfo {
|
||||
running: status.running,
|
||||
pending: status.pending,
|
||||
from_sdk: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// 取消工作流执行
|
||||
pub async fn cancel_workflow(&self, prompt_id: &str) -> Result<()> {
|
||||
if self.use_sdk {
|
||||
if let Some(sdk_service) = &self.sdk_service {
|
||||
if let Ok(_) = sdk_service.cancel_workflow(prompt_id).await {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 回退到传统服务
|
||||
self.legacy_service.cancel_workflow(prompt_id).await
|
||||
}
|
||||
|
||||
/// 切换到 SDK 模式
|
||||
pub async fn switch_to_sdk(&mut self) -> Result<()> {
|
||||
if self.sdk_service.is_none() {
|
||||
let sdk_service = ComfyUISDKService::new(self.settings.clone())?;
|
||||
self.sdk_service = Some(Arc::new(sdk_service));
|
||||
}
|
||||
self.use_sdk = true;
|
||||
info!("已切换到 SDK 模式");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 切换到传统模式
|
||||
pub fn switch_to_legacy(&mut self) {
|
||||
self.use_sdk = false;
|
||||
info!("已切换到传统模式");
|
||||
}
|
||||
|
||||
/// 获取当前使用的服务类型
|
||||
pub fn get_current_service_type(&self) -> &'static str {
|
||||
if self.use_sdk && self.sdk_service.is_some() {
|
||||
"SDK"
|
||||
} else {
|
||||
"Legacy"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 传统服务工作流结果
|
||||
#[derive(Debug)]
|
||||
struct LegacyWorkflowResult {
|
||||
prompt_id: String,
|
||||
outputs: HashMap<String, Vec<String>>,
|
||||
execution_time: Duration,
|
||||
node_outputs: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
/// 队列状态信息
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct QueueStatusInfo {
|
||||
pub running: usize,
|
||||
pub pending: usize,
|
||||
pub from_sdk: bool,
|
||||
}
|
||||
|
||||
// 为了编译通过,我们需要为传统服务添加一些方法的扩展
|
||||
// 这些方法需要在实际的 ComfyUIService 中实现
|
||||
impl ComfyUIService {
|
||||
/// 提交工作流(需要在实际服务中实现)
|
||||
pub async fn submit_workflow(&self, _workflow: Value) -> Result<String> {
|
||||
// 这里需要调用实际的提交方法
|
||||
todo!("需要在 ComfyUIService 中实现 submit_workflow 方法")
|
||||
}
|
||||
|
||||
/// 等待完成(需要在实际服务中实现)
|
||||
pub async fn wait_for_completion(&self, _prompt_id: &str, _timeout: Duration) -> Result<HashMap<String, Vec<String>>> {
|
||||
// 这里需要调用实际的等待方法
|
||||
todo!("需要在 ComfyUIService 中实现 wait_for_completion 方法")
|
||||
}
|
||||
|
||||
/// 获取队列状态(需要在实际服务中实现)
|
||||
pub async fn get_queue_status(&self) -> Result<QueueStatusInfo> {
|
||||
// 这里需要调用实际的队列状态方法
|
||||
todo!("需要在 ComfyUIService 中实现 get_queue_status 方法")
|
||||
}
|
||||
|
||||
/// 取消工作流(需要在实际服务中实现)
|
||||
pub async fn cancel_workflow(&self, _prompt_id: &str) -> Result<()> {
|
||||
// 这里需要调用实际的取消方法
|
||||
todo!("需要在 ComfyUIService 中实现 cancel_workflow 方法")
|
||||
}
|
||||
|
||||
/// 检查健康状态(需要在实际服务中实现)
|
||||
pub async fn check_health(&self) -> Result<bool> {
|
||||
// 这里需要调用实际的健康检查方法
|
||||
todo!("需要在 ComfyUIService 中实现 check_health 方法")
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,8 @@ pub mod jianying_export;
|
|||
pub mod template_segment_weight_service;
|
||||
pub mod directory_settings_service;
|
||||
pub mod comfyui_service;
|
||||
pub mod comfyui_sdk_service;
|
||||
pub mod comfyui_integration_service;
|
||||
pub mod outfit_photo_generation_service;
|
||||
pub mod workflow_management_service;
|
||||
pub mod error_handling_service;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,26 @@ pub struct ComfyUISettings {
|
|||
pub workflow_directory: Option<String>,
|
||||
/// 输出文件存储目录
|
||||
pub output_directory: Option<String>,
|
||||
/// SDK 配置
|
||||
pub sdk_config: ComfyUISDKConfig,
|
||||
}
|
||||
|
||||
/// ComfyUI SDK 配置
|
||||
/// 控制 SDK 的使用和行为
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ComfyUISDKConfig {
|
||||
/// 是否优先使用 SDK
|
||||
pub prefer_sdk: bool,
|
||||
/// 当 SDK 失败时是否回退到传统实现
|
||||
pub fallback_to_legacy: bool,
|
||||
/// SDK 执行超时时间(秒)
|
||||
pub sdk_timeout_seconds: u64,
|
||||
/// SDK 重试次数
|
||||
pub sdk_retry_attempts: u32,
|
||||
/// 是否启用详细日志
|
||||
pub enable_verbose_logging: bool,
|
||||
/// 是否启用进度回调
|
||||
pub enable_progress_callback: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
@ -72,6 +92,19 @@ impl Default for DirectorySettings {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for ComfyUISDKConfig {
|
||||
fn default() -> Self {
|
||||
ComfyUISDKConfig {
|
||||
prefer_sdk: true,
|
||||
fallback_to_legacy: true,
|
||||
sdk_timeout_seconds: 300,
|
||||
sdk_retry_attempts: 3,
|
||||
enable_verbose_logging: false,
|
||||
enable_progress_callback: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ComfyUISettings {
|
||||
fn default() -> Self {
|
||||
ComfyUISettings {
|
||||
|
|
@ -82,10 +115,28 @@ impl Default for ComfyUISettings {
|
|||
enabled: false,
|
||||
workflow_directory: None,
|
||||
output_directory: None,
|
||||
sdk_config: ComfyUISDKConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComfyUISettings {
|
||||
/// 获取完整的 ComfyUI 服务 URL
|
||||
pub fn base_url(&self) -> String {
|
||||
format!("http://{}:{}", self.server_address, self.server_port)
|
||||
}
|
||||
|
||||
/// 检查是否启用了 SDK
|
||||
pub fn is_sdk_enabled(&self) -> bool {
|
||||
self.enabled && self.sdk_config.prefer_sdk
|
||||
}
|
||||
|
||||
/// 获取 SDK 超时时间
|
||||
pub fn get_sdk_timeout(&self) -> std::time::Duration {
|
||||
std::time::Duration::from_secs(self.sdk_config.sdk_timeout_seconds)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
fn default() -> Self {
|
||||
AppConfig {
|
||||
|
|
|
|||
Loading…
Reference in New Issue