图生 3D 的资源派生来源改为取自请求的 source
- job.rs 新增 Model3dJobRequest::source_resource_id():resource 来源带出画布资源 id,素材库来源与文生 3D 没有可登记的来源资源 - worker.rs 落库时资源行与素材行都改用它:资源行记派生来源,素材行优先指向本项目的资源行、只落素材库时退回请求里的来源资源 - 新增单测钉住三种来源(resource / asset / 文生)的取值,不再拿本次新生成的输出资源 id 冒充来源
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
use serde_json::Value;
|
||||
use shared_contracts::editor_canvas::EditorCanvasGenerationCompletionPayload as EditorCanvasGenerationCompletionRequest;
|
||||
use shared_contracts::model3d::common::Model3dGenerationSource;
|
||||
use shared_contracts::model3d::image_to_model::Model3dImageToModelRequest;
|
||||
use shared_contracts::model3d::text_to_model::Model3dTextToModelRequest;
|
||||
|
||||
@@ -85,6 +86,21 @@ impl Model3dJobRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/// 本次生成派生自哪个画布资源;素材库对象与文生 3D 没有可登记的来源资源。
|
||||
///
|
||||
/// 资源 / 素材记录的 `source_resource_id` 记的是「派生来源」,所以只能从请求的
|
||||
/// `source` 取:本次新生成的输出资源 id 是产物自己,写进去等于自证来源。
|
||||
pub(crate) fn source_resource_id(&self) -> Option<String> {
|
||||
match self {
|
||||
Self::TextToModel(_) => None,
|
||||
Self::ImageToModel(request) => match &request.source {
|
||||
Model3dGenerationSource::Resource { resource_id } => Some(resource_id.clone()),
|
||||
// 素材库对象没有画布资源 id,没有可登记的来源资源。
|
||||
Model3dGenerationSource::Asset { .. } => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// 审计与落库用的模型版本线上取值;取值只由契约枚举的 serde rename 定义。
|
||||
///
|
||||
/// 该值会持久化进资源 / 素材记录的 `model` 字段,因此走严格的
|
||||
@@ -340,6 +356,61 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// 派生来源只认请求里的 `source`:图生 3D 的 resource 变体带出资源 id,
|
||||
/// 素材库来源与文生 3D 都没有可登记的来源资源。
|
||||
#[test]
|
||||
fn source_resource_id_comes_from_the_request_source_only() {
|
||||
let image_request = |source: Value| {
|
||||
Model3dJobRequest::ImageToModel(
|
||||
serde_json::from_value(json!({
|
||||
"source": source,
|
||||
"generation": {
|
||||
"model": "v3.1-20260211",
|
||||
"texture": true,
|
||||
"pbr": true,
|
||||
"textureQuality": "standard",
|
||||
"geometryQuality": "standard",
|
||||
"quad": false,
|
||||
"smartLowPoly": false,
|
||||
"generateParts": false
|
||||
},
|
||||
"projectId": "project-1"
|
||||
}))
|
||||
.expect("测试请求应可反序列化"),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
image_request(json!({ "kind": "resource", "resourceId": "resource-source" }))
|
||||
.source_resource_id()
|
||||
.as_deref(),
|
||||
Some("resource-source")
|
||||
);
|
||||
assert_eq!(
|
||||
image_request(json!({ "kind": "asset", "assetId": "asset-1" })).source_resource_id(),
|
||||
None
|
||||
);
|
||||
|
||||
let text = Model3dJobRequest::TextToModel(
|
||||
serde_json::from_value(json!({
|
||||
"generation": {
|
||||
"prompt": "一只木箱",
|
||||
"model": "v3.1-20260211",
|
||||
"texture": true,
|
||||
"pbr": true,
|
||||
"textureQuality": "standard",
|
||||
"geometryQuality": "standard",
|
||||
"quad": false,
|
||||
"smartLowPoly": false,
|
||||
"generateParts": false
|
||||
},
|
||||
"projectId": "project-1"
|
||||
}))
|
||||
.expect("测试请求应可反序列化"),
|
||||
);
|
||||
assert_eq!(text.source_resource_id(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn job_request_is_parsed_after_stripping_platform_fingerprint() {
|
||||
let payload = json!({
|
||||
|
||||
@@ -298,6 +298,9 @@ async fn persist_result(
|
||||
);
|
||||
let has_resource = project_id.is_some();
|
||||
let has_asset = folder_id.is_some();
|
||||
// 派生来源只来自请求:资源 / 素材记录的 `source_resource_id` 记的是「从哪个画布资源
|
||||
// 派生出来的」,与本次新生成的输出资源 id 无关(图生 3D 的 source,文生 3D 没有)。
|
||||
let source_resource_id = request.source_resource_id();
|
||||
let project_resource = project_id.map(|project_id| EditorProjectResourceCreateRecordInput {
|
||||
resource_id: resource_id.clone(),
|
||||
project_id,
|
||||
@@ -314,7 +317,7 @@ async fn persist_result(
|
||||
provider: Some(MODEL3D_PROVIDER_KIND.to_string()),
|
||||
// 平台自己的 operation ID;provider task ID 只留在 checkpoint,不落业务行。
|
||||
task_id: Some(job.job_id.clone()),
|
||||
source_resource_id: None,
|
||||
source_resource_id: source_resource_id.clone(),
|
||||
asset_kind: Some(MODEL3D_ASSET_KIND.to_string()),
|
||||
generation_inputs_json: None,
|
||||
updated_at_micros: completed_at_micros,
|
||||
@@ -340,7 +343,11 @@ async fn persist_result(
|
||||
task_id: Some(job.job_id.clone()),
|
||||
asset_kind: Some(MODEL3D_ASSET_KIND.to_string()),
|
||||
generation_inputs_json: None,
|
||||
source_resource_id: has_resource.then(|| resource_id.clone()),
|
||||
// 素材行与画布资源行是同一份产物的两种落点:有本项目的资源行时指向它(与其它
|
||||
// 生成工具一致),只落素材库时退回请求里的来源资源,不把溯源信息丢掉。
|
||||
source_resource_id: has_resource
|
||||
.then(|| resource_id.clone())
|
||||
.or_else(|| source_resource_id.clone()),
|
||||
generation_cost_mud_points: job.price_mud_points,
|
||||
now_micros: completed_at_micros,
|
||||
thumbnail_src: Some(preview_src.clone()),
|
||||
|
||||
Reference in New Issue
Block a user