fix: sdk
This commit is contained in:
@@ -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 template_segment_weight_service;
|
||||||
pub mod directory_settings_service;
|
pub mod directory_settings_service;
|
||||||
pub mod comfyui_service;
|
pub mod comfyui_service;
|
||||||
|
pub mod comfyui_sdk_service;
|
||||||
|
pub mod comfyui_integration_service;
|
||||||
pub mod outfit_photo_generation_service;
|
pub mod outfit_photo_generation_service;
|
||||||
pub mod workflow_management_service;
|
pub mod workflow_management_service;
|
||||||
pub mod error_handling_service;
|
pub mod error_handling_service;
|
||||||
|
|||||||
@@ -51,6 +51,26 @@ pub struct ComfyUISettings {
|
|||||||
pub workflow_directory: Option<String>,
|
pub workflow_directory: Option<String>,
|
||||||
/// 输出文件存储目录
|
/// 输出文件存储目录
|
||||||
pub output_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)]
|
#[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 {
|
impl Default for ComfyUISettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ComfyUISettings {
|
ComfyUISettings {
|
||||||
@@ -82,10 +115,28 @@ impl Default for ComfyUISettings {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
workflow_directory: None,
|
workflow_directory: None,
|
||||||
output_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 {
|
impl Default for AppConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
AppConfig {
|
AppConfig {
|
||||||
|
|||||||
Reference in New Issue
Block a user