enqueue hunyuan3d v3 from tauri

This commit is contained in:
Brandon Thomas committed 2026-01-19 04:18:24 -05:00
1 parent 6f35e2f097
commit ca48e01565
10 files changed
+58 -7

No files matched your search

@@ -17,6 +17,8 @@ use log::{error, info};
use storyteller_client::endpoints::generate::object::generate_hunyuan_3d_2_0_image_to_3d::generate_hunyuan3d_2_0_image_to_3d;
use storyteller_client::endpoints::generate::object::generate_hunyuan_3d_2_1_image_to_3d::generate_hunyuan3d_2_1_image_to_3d;
use tauri::AppHandle;
use artcraft_api_defs::generate::object::multi_function::hunyuan3d_v3_multi_function_object_gen::Hunyuan3dV3MultiFunctionObjectGenRequest;
use storyteller_client::endpoints::generate::object::multi_function::hunyuan3d_v3_multi_function_object_gen::hunyuan3d_v3_multi_function_object_gen;
pub async fn handle_artcraft_object(
request: &EnqueueImageTo3dObjectRequest,
@@ -100,6 +102,37 @@ pub async fn handle_artcraft_object(
}
}
}
Some(EnqueueImageTo3dObjectModel::Hunyuan3d3) => {
info!("enqueue Artcraft Hunyuan 3D 3");
used_model = Some(GenerationModel::Hunyuan3d3);
let request = Hunyuan3dV3MultiFunctionObjectGenRequest {
uuid_idempotency_token,
image_media_token: request.image_media_token.clone(),
prompt: None,
back_image_media_token: None,
left_image_media_token: None,
right_image_media_token: None,
face_count: None,
generate_type: None,
polygon_type: None,
enable_pbr: None,
};
let result = hunyuan3d_v3_multi_function_object_gen(
&app_env_configs.storyteller_host,
Some(&creds),
request,
).await;
match result {
Ok(enqueued) => {
info!("Successfully enqueued Artcraft Hunyuan 3D 3");
enqueued.inference_job_token
}
Err(err) => {
error!("Failed to use Artcraft Hunyuan 3D 3: {:?}", err);
return Err(GenerateError::from(err));
}
}
}
};
info!("Successfully enqueued 3D generation");
@@ -55,6 +55,8 @@ pub enum EnqueueImageTo3dObjectModel {
Hunyuan3d2_0,
#[serde(rename = "hunyuan_3d_2_1")]
Hunyuan3d2_1,
#[serde(rename = "hunyuan_3d_3")]
Hunyuan3d3,
}
#[derive(Serialize)]
@@ -91,6 +91,7 @@ impl TaskEnqueueSuccess{
Some(GenerationModel::Veo3Fast) => Some(TaskModelType::Veo3Fast),
Some(GenerationModel::Hunyuan3d2_0) => Some(TaskModelType::Hunyuan3d2_0),
Some(GenerationModel::Hunyuan3d2_1) => Some(TaskModelType::Hunyuan3d2_1),
Some(GenerationModel::Hunyuan3d3) => Some(TaskModelType::Hunyuan3d3),
Some(GenerationModel::WorldlabsMarble) => Some(TaskModelType::WorldlabsMarble),
Some(GenerationModel::Midjourney) => Some(TaskModelType::Midjourney), // NB: This is a generic Midjourney model, version unknown.
@@ -50,6 +50,8 @@ pub enum GenerationModel {
Hunyuan3d2_0,
#[serde(rename = "hunyuan_3d_2_1")]
Hunyuan3d2_1,
#[serde(rename = "hunyuan_3d_3")]
Hunyuan3d3,
#[serde(rename = "worldlabs_marble")]
WorldlabsMarble,
@@ -85,6 +85,8 @@ pub enum TaskModelType {
Hunyuan3d2_0,
#[serde(rename = "hunyuan_3d_2.1")]
Hunyuan3d2_1,
#[serde(rename = "hunyuan_3d_3")]
Hunyuan3d3,
#[serde(rename = "worldlabs_marble")]
WorldlabsMarble,
}
@@ -134,6 +136,7 @@ impl TaskModelType {
// 3D Object generation models
Self::Hunyuan3d2_0 => "hunyuan_3d_2.0",
Self::Hunyuan3d2_1 => "hunyuan_3d_2.1",
Self::Hunyuan3d3 => "hunyuan_3d_3",
Self::WorldlabsMarble => "worldlabs_marble",
}
}
@@ -176,6 +179,7 @@ impl TaskModelType {
// 3D Object generation models
"hunyuan_3d_2.0" => Ok(Self::Hunyuan3d2_0),
"hunyuan_3d_2.1" => Ok(Self::Hunyuan3d2_1),
"hunyuan_3d_3" => Ok(Self::Hunyuan3d3),
"worldlabs_marble" => Ok(Self::WorldlabsMarble),
_ => Err(EnumError::CouldNotConvertFromString(value.to_string())),
}
@@ -221,6 +225,7 @@ impl TaskModelType {
// 3D Object generation models
Self::Hunyuan3d2_0,
Self::Hunyuan3d2_1,
Self::Hunyuan3d3,
Self::WorldlabsMarble,
])
}
@@ -273,6 +278,7 @@ mod tests {
// 3D Object generation models
assert_serialization(TaskModelType::Hunyuan3d2_0, "hunyuan_3d_2.0");
assert_serialization(TaskModelType::Hunyuan3d2_1, "hunyuan_3d_2.1");
assert_serialization(TaskModelType::Hunyuan3d3, "hunyuan_3d_3");
assert_serialization(TaskModelType::WorldlabsMarble, "worldlabs_marble");
}
@@ -314,6 +320,7 @@ mod tests {
// 3D Object generation models
assert_eq!(TaskModelType::Hunyuan3d2_0.to_str(), "hunyuan_3d_2.0");
assert_eq!(TaskModelType::Hunyuan3d2_1.to_str(), "hunyuan_3d_2.1");
assert_eq!(TaskModelType::Hunyuan3d3.to_str(), "hunyuan_3d_3");
assert_eq!(TaskModelType::WorldlabsMarble.to_str(), "worldlabs_marble");
}
@@ -355,6 +362,7 @@ mod tests {
// 3D Object generation models
assert_eq!(TaskModelType::from_str("hunyuan_3d_2.0").unwrap(), TaskModelType::Hunyuan3d2_0);
assert_eq!(TaskModelType::from_str("hunyuan_3d_2.1").unwrap(), TaskModelType::Hunyuan3d2_1);
assert_eq!(TaskModelType::from_str("hunyuan_3d_3").unwrap(), TaskModelType::Hunyuan3d3);
assert_eq!(TaskModelType::from_str("worldlabs_marble").unwrap(), TaskModelType::WorldlabsMarble);
}
@@ -372,7 +380,7 @@ mod tests {
#[test]
fn all_variants() {
let mut variants = TaskModelType::all_variants();
assert_eq!(variants.len(), 34);
assert_eq!(variants.len(), 35);
// Image models
assert_eq!(variants.pop_first(), Some(TaskModelType::Flux1Dev));
assert_eq!(variants.pop_first(), Some(TaskModelType::Flux1Schnell));
@@ -409,6 +417,7 @@ mod tests {
// 3D Object generation models
assert_eq!(variants.pop_first(), Some(TaskModelType::Hunyuan3d2_0));
assert_eq!(variants.pop_first(), Some(TaskModelType::Hunyuan3d2_1));
assert_eq!(variants.pop_first(), Some(TaskModelType::Hunyuan3d3));
assert_eq!(variants.pop_first(), Some(TaskModelType::WorldlabsMarble));
assert_eq!(variants.pop_first(), None);
}
@@ -152,6 +152,9 @@ pub async fn generate_hunyuan3d_v3_multi_function_object_handler(
.unwrap_or(false);
let has_image = image_url.is_some();
// Defaults
let enable_pbr = request.enable_pbr.unwrap_or(true);
let fal_result = match (has_prompt, has_image) {
// Text-to-3D: prompt only, no image
@@ -176,7 +179,7 @@ pub async fn generate_hunyuan3d_v3_multi_function_object_handler(
face_count: request.face_count,
generate_type,
polygon_type,
enable_pbr: request.enable_pbr,
enable_pbr: Some(enable_pbr),
webhook_url: &server_state.fal.webhook_url,
api_key: &server_state.fal.api_key,
};
@@ -215,7 +218,7 @@ pub async fn generate_hunyuan3d_v3_multi_function_object_handler(
face_count: request.face_count,
generate_type,
polygon_type,
enable_pbr: request.enable_pbr,
enable_pbr: Some(enable_pbr),
webhook_url: &server_state.fal.webhook_url,
api_key: &server_state.fal.api_key,
};
@@ -256,7 +259,7 @@ pub async fn generate_hunyuan3d_v3_multi_function_object_handler(
face_count: request.face_count,
generate_type,
polygon_type,
enable_pbr: request.enable_pbr,
enable_pbr: Some(enable_pbr),
webhook_url: &server_state.fal.webhook_url,
api_key: &server_state.fal.api_key,
};
@@ -252,7 +252,7 @@ export const ImageTo3DExperience = ({
variant === "object"
? await EnqueueImageTo3dObject({
image_media_token: uploadedMediaToken || undefined,
model: EnqueueImageTo3dObjectModel.Hunyuan3d2,
model: EnqueueImageTo3dObjectModel.Hunyuan3d3,
frontend_caller: "mini_app",
frontend_subscriber_id: subscriberId,
})
@@ -183,7 +183,7 @@ export const Create3dModal = ({ onModelComplete }: Create3dModalProps = {}) => {
// Enqueue the image for 3D model creation using the Hunyuan 3D 2 model
const result = await EnqueueImageTo3dObject({
image_media_token: mediaToken,
model: EnqueueImageTo3dObjectModel.Hunyuan3d2,
model: EnqueueImageTo3dObjectModel.Hunyuan3d3,
frontend_caller: "mini_app",
});
@@ -735,7 +735,7 @@ export function LightboxModal({
gtagEvent("image_to_3d_clicked");
await EnqueueImageTo3dObject({
image_media_token: selectedMediaToken,
model: EnqueueImageTo3dObjectModel.Hunyuan3d2_0,
model: EnqueueImageTo3dObjectModel.Hunyuan3d3,
frontend_caller: "mini_app",
});
}}
@@ -36,6 +36,7 @@ export enum EnqueueImageTo3dObjectModel {
Hunyuan3d2 = "hunyuan_3d_2",
Hunyuan3d2_0 = "hunyuan_3d_2_0",
Hunyuan3d2_1 = "hunyuan_3d_2_1",
Hunyuan3d3 = "hunyuan_3d_3",
}
export interface EnqueueImageTo3dObjectError extends CommandResult {