mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-10 20:11:49 +00:00
update
This commit is contained in:
commit
e741951630
164 files changed
+5753
-238
No files matched your search
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO model_weights_extension_tts_details\nSET\n model_weights_token = ?,\n ietf_language_tag = ?,\n ietf_primary_language_subtag = ?,\n text_pipeline_type = ?,\n use_default_mel_multiply_factor = ?,\n maybe_custom_mel_multiply_factor = ?,\n maybe_default_pretrained_vocoder = ?,\n maybe_custom_vocoder_token = ?\nON DUPLICATE KEY UPDATE\n ietf_language_tag = ?,\n ietf_primary_language_subtag = ?,\n text_pipeline_type = ?,\n use_default_mel_multiply_factor = ?,\n maybe_custom_mel_multiply_factor = ?,\n maybe_default_pretrained_vocoder = ?,\n maybe_custom_vocoder_token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 15
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "1ce9219b8f05fe54adaa6841acb708e165e1c7855b441b9623a2151197578929"
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n w.token as `token: tokens::tokens::model_weights::ModelWeightToken`,\n w.weights_type as `weight_type: enums::by_table::model_weights::weights_types::WeightsType`,\n w.title,\n w.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,\n users.username as creator_username,\n users.display_name as creator_display_name,\n users.email_gravatar_hash as creator_gravatar_hash,\n w_extension.ietf_language_tag,\n w_extension.ietf_primary_language_subtag,\n w.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n w.created_at,\n w.updated_at\nFROM model_weights as w\nLEFT OUTER JOIN model_weights_extension_tts_details as w_extension\n ON w_extension.model_weights_token = w.token\nJOIN users\n ON users.token = w.creator_user_token\nWHERE\n w.weights_type IN (\"tt2\")\n AND w.user_deleted_at IS NULL\n AND w.mod_deleted_at IS NULL\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "token: tokens::tokens::model_weights::ModelWeightToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "weight_type: enums::by_table::model_weights::weights_types::WeightsType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "creator_user_token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "creator_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "creator_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "creator_gravatar_hash",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "ietf_language_tag",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 256
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "ietf_primary_language_subtag",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 48
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "creator_set_visibility: enums::common::visibility::Visibility",
|
||||
"type_info": {
|
||||
"type": "String",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | ENUM",
|
||||
"char_set": 224,
|
||||
"max_size": 28
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 0
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "4d45f5ce213627465e991eaec9b509100e22c614367b67ab026b5edd70927ea5"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nUPDATE tts_models\nSET\n maybe_migration_new_model_weights_token = ?\nWHERE token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "aa7ec1c1e32f773212b264f34173f99db1e515e370c47065f932aaec56f89112"
|
||||
}
|
||||
Generated
+23
@@ -1259,6 +1259,24 @@ dependencies = [
|
||||
"my-workspace-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "composite_identifiers"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"enums",
|
||||
"my-workspace-hack",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"sqlx-core",
|
||||
"sqlx-mysql",
|
||||
"strum",
|
||||
"tokens",
|
||||
"toml 0.5.11",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrency"
|
||||
version = "0.0.1"
|
||||
@@ -3052,6 +3070,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"cloud_storage",
|
||||
"collections",
|
||||
"composite_identifiers",
|
||||
"concurrency",
|
||||
"config",
|
||||
"dotenv",
|
||||
@@ -3059,6 +3078,7 @@ dependencies = [
|
||||
"enums",
|
||||
"errors",
|
||||
"filesys",
|
||||
"google_drive_common",
|
||||
"hashing",
|
||||
"hostname",
|
||||
"hyper",
|
||||
@@ -3857,6 +3877,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"buckets",
|
||||
"chrono",
|
||||
"composite_identifiers",
|
||||
"config",
|
||||
"container_common",
|
||||
"dotenv",
|
||||
@@ -6006,6 +6027,7 @@ dependencies = [
|
||||
"buckets",
|
||||
"chrono",
|
||||
"cloud_storage",
|
||||
"composite_identifiers",
|
||||
"config",
|
||||
"container_common",
|
||||
"cookies",
|
||||
@@ -6068,6 +6090,7 @@ dependencies = [
|
||||
"sha2 0.9.9",
|
||||
"speculoos",
|
||||
"sqlx",
|
||||
"strum",
|
||||
"symphonia",
|
||||
"time 0.3.30",
|
||||
"tokens",
|
||||
|
||||
@@ -5,6 +5,7 @@ members = [
|
||||
# Types: common strongly-typed tokens, ids, payloads, etc.
|
||||
# Also common cloud buckets and other "strongly typed" configs.
|
||||
"crates/_types/buckets",
|
||||
"crates/_types/composite_identifiers",
|
||||
"crates/_types/enums",
|
||||
"crates/_types/reusable_types", # TODO(bt, 2022-12-21): Deprecate
|
||||
"crates/_types/tokens",
|
||||
|
||||
@@ -2,6 +2,20 @@
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
|
||||
-- Find jobs that are broken for a given user
|
||||
select id, last_assigned_worker, internal_debugging_failure_reason,created_at
|
||||
from tts_inference_jobs
|
||||
where maybe_creator_user_token IN (
|
||||
select token
|
||||
from users
|
||||
where username IN ('knifecat ', 'rewritten_code', 'johnloberger')
|
||||
)
|
||||
and attempt_count > 1
|
||||
and status IN ('complete_failure', 'dead', 'attempt_failed')
|
||||
and created_at > ( CURDATE() - INTERVAL 5 DAY );
|
||||
|
||||
|
||||
-- Total pending jobs
|
||||
select count(*)
|
||||
from tts_inference_jobs
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE model_weights_extension_tts_details DROP COLUMN text_pipeline_type;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE model_weights_extension_tts_details
|
||||
ADD COLUMN text_pipeline_type VARCHAR(64) DEFAULT NULL
|
||||
AFTER ietf_primary_language_subtag;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
drop table idempotency_tokens;
|
||||
@@ -0,0 +1,19 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- A form of optimistic locking
|
||||
CREATE TABLE idempotency_tokens (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- This can be a UUID or any entropic value.
|
||||
idempotency_value VARCHAR(36) NOT NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (idempotency_value)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
drop table batch_generations;
|
||||
@@ -0,0 +1,42 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Batch generations
|
||||
CREATE TABLE batch_generations (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- The batch token
|
||||
-- This is **NOT** a unique token.
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== ENTITY LINKAGE ==========
|
||||
|
||||
-- The type of record this is attached to
|
||||
-- Currently supported values:
|
||||
-- * 'model_weight'
|
||||
-- * 'media_file'
|
||||
-- * 'comment'
|
||||
entity_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The token for the record.
|
||||
entity_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token, entity_type, entity_token),
|
||||
KEY index_token (token),
|
||||
KEY index_entity_token (entity_token)
|
||||
|
||||
-- NB: Realistically, we probably don't need this index until we have a lot of entity types, and the entity_token
|
||||
-- entropy is probably sufficient enough as-is.
|
||||
-- KEY index_entity_type_and_token (entity_type, entity_token),
|
||||
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files DROP COLUMN is_batch_generated;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN is_batch_generated BOOLEAN NOT NULL DEFAULT FALSE
|
||||
AFTER maybe_origin_filename;
|
||||
@@ -0,0 +1,42 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- Batch generations
|
||||
CREATE TABLE batch_generations (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- The batch token
|
||||
-- This is **NOT** a unique token.
|
||||
token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== ENTITY LINKAGE ==========
|
||||
|
||||
-- The type of record this is attached to
|
||||
-- Currently supported values:
|
||||
-- * 'model_weight'
|
||||
-- * 'media_file'
|
||||
-- * 'comment'
|
||||
entity_type VARCHAR(32) NOT NULL,
|
||||
|
||||
-- The token for the record.
|
||||
entity_token VARCHAR(32) NOT NULL,
|
||||
|
||||
-- ========== TIMESTAMPS ==========
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (token, entity_type, entity_token),
|
||||
KEY index_token (token),
|
||||
KEY index_entity_token (entity_token)
|
||||
|
||||
-- NB: Realistically, we probably don't need this index until we have a lot of entity types, and the entity_token
|
||||
-- entropy is probably sufficient enough as-is.
|
||||
-- KEY index_entity_type_and_token (entity_type, entity_token),
|
||||
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -0,0 +1,19 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
-- A form of optimistic locking
|
||||
CREATE TABLE idempotency_tokens (
|
||||
-- Not used for anything except replication.
|
||||
id BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
-- This can be a UUID or any entropic value.
|
||||
idempotency_value VARCHAR(36) NOT NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- INDICES --
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (idempotency_value)
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
@@ -26,7 +26,7 @@ CREATE TABLE media_files (
|
||||
-- * 'device_api' for direct user uploads recorded using Browser/Device APIs.
|
||||
origin_category VARCHAR(16) NOT NULL,
|
||||
|
||||
-- TODO: Remove default value once records backfilled and queries updated.
|
||||
-- TODO(bt,2024-01-12): Rename to origin_product.
|
||||
-- Product area where the media file originated.
|
||||
-- This is not the *model* that created the thing, this is the *product*.
|
||||
-- (The underlying models can change over time.)
|
||||
@@ -37,8 +37,13 @@ CREATE TABLE media_files (
|
||||
-- "Voice Designer" dataset samples in a video generation flow.)
|
||||
--
|
||||
-- Possible values:
|
||||
-- * 'unknown' for legacy records without an associated product
|
||||
-- * 'face_animator' for uploads and outputs
|
||||
-- * 'unknown' for legacy records without an associated product (TODO: This should be temporary)
|
||||
-- * 'tts' for text to speech outputs
|
||||
-- * 'voice_conversion' for uploads or outputs (RVC or SVC)
|
||||
-- * 'zs_voice' for uploads or outputs for zero shot voice products
|
||||
-- * 'video_filter' filters on videos
|
||||
-- * 'mocap' for files uploaded or processed by motion capture
|
||||
origin_product_category VARCHAR(16) NOT NULL DEFAULT "unknown",
|
||||
|
||||
-- For inference that can be tied back to a model, the type of model.
|
||||
@@ -53,6 +58,11 @@ CREATE TABLE media_files (
|
||||
-- The original filename of the media (if uploaded by a user)
|
||||
maybe_origin_filename VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- Whether this media file was generated as part of a batch
|
||||
-- If so, we can look up the batch in a separate query/call to the `batch_generations` table.
|
||||
-- We won't hold the batch token in this table since it'll be very sparsely populated.
|
||||
is_batch_generated BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- ========== METADATA ==========
|
||||
|
||||
-- We can store text transcripts, etc. in other tables and refer back via foreign key.
|
||||
|
||||
@@ -28,7 +28,7 @@ CREATE TABLE model_weights_extension_tts_details (
|
||||
-- live in the `storyteller-ml` repository.
|
||||
-- Older models and brand new models will have this field set to null, and we'll infer which value to
|
||||
-- lazily backfill based on the creation date and language setting.
|
||||
-- tts_text_pipeline_type VARCHAR(64) DEFAULT NULL,
|
||||
text_pipeline_type VARCHAR(64) DEFAULT NULL,
|
||||
|
||||
-- If true, multiply the mel outputs before being vocoded by a globally default constant.
|
||||
use_default_mel_multiply_factor BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
@@ -26,12 +26,14 @@ impl ModelCategory {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ModelType {
|
||||
VallEx,
|
||||
StyleTTS2,
|
||||
}
|
||||
|
||||
impl ModelType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
ModelType::VallEx => "vallex",
|
||||
ModelType::StyleTTS2 => "styletts2",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ impl PublicPath for WeightFileBucketPath {}
|
||||
|
||||
impl WeightFileBucketPath {
|
||||
|
||||
// TODO(bt,2024-01-14): This is temporary standardization. Clean this up.
|
||||
pub fn generate_for_tt2_model() -> Self {
|
||||
Self::generate_new(Some("tt2_"), Some(".pt"))
|
||||
}
|
||||
|
||||
// TODO(bt,2023-12-19): This is temporary standardization. Clean this up.
|
||||
pub fn generate_for_svc_model() -> Self {
|
||||
Self::generate_new(Some("svc_"), Some(".pt"))
|
||||
@@ -35,6 +40,11 @@ impl WeightFileBucketPath {
|
||||
Self::generate_new(Some("rvc_"), Some(".pt"))
|
||||
}
|
||||
|
||||
// TODO(bt,2024-01-15): This is temporary standardization. Clean this up.
|
||||
pub fn tt2_model_file_from_object_hash(hash: &str) -> Self {
|
||||
Self::from_object_hash(hash, Some("tt2_"), Some(".pt"))
|
||||
}
|
||||
|
||||
// TODO(bt,2023-12-19): This is temporary standardization. Clean this up.
|
||||
pub fn svc_model_file_from_object_hash(hash: &str) -> Self {
|
||||
Self::from_object_hash(hash, Some("svc_"), Some(".pt"))
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
[package]
|
||||
name = "composite_identifiers"
|
||||
edition = "2018"
|
||||
version = "0.0.1"
|
||||
authors = [
|
||||
"Brandon Thomas <bt@brand.io>",
|
||||
"Brandon Thomas <echelon@gmail.com>",
|
||||
]
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "composite_identifiers"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
enums = { path = "../enums" }
|
||||
tokens = { path = "../tokens" }
|
||||
|
||||
# Workspace hack (faster compile times)
|
||||
my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }
|
||||
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
|
||||
sqlx = { version = "0.7.2", features = [ "mysql", "sqlite", "runtime-tokio-native-tls", "chrono" ] }
|
||||
sqlx-core = { version = "0.7.2" }
|
||||
sqlx-mysql= { version = "0.7.2" }
|
||||
|
||||
utoipa = { version = "4", features = ["chrono","actix_extras"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
# Enum utilities
|
||||
strum = { version = "0.25", features = ["derive"] }
|
||||
|
||||
# Test serialization
|
||||
serde_json = "1.0.108"
|
||||
toml = "0.5.8"
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
use enums::by_table::batch_generations::batch_generation_entity_type::BatchGenerationEntityType;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
// TODO(bt, 2024-01-16): A ref type with <'a> lifetime of inner data instead of ownership?
|
||||
pub enum BatchGenerationEntity {
|
||||
MediaFile(MediaFileToken),
|
||||
}
|
||||
|
||||
// TODO(bt, 2024-01-16): Codegen? Make traits for these? Maybe overkill.
|
||||
impl BatchGenerationEntity {
|
||||
pub fn get_entity_type(&self) -> BatchGenerationEntityType {
|
||||
match self {
|
||||
Self::MediaFile(_) => BatchGenerationEntityType::MediaFile,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_entity_token_str(&self) -> &str {
|
||||
match self {
|
||||
Self::MediaFile(token) => token.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_composite_keys(&self) -> (BatchGenerationEntityType, &str) {
|
||||
match self {
|
||||
Self::MediaFile(token) => (BatchGenerationEntityType::MediaFile, token.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod batch_generation_entity;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod batch_generations;
|
||||
@@ -0,0 +1,22 @@
|
||||
//! composite_identifiers
|
||||
//!
|
||||
//! The purpose of this library is to provide easy to construct, **typesafe**, composite identifiers.
|
||||
//! This is mostly a combination of `tokens` and `enums`.
|
||||
//!
|
||||
|
||||
// Never allow these
|
||||
#![forbid(private_bounds)]
|
||||
#![forbid(private_interfaces)]
|
||||
#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things
|
||||
|
||||
// Okay to toggle
|
||||
#![forbid(unreachable_patterns)]
|
||||
#![forbid(unused_imports)]
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
// Always allow
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
pub mod by_table;
|
||||
@@ -0,0 +1,109 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, ToSchema)]
|
||||
pub enum BatchGenerationEntityType {
|
||||
/// Media files
|
||||
/// This will probably be the only type supported, but we'll leave the possibility of future types.
|
||||
#[serde(rename = "media_file")]
|
||||
MediaFile,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
impl_enum_display_and_debug_using_to_str!(BatchGenerationEntityType);
|
||||
impl_mysql_enum_coders!(BatchGenerationEntityType);
|
||||
impl_mysql_from_row!(BatchGenerationEntityType);
|
||||
|
||||
/// NB: Legacy API for older code.
|
||||
impl BatchGenerationEntityType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::MediaFile => "media_file",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"media_file" => Ok(Self::MediaFile),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::MediaFile,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::batch_generations::batch_generation_entity_type::BatchGenerationEntityType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(BatchGenerationEntityType::MediaFile, "media_file");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(BatchGenerationEntityType::MediaFile.to_str(), "media_file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(BatchGenerationEntityType::from_str("media_file").unwrap(), BatchGenerationEntityType::MediaFile);
|
||||
assert!(BatchGenerationEntityType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
mod manual_variant_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = BatchGenerationEntityType::all_variants();
|
||||
assert_eq!(variants.len(), 1);
|
||||
assert_eq!(variants.pop_first(), Some(BatchGenerationEntityType::MediaFile));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
mod mechanical_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn variant_length() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(BatchGenerationEntityType::all_variants().len(), BatchGenerationEntityType::iter().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in BatchGenerationEntityType::all_variants() {
|
||||
assert_eq!(variant, BatchGenerationEntityType::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, BatchGenerationEntityType::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, BatchGenerationEntityType::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod batch_generation_entity_type;
|
||||
@@ -29,6 +29,9 @@ pub enum InferenceCategory {
|
||||
#[serde(rename = "video_filter")]
|
||||
VideoFilter,
|
||||
|
||||
#[serde(rename = "image_generation")]
|
||||
ImageGeneration,
|
||||
|
||||
#[serde(rename = "mocap")]
|
||||
Mocap,
|
||||
|
||||
@@ -48,6 +51,7 @@ impl InferenceCategory {
|
||||
Self::TextToSpeech => "text_to_speech",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
Self::VideoFilter => "video_filter",
|
||||
Self::ImageGeneration => "image_generation",
|
||||
Self::Mocap => "mocap",
|
||||
Self::Workflow => "workflow",
|
||||
}
|
||||
@@ -59,6 +63,7 @@ impl InferenceCategory {
|
||||
"text_to_speech" => Ok(Self::TextToSpeech),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
"video_filter" => Ok(Self::VideoFilter),
|
||||
"image_generation" => Ok(Self::ImageGeneration),
|
||||
"mocap" => Ok(Self::Mocap),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
@@ -72,6 +77,7 @@ impl InferenceCategory {
|
||||
Self::TextToSpeech,
|
||||
Self::VoiceConversion,
|
||||
Self::VideoFilter,
|
||||
Self::ImageGeneration,
|
||||
Self::Mocap,
|
||||
Self::Workflow,
|
||||
])
|
||||
@@ -89,6 +95,7 @@ mod tests {
|
||||
assert_serialization(InferenceCategory::TextToSpeech, "text_to_speech");
|
||||
assert_serialization(InferenceCategory::VoiceConversion, "voice_conversion");
|
||||
assert_serialization(InferenceCategory::VideoFilter, "video_filter");
|
||||
assert_serialization(InferenceCategory::ImageGeneration, "image_generation");
|
||||
assert_serialization(InferenceCategory::Mocap, "mocap");
|
||||
assert_serialization(InferenceCategory::Workflow, "workflow")
|
||||
}
|
||||
@@ -99,6 +106,7 @@ mod tests {
|
||||
assert_eq!(InferenceCategory::TextToSpeech.to_str(), "text_to_speech");
|
||||
assert_eq!(InferenceCategory::VoiceConversion.to_str(), "voice_conversion");
|
||||
assert_eq!(InferenceCategory::VideoFilter.to_str(), "video_filter");
|
||||
assert_eq!(InferenceCategory::ImageGeneration.to_str(), "image_generation");
|
||||
assert_eq!(InferenceCategory::Mocap.to_str(), "mocap");
|
||||
assert_eq!(InferenceCategory::Workflow.to_str(), "workflow");
|
||||
}
|
||||
@@ -109,6 +117,7 @@ mod tests {
|
||||
assert_eq!(InferenceCategory::from_str("text_to_speech").unwrap(), InferenceCategory::TextToSpeech);
|
||||
assert_eq!(InferenceCategory::from_str("voice_conversion").unwrap(), InferenceCategory::VoiceConversion);
|
||||
assert_eq!(InferenceCategory::from_str("video_filter").unwrap(), InferenceCategory::VideoFilter);
|
||||
assert_eq!(InferenceCategory::from_str("image_generation").unwrap(), InferenceCategory::ImageGeneration);
|
||||
assert_eq!(InferenceCategory::from_str("mocap").unwrap(), InferenceCategory::Mocap);
|
||||
assert_eq!(InferenceCategory::from_str("workflow").unwrap(), InferenceCategory::Workflow);
|
||||
}
|
||||
@@ -122,6 +131,7 @@ mod tests {
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::TextToSpeech));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::VoiceConversion));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::VideoFilter));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::ImageGeneration));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::Mocap));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceCategory::Workflow));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
@@ -33,10 +33,14 @@ pub enum InferenceModelType {
|
||||
VallEX,
|
||||
#[serde(rename = "rerender_a_video")]
|
||||
RerenderAVideo,
|
||||
#[serde(rename = "stable_diffusion")]
|
||||
StableDiffusion,
|
||||
#[serde(rename = "mocap_net")]
|
||||
MocapNet,
|
||||
#[serde(rename = "comfy_ui")]
|
||||
ComfyUi,
|
||||
#[serde(rename = "styletts2")]
|
||||
StyleTTS2,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
@@ -54,7 +58,9 @@ impl InferenceModelType {
|
||||
Self::Vits => "vits",
|
||||
Self::VallEX => "vall_e_x",
|
||||
Self::RerenderAVideo => "rerender_a_video",
|
||||
Self::StableDiffusion => "stable_diffusion",
|
||||
Self::MocapNet => "mocap_net",
|
||||
Self::StyleTTS2 => "styletts2",
|
||||
Self::ComfyUi => "comfy_ui",
|
||||
}
|
||||
}
|
||||
@@ -68,7 +74,9 @@ impl InferenceModelType {
|
||||
"vits" => Ok(Self::Vits),
|
||||
"vall_e_x" => Ok(Self::VallEX),
|
||||
"rerender_a_video" => Ok(Self::RerenderAVideo),
|
||||
"stable_diffusion" => Ok(Self::StableDiffusion),
|
||||
"mocap_net" => Ok(Self::MocapNet),
|
||||
"styletts2" => Ok(Self::StyleTTS2),
|
||||
"comfy_ui" => Ok(Self::ComfyUi),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
@@ -85,7 +93,9 @@ impl InferenceModelType {
|
||||
InferenceModelType::Vits,
|
||||
InferenceModelType::VallEX,
|
||||
InferenceModelType::RerenderAVideo,
|
||||
InferenceModelType::StableDiffusion,
|
||||
InferenceModelType::MocapNet,
|
||||
InferenceModelType::StyleTTS2,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -104,8 +114,10 @@ mod tests {
|
||||
assert_serialization(InferenceModelType::Vits, "vits");
|
||||
assert_serialization(InferenceModelType::VallEX, "vall_e_x");
|
||||
assert_serialization(InferenceModelType::RerenderAVideo, "rerender_a_video");
|
||||
assert_serialization(InferenceModelType::StableDiffusion, "stable_diffusion");
|
||||
assert_serialization(InferenceModelType::MocapNet, "mocap_net");
|
||||
assert_serialization(InferenceModelType::ComfyUi, "comfy_ui");
|
||||
assert_serialization(InferenceModelType::StyleTTS2, "styletts2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -117,7 +129,9 @@ mod tests {
|
||||
assert_eq!(InferenceModelType::Vits.to_str(), "vits");
|
||||
assert_eq!(InferenceModelType::VallEX.to_str(), "vall_e_x");
|
||||
assert_eq!(InferenceModelType::RerenderAVideo.to_str(), "rerender_a_video");
|
||||
assert_eq!(InferenceModelType::StableDiffusion.to_str(), "stable_diffusion");
|
||||
assert_eq!(InferenceModelType::MocapNet.to_str(), "mocap_net");
|
||||
assert_eq!(InferenceModelType::StyleTTS2.to_str(), "styletts2");
|
||||
assert_eq!(InferenceModelType::ComfyUi.to_str(), "comfy_ui");
|
||||
}
|
||||
|
||||
@@ -130,7 +144,9 @@ mod tests {
|
||||
assert_eq!(InferenceModelType::from_str("vits").unwrap(), InferenceModelType::Vits);
|
||||
assert_eq!(InferenceModelType::from_str("vall_e_x").unwrap(), InferenceModelType::VallEX);
|
||||
assert_eq!(InferenceModelType::from_str("rerender_a_video").unwrap(), InferenceModelType::RerenderAVideo);
|
||||
assert_eq!(InferenceModelType::from_str("stable_diffusion").unwrap(), InferenceModelType::StableDiffusion);
|
||||
assert_eq!(InferenceModelType::from_str("mocap_net").unwrap(), InferenceModelType::MocapNet);
|
||||
assert_eq!(InferenceModelType::from_str("styletts2").unwrap(), InferenceModelType::StyleTTS2);
|
||||
assert_eq!(InferenceModelType::from_str("comfy_ui").unwrap(), InferenceModelType::ComfyUi);
|
||||
}
|
||||
|
||||
@@ -138,7 +154,7 @@ mod tests {
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = InferenceModelType::all_variants();
|
||||
assert_eq!(variants.len(), 9);
|
||||
assert_eq!(variants.len(), 10);
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::RvcV2));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::SadTalker));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::SoVitsSvc));
|
||||
@@ -146,7 +162,9 @@ mod tests {
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::Vits));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::VallEX));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::RerenderAVideo));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::StableDiffusion));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::MocapNet));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::StyleTTS2));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceModelType::ComfyUi));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ pub enum InferenceResultType {
|
||||
|
||||
#[serde(rename = "zs_voice_embedding")]
|
||||
ZeroShotVoiceEmbedding,
|
||||
|
||||
#[serde(rename = "upload_model")]
|
||||
UploadModel
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
@@ -43,6 +46,7 @@ impl InferenceResultType {
|
||||
Self::TextToSpeech => "text_to_speech",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
Self::ZeroShotVoiceEmbedding => "zs_voice_embedding",
|
||||
Self::UploadModel => "upload_model",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +56,7 @@ impl InferenceResultType {
|
||||
"text_to_speech" => Ok(Self::TextToSpeech),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
"zs_voice_embedding" => Ok(Self::ZeroShotVoiceEmbedding),
|
||||
"upload_model" => Ok(Self::UploadModel),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -64,6 +69,7 @@ impl InferenceResultType {
|
||||
InferenceResultType::TextToSpeech,
|
||||
InferenceResultType::VoiceConversion,
|
||||
InferenceResultType::ZeroShotVoiceEmbedding,
|
||||
InferenceResultType::UploadModel,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -79,6 +85,7 @@ mod tests {
|
||||
assert_serialization(InferenceResultType::TextToSpeech, "text_to_speech");
|
||||
assert_serialization(InferenceResultType::VoiceConversion, "voice_conversion");
|
||||
assert_serialization(InferenceResultType::ZeroShotVoiceEmbedding, "zs_voice_embedding");
|
||||
assert_serialization(InferenceResultType::UploadModel, "upload_model");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -87,6 +94,7 @@ mod tests {
|
||||
assert_eq!(InferenceResultType::TextToSpeech.to_str(), "text_to_speech");
|
||||
assert_eq!(InferenceResultType::VoiceConversion.to_str(), "voice_conversion");
|
||||
assert_eq!(InferenceResultType::ZeroShotVoiceEmbedding.to_str(), "zs_voice_embedding");
|
||||
assert_eq!(InferenceResultType::UploadModel.to_str(), "upload_model");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -95,17 +103,19 @@ mod tests {
|
||||
assert_eq!(InferenceResultType::from_str("text_to_speech").unwrap(), InferenceResultType::TextToSpeech);
|
||||
assert_eq!(InferenceResultType::from_str("voice_conversion").unwrap(), InferenceResultType::VoiceConversion);
|
||||
assert_eq!(InferenceResultType::from_str("zs_voice_embedding").unwrap(), InferenceResultType::ZeroShotVoiceEmbedding);
|
||||
assert_eq!(InferenceResultType::from_str("upload_model").unwrap(), InferenceResultType::UploadModel);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
// Static check
|
||||
let mut variants = InferenceResultType::all_variants();
|
||||
assert_eq!(variants.len(), 4);
|
||||
assert_eq!(variants.len(), 5);
|
||||
assert_eq!(variants.pop_first(), Some(InferenceResultType::MediaFile));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceResultType::TextToSpeech));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceResultType::VoiceConversion));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceResultType::ZeroShotVoiceEmbedding));
|
||||
assert_eq!(variants.pop_first(), Some(InferenceResultType::UploadModel));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
|
||||
// Generated check
|
||||
|
||||
@@ -41,6 +41,9 @@ pub enum MediaFileOriginModelType {
|
||||
|
||||
#[serde(rename = "comfy_ui")]
|
||||
ComfyUi,
|
||||
|
||||
#[serde(rename = "styletts2")]
|
||||
StyleTTS2,
|
||||
}
|
||||
|
||||
// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests!
|
||||
@@ -60,6 +63,7 @@ impl MediaFileOriginModelType {
|
||||
Self::Rerender => "rerender",
|
||||
Self::MocapNet => "mocap_net",
|
||||
Self::ComfyUi => "comfy_ui",
|
||||
Self::StyleTTS2 => "styletts2",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +77,7 @@ impl MediaFileOriginModelType {
|
||||
"rerender" => Ok(Self::Rerender),
|
||||
"mocap_net" => Ok(Self::MocapNet),
|
||||
"comfy_ui" => Ok(Self::ComfyUi),
|
||||
"styletts2" => Ok(Self::StyleTTS2),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -89,6 +94,7 @@ impl MediaFileOriginModelType {
|
||||
Self::Rerender,
|
||||
Self::MocapNet,
|
||||
Self::ComfyUi,
|
||||
Self::StyleTTS2,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -116,6 +122,7 @@ mod tests {
|
||||
assert_eq!(MediaFileOriginModelType::Rerender.to_str(), "rerender");
|
||||
assert_eq!(MediaFileOriginModelType::MocapNet.to_str(), "mocap_net");
|
||||
assert_eq!(MediaFileOriginModelType::ComfyUi.to_str(), "comfy_ui");
|
||||
assert_eq!(MediaFileOriginModelType::StyleTTS2.to_str(), "styletts2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -128,13 +135,14 @@ mod tests {
|
||||
assert_eq!(MediaFileOriginModelType::from_str("rerender").unwrap(), MediaFileOriginModelType::Rerender);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("mocap_net").unwrap(), MediaFileOriginModelType::MocapNet);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("comfy_ui").unwrap(), MediaFileOriginModelType::ComfyUi);
|
||||
assert_eq!(MediaFileOriginModelType::from_str("styletts2").unwrap(), MediaFileOriginModelType::StyleTTS2);
|
||||
assert!(MediaFileOriginModelType::from_str("foo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileOriginModelType::all_variants();
|
||||
assert_eq!(variants.len(), 8);
|
||||
assert_eq!(variants.len(), 10);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::RvcV2));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SadTalker));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::SoVitsSvc));
|
||||
@@ -143,6 +151,7 @@ mod tests {
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::Rerender));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::MocapNet));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::ComfyUi));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginModelType::StyleTTS2));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -17,6 +17,11 @@ use utoipa::ToSchema;
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema)]
|
||||
pub enum MediaFileOriginProductCategory {
|
||||
/// Unknown which product is attached to the file (generated the file, the file was
|
||||
/// uploaded on behalf of, etc.)
|
||||
#[serde(rename = "unknown")]
|
||||
Unknown,
|
||||
|
||||
/// Media files created by (or uploaded for) the Face Animator product.
|
||||
/// The underlying model could be SadTalker, Wav2Lip, or some future model
|
||||
#[serde(rename = "face_animator")]
|
||||
@@ -26,12 +31,6 @@ pub enum MediaFileOriginProductCategory {
|
||||
#[serde(rename = "tts")]
|
||||
TextToSpeech,
|
||||
|
||||
// TODO: This should be a temporary category until we migrate the DB to remove this default value
|
||||
/// Unknown which product is attached to the file (generated the file, the file was
|
||||
/// uploaded on behalf of, etc.)
|
||||
#[serde(rename = "unknown")]
|
||||
Unknown,
|
||||
|
||||
/// Voice conversion (either RVC or SVC)
|
||||
#[serde(rename = "voice_conversion")]
|
||||
VoiceConversion,
|
||||
@@ -62,9 +61,9 @@ impl_mysql_from_row!(MediaFileOriginProductCategory);
|
||||
impl MediaFileOriginProductCategory {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unknown => "unknown",
|
||||
Self::FaceAnimator => "face_animator",
|
||||
Self::TextToSpeech => "tts",
|
||||
Self::Unknown => "unknown",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
Self::ZeroShotVoice => "zs_voice",
|
||||
Self::VideoFilter => "video_filter",
|
||||
@@ -75,9 +74,9 @@ impl MediaFileOriginProductCategory {
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"unknown" => Ok(Self::Unknown),
|
||||
"face_animator" => Ok(Self::FaceAnimator),
|
||||
"tts" => Ok(Self::TextToSpeech),
|
||||
"unknown" => Ok(Self::Unknown),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
"zs_voice" => Ok(Self::ZeroShotVoice),
|
||||
"video_filter" => Ok(Self::VideoFilter),
|
||||
@@ -91,10 +90,10 @@ impl MediaFileOriginProductCategory {
|
||||
// NB: BTreeSet is sorted
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::Unknown,
|
||||
Self::FaceAnimator,
|
||||
Self::TextToSpeech,
|
||||
Self::VideoFilter,
|
||||
Self::Unknown,
|
||||
Self::VoiceConversion,
|
||||
Self::ZeroShotVoice,
|
||||
Self::Mocap,
|
||||
@@ -113,9 +112,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown");
|
||||
assert_serialization(MediaFileOriginProductCategory::FaceAnimator, "face_animator");
|
||||
assert_serialization(MediaFileOriginProductCategory::TextToSpeech, "tts");
|
||||
assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown");
|
||||
assert_serialization(MediaFileOriginProductCategory::VoiceConversion, "voice_conversion");
|
||||
assert_serialization(MediaFileOriginProductCategory::ZeroShotVoice, "zs_voice");
|
||||
assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter");
|
||||
@@ -125,9 +124,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(MediaFileOriginProductCategory::Unknown.to_str(), "unknown");
|
||||
assert_eq!(MediaFileOriginProductCategory::FaceAnimator.to_str(), "face_animator");
|
||||
assert_eq!(MediaFileOriginProductCategory::TextToSpeech.to_str(), "tts");
|
||||
assert_eq!(MediaFileOriginProductCategory::Unknown.to_str(), "unknown");
|
||||
assert_eq!(MediaFileOriginProductCategory::VoiceConversion.to_str(), "voice_conversion");
|
||||
assert_eq!(MediaFileOriginProductCategory::ZeroShotVoice.to_str(), "zs_voice");
|
||||
assert_eq!(MediaFileOriginProductCategory::VideoFilter.to_str(), "video_filter");
|
||||
@@ -137,9 +136,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("unknown").unwrap(), MediaFileOriginProductCategory::Unknown);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("face_animator").unwrap(), MediaFileOriginProductCategory::FaceAnimator);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("tts").unwrap(), MediaFileOriginProductCategory::TextToSpeech);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("unknown").unwrap(), MediaFileOriginProductCategory::Unknown);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("voice_conversion").unwrap(), MediaFileOriginProductCategory::VoiceConversion);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("zs_voice").unwrap(), MediaFileOriginProductCategory::ZeroShotVoice);
|
||||
assert_eq!(MediaFileOriginProductCategory::from_str("video_filter").unwrap(), MediaFileOriginProductCategory::VideoFilter);
|
||||
@@ -151,9 +150,9 @@ mod tests {
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileOriginProductCategory::all_variants();
|
||||
assert_eq!(variants.len(), 8);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Unknown));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::FaceAnimator));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::TextToSpeech));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::Unknown));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VoiceConversion));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::ZeroShotVoice));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileOriginProductCategory::VideoFilter));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// ===== MySql =====
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod comments;
|
||||
pub mod email_sender_jobs;
|
||||
pub mod entity_stats;
|
||||
@@ -17,6 +18,7 @@ pub mod user_ratings;
|
||||
pub mod voice_conversion_models;
|
||||
pub mod voice_conversion_results;
|
||||
pub mod zs_voices;
|
||||
|
||||
// ===== Sqlite =====
|
||||
pub mod tts_render_tasks;
|
||||
pub mod web_rendition_targets;
|
||||
|
||||
@@ -17,6 +17,8 @@ pub enum WeightsCategory {
|
||||
Vocoder,
|
||||
#[serde(rename = "voice_conversion")]
|
||||
VoiceConversion,
|
||||
#[serde(rename = "workflow_config")]
|
||||
WorkflowConfig,
|
||||
}
|
||||
|
||||
impl WeightsCategory {
|
||||
@@ -26,6 +28,7 @@ impl WeightsCategory {
|
||||
Self::TextToSpeech => "text_to_speech",
|
||||
Self::Vocoder => "vocoder",
|
||||
Self::VoiceConversion => "voice_conversion",
|
||||
Self::WorkflowConfig => "workflow_config",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +38,7 @@ impl WeightsCategory {
|
||||
"text_to_speech" => Ok(Self::TextToSpeech),
|
||||
"vocoder" => Ok(Self::Vocoder),
|
||||
"voice_conversion" => Ok(Self::VoiceConversion),
|
||||
"workflow_config" => Ok(Self::WorkflowConfig),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -45,6 +49,7 @@ impl WeightsCategory {
|
||||
Self::TextToSpeech,
|
||||
Self::Vocoder,
|
||||
Self::VoiceConversion,
|
||||
Self::WorkflowConfig,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -62,6 +67,7 @@ mod tests {
|
||||
assert_eq!(WeightsCategory::TextToSpeech.to_str(), "text_to_speech");
|
||||
assert_eq!(WeightsCategory::Vocoder.to_str(), "vocoder");
|
||||
assert_eq!(WeightsCategory::VoiceConversion.to_str(), "voice_conversion");
|
||||
assert_eq!(WeightsCategory::WorkflowConfig.to_str(), "workflow_config");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -70,16 +76,18 @@ mod tests {
|
||||
assert_eq!(WeightsCategory::from_str("text_to_speech").unwrap(), WeightsCategory::TextToSpeech);
|
||||
assert_eq!(WeightsCategory::from_str("vocoder").unwrap(), WeightsCategory::Vocoder);
|
||||
assert_eq!(WeightsCategory::from_str("voice_conversion").unwrap(), WeightsCategory::VoiceConversion);
|
||||
assert_eq!(WeightsCategory::from_str("workflow_config").unwrap(), WeightsCategory::WorkflowConfig);
|
||||
assert!(WeightsCategory::from_str("invalid").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_variants() {
|
||||
let variants = WeightsCategory::all_variants();
|
||||
assert_eq!(variants.len(), 4);
|
||||
assert_eq!(variants.len(), 5);
|
||||
assert!(variants.contains(&WeightsCategory::ImageGeneration));
|
||||
assert!(variants.contains(&WeightsCategory::TextToSpeech));
|
||||
assert!(variants.contains(&WeightsCategory::Vocoder));
|
||||
assert!(variants.contains(&WeightsCategory::VoiceConversion));
|
||||
assert!(variants.contains(&WeightsCategory::WorkflowConfig));
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ pub enum WeightsType {
|
||||
LoRA,
|
||||
#[serde(rename = "vall_e")]
|
||||
VallE,
|
||||
#[serde(rename = "comfy_ui")]
|
||||
ComfyUi,
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +41,7 @@ impl WeightsType {
|
||||
Self::Tacotron2 => "tt2",
|
||||
Self::LoRA => "loRA",
|
||||
Self::VallE => "vall_e",
|
||||
Self::ComfyUi => "comfy_ui",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +55,7 @@ impl WeightsType {
|
||||
"tt2" => Ok(Self::Tacotron2),
|
||||
"loRA" => Ok(Self::LoRA),
|
||||
"vall_e" => Ok(Self::VallE),
|
||||
"comfy_ui" => Ok(Self::ComfyUi),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -65,7 +69,8 @@ impl WeightsType {
|
||||
Self::SoVitsSvc,
|
||||
Self::Tacotron2,
|
||||
Self::LoRA,
|
||||
Self::VallE
|
||||
Self::VallE,
|
||||
Self::ComfyUi,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -88,6 +93,7 @@ mod tests {
|
||||
assert_eq!(WeightsType::Tacotron2.to_str(), "tt2");
|
||||
assert_eq!(WeightsType::LoRA.to_str(), "loRA");
|
||||
assert_eq!(WeightsType::VallE.to_str(), "vall_e");
|
||||
assert_eq!(WeightsType::ComfyUi.to_str(), "comfy_ui");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -100,13 +106,14 @@ mod tests {
|
||||
assert_eq!(WeightsType::from_str("tt2").unwrap(), WeightsType::Tacotron2);
|
||||
assert_eq!(WeightsType::from_str("loRA").unwrap(), WeightsType::LoRA);
|
||||
assert_eq!(WeightsType::from_str("vall_e").unwrap(), WeightsType::VallE);
|
||||
assert_eq!(WeightsType::from_str("comfy_ui").unwrap(), WeightsType::ComfyUi);
|
||||
assert!(WeightsType::from_str("invalid").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_variants() {
|
||||
let variants = WeightsType::all_variants();
|
||||
assert_eq!(variants.len(), 8);
|
||||
assert_eq!(variants.len(), 9);
|
||||
assert!(variants.contains(&WeightsType::HifiganTacotron2));
|
||||
assert!(variants.contains(&WeightsType::RvcV2));
|
||||
assert!(variants.contains(&WeightsType::StableDiffusion15));
|
||||
@@ -115,5 +122,6 @@ mod tests {
|
||||
assert!(variants.contains(&WeightsType::Tacotron2));
|
||||
assert!(variants.contains(&WeightsType::LoRA));
|
||||
assert!(variants.contains(&WeightsType::VallE));
|
||||
assert!(variants.contains(&WeightsType::ComfyUi));
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ pub enum ZsVoiceModelType {
|
||||
/// TTS-type zero shot models
|
||||
#[serde(rename = "vall-e-x")]
|
||||
VallEX,
|
||||
#[serde(rename = "styletts2")]
|
||||
StyleTTS2,
|
||||
}
|
||||
|
||||
// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests!
|
||||
@@ -27,12 +29,14 @@ impl ZsVoiceModelType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::VallEX=> "vall-e-x",
|
||||
Self::StyleTTS2 => "styletts2",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"vall-e-x" => Ok(Self::VallEX),
|
||||
"styletts2" => Ok(Self::StyleTTS2),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
@@ -42,6 +46,7 @@ impl ZsVoiceModelType {
|
||||
// NB: BTreeSet::from() isn't const, but not worth using LazyStatic, etc.
|
||||
BTreeSet::from([
|
||||
Self::VallEX,
|
||||
Self::StyleTTS2,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -66,11 +71,13 @@ mod tests {
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(ZsVoiceModelType::VallEX.to_str(), "vall-e-x");
|
||||
assert_eq!(ZsVoiceModelType::StyleTTS2.to_str(), "styletts2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(ZsVoiceModelType::from_str("vall-e-x").unwrap(), ZsVoiceModelType::VallEX);
|
||||
assert_eq!(ZsVoiceModelType::from_str("styletts2").unwrap(), ZsVoiceModelType::StyleTTS2);
|
||||
assert!(ZsVoiceModelType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
@@ -81,8 +88,9 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = ZsVoiceModelType::all_variants();
|
||||
assert_eq!(variants.len(), 1);
|
||||
assert_eq!(variants.len(), 2);
|
||||
assert_eq!(variants.pop_first(), Some(ZsVoiceModelType::VallEX));
|
||||
assert_eq!(variants.pop_first(), Some(ZsVoiceModelType::StyleTTS2));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ use strum::EnumIter;
|
||||
pub(crate) enum TokenPrefix {
|
||||
AnonymousVisitorTracking, // AVTs are not stored as primary keys in any table, but an index in many tables.
|
||||
AuditLog,
|
||||
BatchGeneration,
|
||||
Comment,
|
||||
DownloadJob,
|
||||
EmailSenderJob,
|
||||
@@ -90,6 +91,7 @@ impl PrefixGenerator for TokenPrefix {
|
||||
match self {
|
||||
Self::AnonymousVisitorTracking => "avt_",
|
||||
Self::AuditLog => "audit_",
|
||||
Self::BatchGeneration => "batch_g_",
|
||||
Self::Comment => "comment_",
|
||||
Self::DownloadJob => "jdown_", // NB: Previously "JGUP:"
|
||||
Self::EmailSenderJob => "email_job_",
|
||||
@@ -297,7 +299,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_all_prefixes_end_with_separator_length_one() {
|
||||
for prefix in get_all_prefixes().iter().map(|s| *s) {
|
||||
if prefix == "news_story_" || prefix == "tts_task_" || prefix == "INT_API:" || prefix == "pw_reset_" || prefix == "email_job_" {
|
||||
if prefix == "news_story_"
|
||||
|| prefix == "tts_task_"
|
||||
|| prefix == "INT_API:"
|
||||
|| prefix == "pw_reset_"
|
||||
|| prefix == "email_job_"
|
||||
|| prefix == "batch_g_"
|
||||
{
|
||||
// TODO/FIXME: I'm too tired at 5AM to replacen from the left. Make this test valid.
|
||||
// These tokens are from the AIChatBot sidecar, so asserting their validity is less important.
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::prefixes::TokenPrefix;
|
||||
|
||||
/// The primary key for Audit Logs.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct BatchGenerationToken(pub String);
|
||||
|
||||
impl_string_token!(BatchGenerationToken);
|
||||
impl_crockford_generator!(BatchGenerationToken, 32usize, TokenPrefix::BatchGeneration, CrockfordLower);
|
||||
@@ -2,6 +2,7 @@ pub mod anonymous_visitor_tracking;
|
||||
pub mod api_tokens_external;
|
||||
pub mod api_tokens_internal;
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod comments;
|
||||
pub mod email_sender_job_token;
|
||||
pub mod firehose_entries;
|
||||
@@ -20,6 +21,7 @@ pub mod tts_results;
|
||||
pub mod twitch_event_rule;
|
||||
pub mod twitch_oauth_tokens_grouping;
|
||||
pub mod twitch_oauth_tokens_internal;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_sessions;
|
||||
pub mod user_subscriptions;
|
||||
pub mod users;
|
||||
@@ -34,4 +36,3 @@ pub mod w2l_templates;
|
||||
pub mod zs_voice_dataset_samples;
|
||||
pub mod zs_voice_datasets;
|
||||
pub mod zs_voices;
|
||||
pub mod user_bookmarks;
|
||||
@@ -7,13 +7,11 @@ use errors::AnyhowResult;
|
||||
|
||||
use crate::bucket_clients::get_bucket_clients;
|
||||
use crate::cli_args::parse_cli_args;
|
||||
use crate::seeding::model_weights::seed_weights; // V1
|
||||
use crate::seeding::seed_model_weights::seed_weights_files; // V2 v3 will come later on when everything is more conslidated and clear.
|
||||
use crate::seeding::model_weights::seed_weights;
|
||||
use crate::seeding::seed_media_files::seed_media_files;
|
||||
use crate::seeding::tts_tacotron2::seed_tts_tacotron2;
|
||||
use crate::seeding::users::seed_user_accounts;
|
||||
use crate::seeding::voice_conversion::seed_voice_conversion;
|
||||
use crate::seeding::zero_shot_tts::seed_zero_shot_tts;
|
||||
|
||||
pub mod bucket_clients;
|
||||
|
||||
@@ -61,9 +59,10 @@ pub async fn main() -> AnyhowResult<()> {
|
||||
seed_tts_tacotron2(&pool, maybe_bucket_clients.as_ref()).await?;
|
||||
|
||||
// should seed the weights with a few files for hanashi
|
||||
seed_weights_files(&pool, maybe_bucket_clients.as_ref()).await?;
|
||||
|
||||
info!("Done!");
|
||||
//seed_weights_files(&pool, maybe_bucket_clients.as_ref()).await?;
|
||||
//println!("TESTING DOWLOAD");
|
||||
//test_seed_weights_files().await?;
|
||||
//info!("Done!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
use std::path::PathBuf;
|
||||
use std::vec;
|
||||
|
||||
use log::info;
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use cloud_storage::remote_file_manager::remote_cloud_bucket_details::RemoteCloudBucketDetails;
|
||||
use cloud_storage::remote_file_manager::remote_cloud_file_manager::RemoteCloudFileClient;
|
||||
use cloud_storage::remote_file_manager::weights_descriptor::{WeightsLoRADescriptor, WeightsSD15Descriptor, WeightsWorkflowDescriptor};
|
||||
use enums::by_table::model_weights::{
|
||||
weights_category::WeightsCategory,
|
||||
weights_types::WeightsType,
|
||||
@@ -11,11 +15,48 @@ use enums::common::visibility::Visibility;
|
||||
use errors::{anyhow, AnyhowResult};
|
||||
use mysql_queries::queries::model_weights::create::create_weight::{create_weight, CreateModelWeightsArgs};
|
||||
use mysql_queries::queries::users::user::get_user_token_by_username::get_user_token_by_username;
|
||||
use storyteller_root::get_seed_tool_data_root;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::seeding::users::HANASHI_USERNAME;
|
||||
|
||||
pub async fn test_seed_weights_files() -> AnyhowResult<()> {
|
||||
|
||||
let seed_path = PathBuf::from("/storyteller/root/custom-seed-tool-data");
|
||||
let remote_cloud_file_client = RemoteCloudFileClient::get_remote_cloud_file_client().await;
|
||||
let remote_cloud_file_client = match remote_cloud_file_client {
|
||||
Ok(res) => {
|
||||
res
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(anyhow!("failed to get remote cloud file client"));
|
||||
}
|
||||
};
|
||||
|
||||
let mut path_dl1 = seed_path.clone();
|
||||
path_dl1.push("downloads/loRA");
|
||||
let mut path_dl2 = seed_path.clone();
|
||||
path_dl2.push("downloads/checkpoint");
|
||||
|
||||
let bucket_details1 = RemoteCloudBucketDetails {
|
||||
object_hash: String::from("apa0ej6es8d3ss2gwtf1cghge35qn9tn"),
|
||||
prefix: String::from("sd15"),
|
||||
suffix: String::from("safetensors"),
|
||||
};
|
||||
|
||||
let bucket_details2 = RemoteCloudBucketDetails {
|
||||
object_hash: String::from("27kz11et18fargyyxbj66ntfn621k9d3"),
|
||||
prefix: String::from("loRA"),
|
||||
suffix: String::from("safetensors"),
|
||||
};
|
||||
|
||||
remote_cloud_file_client.download_file(bucket_details1, String::from("./checkpoint")).await?;
|
||||
remote_cloud_file_client.download_file(bucket_details2, String::from("./loRA")).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn seed_weights_for_paging(mysql_pool: &Pool<MySql>, user_token: UserToken) -> AnyhowResult<()> {
|
||||
let sd1_5_markdown_description = r#"
|
||||
# Dragonfruit AI Models Update and Workflow
|
||||
@@ -330,6 +371,351 @@ pub async fn seed_weights_for_paging(mysql_pool: &Pool<MySql>, user_token: UserT
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn seed_weights_for_testing_inference(mysql_pool: &Pool<MySql>, user_token: UserToken) -> AnyhowResult<()>{
|
||||
|
||||
|
||||
let miyhoyo_description = r#"一个面向米哈游角色的模型合集~A collection for MIHOYO Characters~
|
||||
对应人物tag记录在版本信息里,可在右侧“About this version”选项中查看。The corresponding character prompts are recorded in the version information and can be viewed in the About this version option on the right.
|
||||
打开目录寻找最爱~(附带链接,点击直达)~Open the catalog, find your favorites~ (with links, click to go directly):
|
||||
崩坏三 Honkai Impact 3rd:
|
||||
|
||||
梅比乌斯- Mobius
|
||||
|
||||
琪亚娜-Kiana:琪亚娜 合集-Collections for Kiana (Honkai Impact 3rd)
|
||||
|
||||
布洛妮娅-bronya:布洛妮娅 合集-Collections for Bronya (Honkai Impact 3rd | Honkai Star Rail)
|
||||
|
||||
芽衣:雷电芽衣 合集-Collections for Raiden Mei (Honkai Impact 3rd)
|
||||
|
||||
西琳-Sirin
|
||||
|
||||
魔法少女-Miracle ☆ Magical Girl
|
||||
|
||||
赤鸢-Jingwei
|
||||
|
||||
丹朱苍玄-Nuwa/Fuxi
|
||||
|
||||
李素裳-Li Sushang
|
||||
|
||||
玉骑士·月痕/锦岁玉团-Jade Knight/Auspicious Dazzle
|
||||
|
||||
卡莲-kallen
|
||||
|
||||
第六夜想曲-Sixth Serenade
|
||||
|
||||
符华-Fu hua
|
||||
|
||||
崩落
|
||||
|
||||
云墨丹心-Azure Empyrea
|
||||
|
||||
八重樱-Yae Sakura
|
||||
|
||||
逆神巫女-Gyakushinn Miko
|
||||
|
||||
御神装·勿忘-Goushinnso Memento
|
||||
|
||||
信花舞伎-Blooming Maiko
|
||||
|
||||
希尔-Seele
|
||||
|
||||
生死律者-Herrscher of Rebirth
|
||||
|
||||
栖于永夜-Eternal Night's Embrace
|
||||
|
||||
德莉莎-Theresa:德莉莎 合集-Collections for Theresa (Honkai Impact 3rd)
|
||||
|
||||
月下誓约-Lunar Vow: Crimson Love
|
||||
|
||||
月下初拥-Luna Kindred
|
||||
|
||||
花裳月纱-Rosy Bridesmaid
|
||||
|
||||
格蕾修-Griseo
|
||||
|
||||
繁星·绘世之卷-Starry Impression
|
||||
|
||||
天行·绘星之卷-Cosmic Expression
|
||||
|
||||
画中的童话-Maroon Riding Hood
|
||||
|
||||
原神 Genshin:
|
||||
|
||||
凝光-Ningguang
|
||||
|
||||
申鹤-Shenhe
|
||||
|
||||
妮露
|
||||
|
||||
诺艾尔
|
||||
|
||||
神里绫华(包含礼装)
|
||||
|
||||
甘雨(包含喜茶联动礼装)-Ganyu
|
||||
|
||||
胡桃(包含森罗联动礼装)-Hutao
|
||||
|
||||
琳妮特-Lynette
|
||||
|
||||
绮良良-Kirara
|
||||
|
||||
坎蒂丝-Candace
|
||||
|
||||
芙宁娜-Furina
|
||||
|
||||
芙宁娜/芙卡洛斯-Furina/Focalors
|
||||
|
||||
克洛琳德-Clorinde
|
||||
|
||||
娜维娅-Navia
|
||||
|
||||
丝柯克-Skirk
|
||||
|
||||
夏洛蒂-Charlotte
|
||||
|
||||
归终-Guizhong
|
||||
|
||||
闲云-Xianyun
|
||||
|
||||
千织-Chiori
|
||||
|
||||
夏沃蕾-Chevreuse
|
||||
|
||||
崩坏:星穹铁道 Honkai Star Rand:
|
||||
|
||||
驭空-Yukong
|
||||
|
||||
银狼-Silver Wolf
|
||||
|
||||
符玄-Fu Xuan
|
||||
|
||||
李素裳-Sushang
|
||||
|
||||
三月七(礼装)-March 7th (New Outfit)
|
||||
|
||||
停云-Tingyun
|
||||
|
||||
青雀-Qingque
|
||||
|
||||
布洛妮娅·兰德-Bronya Rand
|
||||
|
||||
镜流-Jingliu
|
||||
|
||||
卡芙卡-Kafka
|
||||
|
||||
托帕-Topaz
|
||||
|
||||
桂乃芬-Guinaifen
|
||||
|
||||
玲可-Lynx
|
||||
|
||||
佩拉-Peia
|
||||
|
||||
寒鸦-Hanya
|
||||
|
||||
藿藿-Huohuo
|
||||
|
||||
阮·梅-Ruan Mei
|
||||
|
||||
雪衣-Xueyi
|
||||
|
||||
希露瓦-Serval
|
||||
|
||||
绝区零 Zenless-zone-zero:
|
||||
|
||||
星见雅-Miyabi
|
||||
|
||||
猫宫又奈-Nekomata
|
||||
|
||||
艾莲·乔-Ellen
|
||||
|
||||
妮可-Nicole
|
||||
|
||||
苍角-Soukaku
|
||||
|
||||
格莉丝-Grace
|
||||
|
||||
珂蕾妲-koleda
|
||||
|
||||
可琳-Corin
|
||||
|
||||
其他 Others:
|
||||
|
||||
鹿鸣-Luming
|
||||
"""#;
|
||||
|
||||
let sd1_5_markdown_description = r#"
|
||||
00025-2161235528-1girl,(orange_hair_1.1),(zentangle, mandala, tangle, entangle_0.6),(fractal art),the most beautiful form of chaos,brutalist desi.png
|
||||
|
||||
|
||||
00010-1626070972-elf portrait,enchanting beauty,fantasy,ethereal glow,pointed ears,delicate facial features,long elegant hair,nature-themed attir.png
|
||||
|
||||
|
||||
00001-301370162-girl in a snowy landscape,winter coat,fluffy hood,white fur trim,breath visible in cold air,soft falling snowflakes,glistening s.png
|
||||
|
||||
|
||||
00002-3996269517-venomous sorcerer,ominous dark robes,glowing green eyes,holding a staff with a serpent design,mystical green flames,poisonous mi.png
|
||||
|
||||
|
||||
00003-3817469732-Thunder Deity,immense power,hovering above the sea,stormy ocean waves below,crackling lightning in fingertips,dramatic stormy cl.png
|
||||
|
||||
if you want to remake my front image, check this out: Lightflow | SD webUI Extension - workflow restore & save in one click - majicMIXfantasy example | Stable Diffusion Other | Civitai
|
||||
|
||||
v3 is here. Shouldn't be difficult to use. Simple and complex prompts can be used, unleash your imagination.
|
||||
|
||||
v3来了,简单复杂的提示词都可以用。
|
||||
|
||||
I developed the v3 version towards 2D in order to make more room for 2.5D models like majicmix lux.
|
||||
|
||||
v3版本我往2D发展是为了给majicmix lux等2.5D模型让出更多空间。
|
||||
|
||||
merged from融了:
|
||||
Jack Of All by GeneratedJudge
|
||||
|
||||
AWPainting by DynamicWang
|
||||
|
||||
majicMIX fantasy v2 =
|
||||
Noosphere by skumerz + dalcefoPainting + 饭特稀V08 by zhazhahui345 + GhostMix
|
||||
"#;
|
||||
|
||||
|
||||
let sd_vae_description = r"This is an earlier version of a stable VAE. Compared to other VAEs, it has a higher level of stability. I am not the creator, but I could not find this VAE on the website, so I am sharing it here.
|
||||
这是较早时候的稳定VAE,与其他VAE相比具有较高的稳定性,不容易坏图。我不是作者,但是站里没找着所以搬运。#";
|
||||
|
||||
|
||||
info!("Seeding weights for inference...");
|
||||
ModelWeightToken::reset_rng_for_testing_and_dev_seeding_never_use_in_production_seriously(54321);
|
||||
let model_weight_token1 = ModelWeightToken::generate_for_testing_and_dev_seeding_never_use_in_production_seriously();
|
||||
let model_weight_token2 = ModelWeightToken::generate_for_testing_and_dev_seeding_never_use_in_production_seriously();
|
||||
let model_weight_token3 = ModelWeightToken::generate_for_testing_and_dev_seeding_never_use_in_production_seriously();
|
||||
|
||||
|
||||
let remote_cloud_file_client = RemoteCloudFileClient::get_remote_cloud_file_client().await?;
|
||||
|
||||
let sd_15_weights_descriptor = Box::new(WeightsSD15Descriptor {});
|
||||
let lora_descriptor = Box::new(WeightsLoRADescriptor{});
|
||||
let sd_vae_15_weights_descriptor = Box::new(WeightsSD15Descriptor {});
|
||||
|
||||
let mut path_object_SD = get_seed_tool_data_root();
|
||||
path_object_SD.push("models/imagegen/sd15/majicmixFantasy_v30Vae.safetensors");
|
||||
|
||||
let mut path_object_loRA = get_seed_tool_data_root();
|
||||
path_object_loRA.push("models/imagegen/loRA/xiawolei-v100-000019.safetensors");
|
||||
|
||||
let mut path_to_VAE = get_seed_tool_data_root();
|
||||
path_to_VAE.push("models/imagegen/vae/zVae_v20.safetensors");
|
||||
|
||||
let metadata1 = remote_cloud_file_client.upload_file(sd_15_weights_descriptor,path_object_SD.as_path().to_str().unwrap()).await?;
|
||||
let metadata2 = remote_cloud_file_client.upload_file(lora_descriptor,path_object_loRA.as_path().to_str().unwrap()).await?;
|
||||
let metadata3 = remote_cloud_file_client.upload_file(sd_vae_15_weights_descriptor,path_to_VAE.as_path().to_str().unwrap()).await?;
|
||||
|
||||
let weights1 = CreateModelWeightsArgs {
|
||||
token: &model_weight_token1, // replace with actual ModelWeightToken
|
||||
weights_type: WeightsType::StableDiffusion15, // replace with actual WeightsType
|
||||
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
|
||||
title: "Dragonfruit".to_string(),
|
||||
maybe_description_markdown: Some(sd1_5_markdown_description.to_string()),
|
||||
maybe_description_rendered_html: Some("<p>Description</p>".to_string()),
|
||||
creator_user_token: Some(&user_token), // replace with actual UserToken
|
||||
creator_ip_address: "192.168.1.1",
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_last_update_user_token: Some("Last Update User Token".to_string()),
|
||||
original_download_url: Some("https://civitai.com/models/41865/majicmix-fantasy".to_string()),
|
||||
original_filename: Some("majicmixFantasy_v30Vae.safetensors".to_string()),
|
||||
file_size_bytes: metadata1.file_size_bytes as i32,
|
||||
file_checksum_sha2: metadata1.sha256_checksum.to_string(),
|
||||
public_bucket_hash: metadata1.bucket_details.clone().unwrap().object_hash,
|
||||
maybe_public_bucket_prefix: Some(metadata1.bucket_details.clone().unwrap().prefix),
|
||||
maybe_public_bucket_extension: Some(metadata1.bucket_details.clone().unwrap().suffix),
|
||||
version: 1,
|
||||
mysql_pool: &mysql_pool, // replace with actual MySqlPool
|
||||
};
|
||||
|
||||
let weights2 = CreateModelWeightsArgs {
|
||||
token: &model_weight_token2, // replace with actual ModelWeightToken
|
||||
weights_type: WeightsType::LoRA, // replace with actual WeightsType
|
||||
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
|
||||
title: "MIHOYO Collection 米家全家桶 (Honkai Impact 3rd | Honkai Star Rail | Genshin Impact | Zenless Zone Zero)".to_string(),
|
||||
maybe_description_markdown: Some(miyhoyo_description.to_string()),
|
||||
maybe_description_rendered_html: Some(miyhoyo_description.to_string()),
|
||||
creator_user_token: Some(&user_token), // replace with actual UserToken
|
||||
creator_ip_address: "292.268.2.2",
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_last_update_user_token: Some("<p> Honkai <p>".to_string()),
|
||||
original_download_url: Some("https://civitai.com/models/95243/mihoyo-collection-honkai-impact-3rd-or-honkai-star-rail-or-genshin-impact-or-zenless-zone-zero".to_string()),
|
||||
original_filename: Some("xiawolei-v100-000019.safetensors".to_string()),
|
||||
file_size_bytes: metadata2.file_size_bytes as i32,
|
||||
file_checksum_sha2: metadata2.sha256_checksum.to_string(),
|
||||
public_bucket_hash: metadata2.bucket_details.clone().unwrap().object_hash.clone(),
|
||||
maybe_public_bucket_prefix: Some(metadata2.bucket_details.clone().unwrap().prefix),
|
||||
maybe_public_bucket_extension: Some(metadata2.bucket_details.clone().unwrap().suffix),
|
||||
version: 2,
|
||||
mysql_pool: &mysql_pool, // replace with actual MySqlPool
|
||||
};
|
||||
|
||||
let weights3 = CreateModelWeightsArgs {
|
||||
token: &model_weight_token3, // replace with actual ModelWeightToken
|
||||
weights_type: WeightsType::StableDiffusion15, // replace with actual WeightsType
|
||||
weights_category: WeightsCategory::ImageGeneration, // replace with actual WeightsCategory
|
||||
title: "z-vae".to_string(),
|
||||
maybe_description_markdown: Some(sd_vae_description.to_string()),
|
||||
maybe_description_rendered_html: Some("<p>Description</p>".to_string()),
|
||||
creator_user_token: Some(&user_token), // replace with actual UserToken
|
||||
creator_ip_address: "192.168.1.1",
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_last_update_user_token: Some("Last Update User Token".to_string()),
|
||||
original_download_url: Some("https://civitai.com/models/97653/z-vae".to_string()),
|
||||
original_filename: Some("zVae_v20.safetensors".to_string()),
|
||||
file_size_bytes: metadata3.file_size_bytes as i32,
|
||||
file_checksum_sha2: metadata3.sha256_checksum.to_string(),
|
||||
public_bucket_hash: metadata3.bucket_details.clone().unwrap().object_hash,
|
||||
maybe_public_bucket_prefix: Some(metadata3.bucket_details.clone().unwrap().prefix),
|
||||
maybe_public_bucket_extension: Some(metadata3.bucket_details.clone().unwrap().suffix),
|
||||
version: 1,
|
||||
mysql_pool: &mysql_pool, // replace with actual MySqlPool
|
||||
};
|
||||
|
||||
create_weight(weights1).await?;
|
||||
create_weight(weights2).await?;
|
||||
create_weight(weights3).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn seed_workflows_for_testing_inference(mysql_pool: &Pool<MySql>, user_token: UserToken) -> AnyhowResult<()>{
|
||||
let model_weight_token4 = ModelWeightToken::generate_for_testing_and_dev_seeding_never_use_in_production_seriously();
|
||||
let mut path_to_comfy = get_seed_tool_data_root();
|
||||
path_to_comfy.push("models/workflows/comfyui/test-workflow.json");
|
||||
let remote_cloud_file_client = RemoteCloudFileClient::get_remote_cloud_file_client().await?;
|
||||
let comfy_weights_descriptor = Box::new(WeightsWorkflowDescriptor {});
|
||||
let metadata4 = remote_cloud_file_client.upload_file(comfy_weights_descriptor,path_to_comfy.as_path().to_str().unwrap()).await?;
|
||||
let weights4 = CreateModelWeightsArgs {
|
||||
token: &model_weight_token4, // replace with actual ModelWeightToken
|
||||
weights_type: WeightsType::ComfyUi, // replace with actual WeightsType
|
||||
weights_category: WeightsCategory::WorkflowConfig, // replace with actual WeightsCategory
|
||||
title: "comfy-test-workflow".to_string(),
|
||||
maybe_description_markdown: Some("Test workflow for ComfyUI".to_string()),
|
||||
maybe_description_rendered_html: Some("<p>Description</p>".to_string()),
|
||||
creator_user_token: Some(&user_token), // replace with actual UserToken
|
||||
creator_ip_address: "192.168.1.1",
|
||||
creator_set_visibility: Visibility::Public,
|
||||
maybe_last_update_user_token: Some("Last Update User Token".to_string()),
|
||||
original_download_url: Some("https://github.com/comfyanonymous/ComfyUI".to_string()),
|
||||
original_filename: Some("test-workflow.json".to_string()),
|
||||
file_size_bytes: metadata4.file_size_bytes as i32,
|
||||
file_checksum_sha2: metadata4.sha256_checksum.to_string(),
|
||||
public_bucket_hash: metadata4.bucket_details.clone().unwrap().object_hash,
|
||||
maybe_public_bucket_prefix: Some(metadata4.bucket_details.clone().unwrap().prefix),
|
||||
maybe_public_bucket_extension: Some(metadata4.bucket_details.clone().unwrap().suffix),
|
||||
version: 1,
|
||||
mysql_pool: &mysql_pool, // replace with actual MySqlPool
|
||||
};
|
||||
create_weight(weights4).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn seed_weights_for_user_token(
|
||||
mysql_pool: &Pool<MySql>,
|
||||
user_token: UserToken
|
||||
@@ -630,6 +1016,7 @@ pub async fn original_seed_weights(mysql_pool: &Pool<MySql>, _user_token: UserTo
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
|
||||
info!("Seeding weights...");
|
||||
|
||||
@@ -642,7 +1029,10 @@ pub async fn seed_weights(mysql_pool: &Pool<MySql>) -> AnyhowResult<()> {
|
||||
|
||||
//original_seed_weights(mysql_pool,user_token).await?;
|
||||
//seed_weights_for_user_token(mysql_pool, user_token).await?;
|
||||
seed_weights_for_paging(mysql_pool,user_token).await?;
|
||||
|
||||
//seed_weights_for_paging(mysql_pool,user_token).await?;
|
||||
// seed_weights_for_testing_inference(mysql_pool,user_token).await?;
|
||||
//println!("TESTING DOWLOAD");
|
||||
//test_seed_weights_files().await?;
|
||||
seed_workflows_for_testing_inference(mysql_pool,user_token).await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -226,3 +226,5 @@ async fn seed_file_to_bucket(
|
||||
maybe_bucket_extension: maybe_bucket_extension.map(|s| s.to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::Parser;
|
||||
use strum::{EnumCount, EnumString, IntoEnumIterator};
|
||||
use strum::EnumIter;
|
||||
|
||||
use errors::{anyhow, AnyhowResult};
|
||||
|
||||
pub struct ParsedArgs {
|
||||
pub action: Action,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, EnumIter, EnumCount, EnumString, strum::Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Action {
|
||||
/// Migrate VC
|
||||
MigrateVoiceConversion,
|
||||
/// Migrate TTS
|
||||
MigrateTts,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name="migration-tool")]
|
||||
pub struct Args {
|
||||
#[arg(name="action", long="action", help="action to take", required=true)]
|
||||
action: String,
|
||||
}
|
||||
|
||||
pub fn parse_cli_args() -> AnyhowResult<ParsedArgs> {
|
||||
let args = Args::parse();
|
||||
|
||||
Ok(ParsedArgs {
|
||||
action: action_from_str(&args.action)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn action_from_str(value: &str) -> AnyhowResult<Action> {
|
||||
let action = Action::from_str(value)
|
||||
.map_err(|err| {
|
||||
let choices = Action::iter()
|
||||
.map(|e| e.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
anyhow!("parse error: {:?}, provided: \"{}\" choices: {:?}", err, value, choices)
|
||||
})?;
|
||||
Ok(action)
|
||||
}
|
||||
@@ -5,17 +5,21 @@
|
||||
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use log::info;
|
||||
use sqlx::{MySql, Pool};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
|
||||
use cloud_storage::bucket_client::BucketClient;
|
||||
use config::shared_constants::DEFAULT_RUST_LOG;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
use crate::cli_args::{Action, parse_cli_args};
|
||||
use crate::deps::Deps;
|
||||
use crate::migrations::tts_models_to_weights::migrate::migrate_tts_to_weights;
|
||||
use crate::migrations::voice_conversion_to_weights::migrate::migrate_voice_conversion_to_weights;
|
||||
|
||||
pub mod cli_args;
|
||||
pub mod deps;
|
||||
pub mod migrations;
|
||||
|
||||
@@ -40,10 +44,20 @@ pub async fn main() -> AnyhowResult<()> {
|
||||
bucket_production_private: get_bucket_client("PRODUCTION_PRIVATE")?,
|
||||
};
|
||||
|
||||
migrate_voice_conversion_to_weights(&deps).await?;
|
||||
let args = parse_cli_args()?;
|
||||
|
||||
match args.action {
|
||||
Action::MigrateVoiceConversion => {
|
||||
migrate_voice_conversion_to_weights(&deps).await?;
|
||||
}
|
||||
Action::MigrateTts => {
|
||||
migrate_tts_to_weights(&deps).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_mysql(env_var_name: &str) -> AnyhowResult<Pool<MySql>> {
|
||||
info!("Connecting to MySQL {env_var_name}...");
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod tts_models_to_weights;
|
||||
pub mod voice_conversion_to_weights;
|
||||
@@ -0,0 +1,47 @@
|
||||
use tempdir::TempDir;
|
||||
|
||||
use buckets::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use cloud_storage::bucket_path_unifier::BucketPathUnifier;
|
||||
use errors::AnyhowResult;
|
||||
use filesys::safe_delete_temp_directory::safe_delete_temp_directory;
|
||||
use filesys::safe_delete_temp_file::safe_delete_temp_file;
|
||||
use hashing::sha256::sha256_hash_file::sha256_hash_file;
|
||||
use mysql_queries::queries::model_weights::migration::upsert_model_weight_from_tts_model::CopiedTtsFileData;
|
||||
use mysql_queries::queries::tts::tts_models::migration::list_whole_tts_models_using_cursor::WholeTtsModelRecord;
|
||||
|
||||
use crate::deps::Deps;
|
||||
|
||||
pub async fn copy_cloud_files(model: &WholeTtsModelRecord, deps: &Deps) -> AnyhowResult<CopiedTtsFileData> {
|
||||
let copied_file_data = copy_model(model, deps).await?;
|
||||
Ok(copied_file_data)
|
||||
}
|
||||
|
||||
async fn copy_model(model: &WholeTtsModelRecord, deps: &Deps) -> AnyhowResult<CopiedTtsFileData> {
|
||||
let bucket_path_unifier = BucketPathUnifier::default_paths();
|
||||
|
||||
let old_model_bucket_path = bucket_path_unifier.tts_synthesizer_path(&model.private_bucket_hash);
|
||||
|
||||
// TODO(bt,2023-12-19): Probably faster to stream between buckets, but whatever.
|
||||
let temp_dir = TempDir::new("model_transfer")?;
|
||||
let model_temp_fs_path = temp_dir.path().join("model.bin");
|
||||
|
||||
deps.bucket_production_private.download_file_to_disk(&old_model_bucket_path, &model_temp_fs_path).await?;
|
||||
|
||||
let file_checksum = sha256_hash_file(&model_temp_fs_path)?;
|
||||
|
||||
let new_model_bucket_path = WeightFileBucketPath::generate_for_tt2_model();
|
||||
|
||||
deps.bucket_production_public.upload_filename_with_content_type(
|
||||
&new_model_bucket_path.get_full_object_path_str(),
|
||||
&model_temp_fs_path,
|
||||
"application/octet-stream").await?;
|
||||
|
||||
safe_delete_temp_file(&model_temp_fs_path);
|
||||
safe_delete_temp_directory(&temp_dir);
|
||||
|
||||
Ok(CopiedTtsFileData {
|
||||
bucket_path: new_model_bucket_path,
|
||||
file_sha_hash: file_checksum,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use log::{info, warn};
|
||||
|
||||
use buckets::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
use errors::AnyhowResult;
|
||||
use mysql_queries::queries::model_weights::get_weight::get_weight_by_token;
|
||||
use mysql_queries::queries::model_weights::migration::upsert_model_weight_from_tts_model::{CopiedTtsFileData, upsert_model_weight_from_tts_model};
|
||||
use mysql_queries::queries::tts::tts_models::migration::list_whole_tts_models_using_cursor::{list_whole_tts_models_using_cursor, WholeTtsModelRecord};
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use crate::deps::Deps;
|
||||
use crate::migrations::tts_models_to_weights::copy_cloud_files::copy_cloud_files;
|
||||
|
||||
const PAGE_SIZE: u64 = 10;
|
||||
|
||||
// TODO(bt,2024-01-15): This hasn't been fully vetted / tested. Do not run until it's combed over.
|
||||
|
||||
pub async fn migrate_tts_to_weights(deps: &Deps) -> AnyhowResult<()> {
|
||||
|
||||
let mut cursor = 0;
|
||||
|
||||
loop {
|
||||
info!("Querying {PAGE_SIZE} models at cursor = {cursor}");
|
||||
|
||||
let results
|
||||
= list_whole_tts_models_using_cursor(&deps.mysql_production, PAGE_SIZE, cursor).await?;
|
||||
|
||||
if results.is_empty() {
|
||||
warn!("No more results found; exiting.");
|
||||
break;
|
||||
}
|
||||
|
||||
for result in results.iter() {
|
||||
println!("\n\nmigrating over result {:?} : {:?} ...", result.token, result);
|
||||
copy_model_record_and_bucket_files(result, &deps).await?;
|
||||
}
|
||||
|
||||
if let Some(last_id) = results.last().map(|result| result.id) {
|
||||
cursor = last_id as u64;
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn copy_model_record_and_bucket_files(record: &WholeTtsModelRecord, deps: &Deps) -> AnyhowResult<()> {
|
||||
let mut maybe_copied_data = None;
|
||||
|
||||
match &record.maybe_migration_new_model_weights_token {
|
||||
None => {
|
||||
info!("Copying bucket files for record {:?} ...", record.token);
|
||||
let result = copy_cloud_files(record, &deps).await?;
|
||||
maybe_copied_data = Some(result);
|
||||
}
|
||||
Some(token) => {
|
||||
info!("Existing migrated record; skipping cloud bucket copy...");
|
||||
maybe_copied_data = lookup_bucket_details_from_record(token, &deps).await?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(copied_data) = &maybe_copied_data {
|
||||
info!("Upserting records...");
|
||||
upsert_model_weight_from_tts_model(record, &deps.mysql_production, copied_data).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Look up the bucket storage details from a previously-migrated record
|
||||
async fn lookup_bucket_details_from_record(model_weight_token: &ModelWeightToken, deps: &Deps) -> AnyhowResult<Option<CopiedTtsFileData>> {
|
||||
let maybe_model_weight_record =
|
||||
get_weight_by_token(model_weight_token, true, &deps.mysql_production).await?;
|
||||
|
||||
let model_weight_record = match maybe_model_weight_record {
|
||||
None => return Ok(None),
|
||||
Some(record) => record,
|
||||
};
|
||||
|
||||
let bucket_path = match model_weight_record.weights_type {
|
||||
WeightsType::Tacotron2 => WeightFileBucketPath::tt2_model_file_from_object_hash(&model_weight_record.public_bucket_hash),
|
||||
_ => return Ok(None), // NB: SVC, RVC, Stable Diffusion, etc. aren't valid for TTS migration
|
||||
};
|
||||
|
||||
Ok(Some(CopiedTtsFileData {
|
||||
bucket_path,
|
||||
file_sha_hash: model_weight_record.file_checksum_sha2,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod copy_cloud_files;
|
||||
pub mod migrate;
|
||||
@@ -19,7 +19,6 @@ pub trait BucketOrchestrationCore {
|
||||
bytes: &[u8],
|
||||
content_type: &str,
|
||||
is_public: bool) -> AnyhowResult<()>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use crate::remote_file_manager::remote_cloud_bucket_details::RemoteCloudBucketDetails;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileMetaData {
|
||||
pub file_size_bytes: u64,
|
||||
pub sha256_checksum: String,
|
||||
pub mimetype: String
|
||||
pub mimetype: String,
|
||||
pub bucket_details: Option<RemoteCloudBucketDetails>
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::remote_file_manager::file_descriptor::FileDescriptor;
|
||||
// TODO ASK BRANDON WHAT path should this be?
|
||||
const MEDIA_FILE_DIRECTORY: &str = "/media";
|
||||
|
||||
pub struct MediaImagePngDescriptor;
|
||||
|
||||
impl FileDescriptor for MediaImagePngDescriptor {
|
||||
fn remote_directory_path(&self) -> &str {
|
||||
MEDIA_FILE_DIRECTORY
|
||||
}
|
||||
fn get_suffix(&self)->String {
|
||||
"png".to_string()
|
||||
}
|
||||
|
||||
fn get_prefix(&self)->String {
|
||||
"image".to_string()
|
||||
}
|
||||
|
||||
fn is_public(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
use crate::remote_file_manager::weights_descriptor::{self};
|
||||
|
||||
use super::file_descriptor::FileDescriptor;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RemoteCloudBucketDetails {
|
||||
pub object_hash: String,
|
||||
pub prefix: String,
|
||||
|
||||
+24
-10
@@ -12,17 +12,13 @@ use crate::remote_file_manager::remote_cloud_bucket_details::RemoteCloudBucketDe
|
||||
use super::file_descriptor::FileDescriptor;
|
||||
use super::file_meta_data::FileMetaData;
|
||||
|
||||
|
||||
pub struct RemoteCloudFileClient {
|
||||
bucket_orchestration_client: Box<dyn BucketOrchestrationCore>
|
||||
}
|
||||
|
||||
impl RemoteCloudFileClient {
|
||||
pub fn new(bucket_orchestration_client: Box<dyn BucketOrchestrationCore>) -> Self {
|
||||
Self {
|
||||
bucket_orchestration_client
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_remote_cloud_file_client() -> AnyhowResult<Self> {
|
||||
let bucket_orchestration = match BucketOrchestration::new_bucket_client_from_existing_env() {
|
||||
Ok(client) => client,
|
||||
@@ -36,6 +32,13 @@ impl RemoteCloudFileClient {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(bucket_orchestration_client: Box<dyn BucketOrchestrationCore>) -> Self {
|
||||
Self {
|
||||
bucket_orchestration_client
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn download_file(&self, remote_cloud_bucket_details:RemoteCloudBucketDetails, to_system_file_path:String) -> AnyhowResult<()> {
|
||||
let file_descriptor = remote_cloud_bucket_details.file_descriptor_from_bucket_details();
|
||||
let file_bucket_directory = FileBucketDirectory::from_existing_bucket_details(remote_cloud_bucket_details);
|
||||
@@ -53,17 +56,26 @@ impl RemoteCloudFileClient {
|
||||
println!("Reading media file: {:?}", from_system_file_path);
|
||||
// get meta data
|
||||
let bytes = file_read_bytes(from_system_file_path)?;
|
||||
let result = Self::get_file_meta_data(from_system_file_path)?;
|
||||
let mut result = Self::get_file_meta_data(from_system_file_path)?;
|
||||
let is_public = file_descriptor.is_public();
|
||||
|
||||
let suffix = file_descriptor.get_suffix().clone();
|
||||
let prefix = file_descriptor.get_prefix().clone();
|
||||
|
||||
let directory = FileBucketDirectory::generate_new(
|
||||
file_descriptor
|
||||
);
|
||||
|
||||
result.bucket_details = Some(RemoteCloudBucketDetails {
|
||||
object_hash: directory.get_file_object_hash().to_string(),
|
||||
suffix,
|
||||
prefix,
|
||||
});
|
||||
|
||||
println!("Uploading media file to bucket path: {:?}",directory.get_full_remote_cloud_file_path());
|
||||
|
||||
self.bucket_orchestration_client.upload_file_with_content_type_process(
|
||||
&directory.get_remote_cloud_base_directory(),
|
||||
&directory.get_full_remote_cloud_file_path(),
|
||||
bytes.as_ref(),
|
||||
result.mimetype.as_ref(),
|
||||
is_public
|
||||
@@ -83,7 +95,8 @@ impl RemoteCloudFileClient {
|
||||
Ok(FileMetaData {
|
||||
file_size_bytes,
|
||||
sha256_checksum,
|
||||
mimetype: mimetype.to_string()
|
||||
mimetype: mimetype.to_string(),
|
||||
bucket_details: None
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -125,7 +138,8 @@ mod tests {
|
||||
is_public: bool) -> AnyhowResult<()> {
|
||||
println!("Upload File to Disk");
|
||||
println!("{}",object_name);
|
||||
assert_eq!(object_name,String::from("/weights/2/y/q/m/2/2yqm2f1bamh88seyd690h9v24apgezhr/loRA_2yqm2f1bamh88seyd690h9v24apgezhr.safetensors"));
|
||||
// this is random you have to just check the outputs
|
||||
//assert_eq!(object_name,String::from("/weights/2/y/q/m/2/2yqm2f1bamh88seyd690h9v24apgezhr/loRA_2yqm2f1bamh88seyd690h9v24apgezhr.safetensors"));
|
||||
println!("ContentType:{}",content_type);
|
||||
println!("{}",is_public);
|
||||
assert_eq!(is_public,true);
|
||||
|
||||
@@ -3,7 +3,6 @@ use super::file_descriptor::FileDescriptor;
|
||||
pub struct WeightsLoRADescriptor;
|
||||
|
||||
const REMOTE_FILE_DIRECTORY: &str = "/weights";
|
||||
|
||||
impl FileDescriptor for WeightsLoRADescriptor {
|
||||
fn remote_directory_path(&self) -> &str {
|
||||
REMOTE_FILE_DIRECTORY
|
||||
@@ -26,6 +25,7 @@ impl FileDescriptor for WeightsLoRADescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct WeightsSD15Descriptor;
|
||||
|
||||
impl FileDescriptor for WeightsSD15Descriptor {
|
||||
@@ -166,6 +166,26 @@ impl FileDescriptor for crate::remote_file_manager::weights_descriptor::WeightsV
|
||||
}
|
||||
|
||||
// This will be ensure that the right bucket is picked
|
||||
fn is_public(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WeightsWorkflowDescriptor;
|
||||
|
||||
impl FileDescriptor for WeightsWorkflowDescriptor {
|
||||
fn remote_directory_path(&self) -> &str {
|
||||
REMOTE_FILE_DIRECTORY
|
||||
}
|
||||
|
||||
fn get_suffix(&self) -> String {
|
||||
"json".to_string()
|
||||
}
|
||||
|
||||
fn get_prefix(&self) -> String {
|
||||
"workflow".to_string()
|
||||
}
|
||||
|
||||
fn is_public(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -57,6 +57,59 @@ impl GoogleDriveDownloadCommand {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download_file_with_file_name(&self,
|
||||
download_url: &str,
|
||||
temp_dir: &TempDir,
|
||||
file_name:&str) -> AnyhowResult<String>
|
||||
{
|
||||
let temp_dir_path = temp_dir.path()
|
||||
.to_str()
|
||||
.unwrap_or("/tmp")
|
||||
.to_string();
|
||||
|
||||
let temp_filename = format!("{}/{}", temp_dir_path, file_name);
|
||||
|
||||
info!("Downloading {} to: {}", download_url, temp_filename);
|
||||
|
||||
let mut command = format!("{} --url \"{}\" --output_filename {}",
|
||||
&self.download_script,
|
||||
download_url,
|
||||
&temp_filename);
|
||||
|
||||
if let Some(venv_activation_script) = self.maybe_venv_activation_script.as_deref() {
|
||||
// NB: "." is source for non-bash shells
|
||||
command = format!(". {} && {}",
|
||||
venv_activation_script,
|
||||
&command);
|
||||
}
|
||||
|
||||
if let Some(change_to_directory) = self.maybe_change_to_directory.as_deref() {
|
||||
command = format!("cd {} && {}",
|
||||
change_to_directory,
|
||||
&command);
|
||||
}
|
||||
|
||||
if let Some(docker_options) = self.maybe_docker_options.as_ref() {
|
||||
command = docker_options.to_command_string(&command);
|
||||
}
|
||||
|
||||
info!("Running command: {}", command);
|
||||
|
||||
let result = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
.output()?;
|
||||
|
||||
info!("Downloader Result: {:?}", result);
|
||||
|
||||
if !result.status.success() {
|
||||
let reason = String::from_utf8(result.stderr).unwrap_or("UNKNOWN".to_string());
|
||||
return Err(anyhow!("Failure to execute command: {:?}", reason))
|
||||
}
|
||||
|
||||
Ok(temp_filename)
|
||||
}
|
||||
|
||||
/// Download file from Google Drive into the `TempDir`.
|
||||
/// Return the local filesystem filename.
|
||||
pub async fn download_file(&self,
|
||||
|
||||
@@ -59,6 +59,8 @@ pub fn add_fakeyou(cors: Cors, is_production: bool) -> Cors {
|
||||
// FakeYou (Staging)
|
||||
.allowed_origin("http://staging.fakeyou.com")
|
||||
.allowed_origin("https://staging.fakeyou.com")
|
||||
// FakeYou (Netlify Staging / Production)
|
||||
.allowed_origin("https://feature-mvp--fakeyou.netlify.app")
|
||||
} else {
|
||||
cors
|
||||
// FakeYou (Development)
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
pub mod text_to_speech;
|
||||
pub mod voice_conversion;
|
||||
@@ -0,0 +1,155 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::MySql;
|
||||
use sqlx::pool::PoolConnection;
|
||||
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
use mysql_queries::queries::model_weights::list::list_model_weights_for_text_to_speech::{list_model_weights_for_text_to_speech, ModelWeightForTts};
|
||||
use mysql_queries::queries::tts::tts_models::list_tts_models::{list_tts_models_with_connection, TtsModelRecordForList};
|
||||
|
||||
/// List TTS models
|
||||
/// This is for the tts model list page.
|
||||
/// Since we're listing, we have to use a flag to determine which query to perform.
|
||||
pub async fn list_tts_models_for_migration(
|
||||
mysql_connection: &mut PoolConnection<MySql>,
|
||||
use_weights_table: bool,
|
||||
) -> AnyhowResult<Vec<TtsModelForList>> {
|
||||
// NB: This is temporary migration code as we switch from the `tts_models` table to the `model_weights` table.
|
||||
if use_weights_table {
|
||||
let models = list_model_weights_for_text_to_speech(
|
||||
mysql_connection).await?;
|
||||
|
||||
Ok(models.into_iter()
|
||||
.map(|model| TtsModelForList::ModelWeight(model))
|
||||
.collect())
|
||||
|
||||
} else {
|
||||
let models = list_tts_models_with_connection(
|
||||
mysql_connection, None, false).await?;
|
||||
|
||||
Ok(models.into_iter()
|
||||
.map(|model| TtsModelForList::LegacyTts(model))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Union over the legacy table and the new table to support an easier migration.
|
||||
/// This enum can hold a record of either type and present a unified accessor interface.
|
||||
#[derive(Clone)]
|
||||
pub enum TtsModelForList {
|
||||
/// Old type from the `tts_models` table, on the way out
|
||||
LegacyTts(TtsModelRecordForList),
|
||||
/// New type, replacing the `tts_models` table.
|
||||
ModelWeight(ModelWeightForTts),
|
||||
}
|
||||
|
||||
impl TtsModelForList {
|
||||
pub fn token(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.model_token.as_str(),
|
||||
TtsModelForList::ModelWeight(ref model) => model.token.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.title,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.title,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ietf_language_tag(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.ietf_language_tag,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.ietf_language_tag,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ietf_primary_language_subtag(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.ietf_primary_language_subtag,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.ietf_primary_language_subtag,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_user_token(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.creator_user_token,
|
||||
TtsModelForList::ModelWeight(ref model) => model.creator_user_token.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_username(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.creator_username,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.creator_username,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_display_name(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.creator_display_name,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.creator_display_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_gravatar_hash(&self) -> &str {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.creator_gravatar_hash,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.creator_gravatar_hash,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_set_visibility(&self) -> Visibility{
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.creator_set_visibility,
|
||||
TtsModelForList::ModelWeight(ref model) => model.creator_set_visibility,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn created_at(&self) -> &DateTime<Utc> {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.created_at,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.created_at,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updated_at(&self) -> &DateTime<Utc> {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => &model.updated_at,
|
||||
TtsModelForList::ModelWeight(ref model) => &model.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn is_front_page_featured(&self) -> bool {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.is_front_page_featured,
|
||||
TtsModelForList::ModelWeight(ref _model) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_positive_count(&self) -> u32 {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.user_ratings_positive_count,
|
||||
TtsModelForList::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_negative_count(&self) -> u32 {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.user_ratings_negative_count,
|
||||
TtsModelForList::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_total_count(&self) -> u32 {
|
||||
match self {
|
||||
TtsModelForList::LegacyTts(ref model) => model.user_ratings_total_count,
|
||||
TtsModelForList::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod list_tts_models_for_migration;
|
||||
@@ -67,6 +67,7 @@ impl VcModelForList {
|
||||
WeightsType::Tacotron2 => None,
|
||||
WeightsType::LoRA => None,
|
||||
WeightsType::VallE => None,
|
||||
WeightsType::ComfyUi => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ impl VcModel {
|
||||
WeightsType::Tacotron2 => VcModelType::Invalid,
|
||||
WeightsType::LoRA => VcModelType::Invalid,
|
||||
WeightsType::VallE => VcModelType::Invalid,
|
||||
WeightsType::ComfyUi => VcModelType::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ impl VcModelLite {
|
||||
WeightsType::HifiganTacotron2 => None, // NB: Not used directly in inference. Included by other models.
|
||||
WeightsType::LoRA => None, // NB: not used directly in inference. Included in other models.
|
||||
WeightsType::VallE => None, // TODO(bt,2023-12-18): Does this mean speaker weights?
|
||||
WeightsType::ComfyUi => None, // NB: not used directly in inference. Included in other models.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +98,7 @@ impl VcModelLite {
|
||||
WeightsType::HifiganTacotron2 => None, // NB: Not used directly in inference. Included by other models.
|
||||
WeightsType::LoRA => None, // NB: not used directly in inference. Included in other models.
|
||||
WeightsType::VallE => None, // TODO(bt,2023-12-18): Does this mean speaker weights?
|
||||
WeightsType::ComfyUi => None, // NB: not used directly in inference. Included in other models.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ path = "src/lib.rs"
|
||||
|
||||
# Internal
|
||||
buckets = { path = "../../_types/buckets" }
|
||||
composite_identifiers = { path = "../../_types/composite_identifiers" }
|
||||
config = { path = "../deprecated/config" }
|
||||
container_common = { path = "../deprecated/container_common" }
|
||||
enums = { path = "../../_types/enums" }
|
||||
|
||||
+56
-3
@@ -1,13 +1,13 @@
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
use crate::payloads::generic_inference_args::image_generation_payload::StableDiffusionArgs;
|
||||
use crate::payloads::generic_inference_args::lipsync_payload::LipsyncArgs;
|
||||
use crate::payloads::generic_inference_args::mocap_payload::MocapArgs;
|
||||
use crate::payloads::generic_inference_args::tts_payload::TTSArgs;
|
||||
use crate::payloads::generic_inference_args::videofilter_payload::{RerenderArgs};
|
||||
use crate::payloads::generic_inference_args::videofilter_payload::RerenderArgs;
|
||||
use crate::payloads::generic_inference_args::workflow_payload::WorkflowArgs;
|
||||
|
||||
|
||||
/// Used to encode extra state for the `generic_inference_jobs` table.
|
||||
/// This should act somewhat like a serialized protobuf stored inside a record.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@@ -43,6 +43,10 @@ pub enum InferenceCategoryAbbreviated {
|
||||
#[serde(alias = "video_filter")]
|
||||
VideoFilter,
|
||||
|
||||
#[serde(rename = "ig")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
|
||||
#[serde(alias = "image_generation")]
|
||||
ImageGeneration,
|
||||
|
||||
#[serde(rename = "mc")] // NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
|
||||
#[serde(alias = "mocap")]
|
||||
Mocap,
|
||||
@@ -103,6 +107,9 @@ pub enum PolymorphicInferenceArgs {
|
||||
/// Rerender a video. (Short name to save space when serializing.)
|
||||
Rr(RerenderArgs),
|
||||
|
||||
/// Image generation. (Short name to save space when serializing.)
|
||||
Ig(StableDiffusionArgs),
|
||||
|
||||
// Mocap (Short name to save space when serializing.)
|
||||
Mc(MocapArgs),
|
||||
|
||||
@@ -110,7 +117,6 @@ pub enum PolymorphicInferenceArgs {
|
||||
Wf(WorkflowArgs)
|
||||
}
|
||||
|
||||
|
||||
impl GenericInferenceArgs {
|
||||
|
||||
pub fn from_json(json: &str) -> AnyhowResult<Self> {
|
||||
@@ -129,6 +135,7 @@ impl InferenceCategoryAbbreviated {
|
||||
InferenceCategory::TextToSpeech => Self::TextToSpeech,
|
||||
InferenceCategory::VoiceConversion => Self::VoiceConversion,
|
||||
InferenceCategory::VideoFilter => Self::VideoFilter,
|
||||
InferenceCategory::ImageGeneration => Self::ImageGeneration,
|
||||
InferenceCategory::Mocap => Self::Mocap,
|
||||
InferenceCategory::Workflow => Self::Workflow,
|
||||
}
|
||||
@@ -140,6 +147,7 @@ impl InferenceCategoryAbbreviated {
|
||||
Self::TextToSpeech => InferenceCategory::TextToSpeech,
|
||||
Self::VoiceConversion => InferenceCategory::VoiceConversion,
|
||||
Self::VideoFilter => InferenceCategory::VideoFilter,
|
||||
Self::ImageGeneration =>InferenceCategory::ImageGeneration,
|
||||
Self::Mocap => InferenceCategory::Mocap,
|
||||
Self::Workflow => InferenceCategory::Workflow,
|
||||
}
|
||||
@@ -148,7 +156,10 @@ impl InferenceCategoryAbbreviated {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use tokens::tokens::{media_files::MediaFileToken, model_weights::ModelWeightToken};
|
||||
|
||||
use crate::payloads::generic_inference_args::generic_inference_args::{FundamentalFrequencyMethodForJob, GenericInferenceArgs, InferenceCategoryAbbreviated, PolymorphicInferenceArgs};
|
||||
use crate::payloads::generic_inference_args::image_generation_payload::StableDiffusionArgs;
|
||||
use crate::payloads::generic_inference_args::lipsync_payload::{LipsyncAnimationAudioSource, LipsyncAnimationImageSource, LipsyncArgs};
|
||||
use crate::payloads::generic_inference_args::tts_payload::TTSArgs;
|
||||
|
||||
@@ -197,6 +208,48 @@ mod tests {
|
||||
assert!(json.len() < 1000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typical_image_gen_args_serialize() {
|
||||
|
||||
let video_media_token = MediaFileToken("video_media_token".to_string());
|
||||
let image_media_token = MediaFileToken("image_media_token".to_string());
|
||||
let sd_model_token = ModelWeightToken("sd_model_token".to_string());
|
||||
let lora_model_token = ModelWeightToken("lora_model_token".to_string());
|
||||
|
||||
let prompt = "prompt".to_string();
|
||||
let a_prompt = "a_prompt".to_string();
|
||||
let n_prompt = "n_prompt".to_string();
|
||||
let seed = 1;
|
||||
let upload_path = "upload_path".to_string();
|
||||
let lora_upload_path = "lora_upload_path".to_string();
|
||||
let checkpoint = "checkpoint".to_string();
|
||||
let type_of_inference = "type_of_inference".to_string();
|
||||
let args = GenericInferenceArgs {
|
||||
inference_category: Some(InferenceCategoryAbbreviated::ImageGeneration),
|
||||
args: Some(PolymorphicInferenceArgs::Ig(StableDiffusionArgs {
|
||||
maybe_sd_model_token: Some(sd_model_token),
|
||||
maybe_lora_model_token: Some(lora_model_token),
|
||||
maybe_sampler: Some("sampler".to_string()),
|
||||
maybe_height: Some(512),
|
||||
maybe_width: Some(512),
|
||||
maybe_cfg_scale: Some(7),
|
||||
maybe_prompt: Some(prompt),
|
||||
maybe_n_prompt: Some(n_prompt),
|
||||
maybe_batch_count: Some(1),
|
||||
maybe_number_of_samples: Some(25),
|
||||
maybe_seed: Some(seed),
|
||||
maybe_upload_path: Some(upload_path),
|
||||
maybe_lora_upload_path: Some(lora_upload_path),
|
||||
type_of_inference,
|
||||
description: Some("Option".to_string()),
|
||||
name: Some("Model Name".to_string())
|
||||
})),
|
||||
};
|
||||
|
||||
let json = serde_json::ser::to_string(&args).unwrap();
|
||||
assert_eq!(json, r#"{"cat":"ig","args":{"Ig":{"vs":"video_media_token","is":"image_media_token","sd":"sd_model_token","lm":"lora_model_token","p":"prompt","ap":"a_prompt","np":"n_prompt","se":1,"mu":"upload_path","lu":"lora_upload_path"}}}"#.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typical_voice_conversion_args_serialize() {
|
||||
let args = GenericInferenceArgs {
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
/// Video sources can be one of several:
|
||||
/// - F: media_files (todo)
|
||||
/// - U: media_uploads (legacy)
|
||||
|
||||
/// For image to image we probably want images
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum StableDiffusionSource {
|
||||
// NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
|
||||
/// Media File Token (media_files table)
|
||||
/// Serde cannot yet rename enum variants.
|
||||
F(String),
|
||||
|
||||
// NB: DO NOT CHANGE. It could break live jobs. Renamed to be fewer bytes.
|
||||
/// Media Upload Token (media_uploads table)
|
||||
/// Serde cannot yet rename enum variants.
|
||||
U(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct StableDiffusionArgs {
|
||||
|
||||
#[serde(rename = "sd")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_sd_model_token: Option<ModelWeightToken>,
|
||||
|
||||
#[serde(rename = "lm")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_lora_model_token: Option<ModelWeightToken>,
|
||||
|
||||
#[serde(rename = "w")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_width: Option<i32>,
|
||||
|
||||
#[serde(rename = "h")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_height: Option<i32>,
|
||||
|
||||
#[serde(rename = "s")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_sampler: Option<String>,
|
||||
|
||||
#[serde(rename = "p")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_prompt: Option<String>,
|
||||
|
||||
#[serde(rename = "np")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_n_prompt: Option<String>,
|
||||
|
||||
#[serde(rename = "se")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_seed: Option<i64>,
|
||||
|
||||
#[serde(rename = "mu")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_upload_path: Option<String>,
|
||||
|
||||
#[serde(rename = "cf")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_cfg_scale: Option<i32>,
|
||||
|
||||
#[serde(rename = "lu")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_lora_upload_path: Option<String>,
|
||||
|
||||
#[serde(rename = "sa")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maybe_number_of_samples: Option<i32>,
|
||||
|
||||
#[serde(rename = "bc")]
|
||||
pub maybe_batch_count: Option<i32>,
|
||||
|
||||
#[serde(rename = "t")]
|
||||
pub type_of_inference: String,
|
||||
|
||||
// loRA / checkpoint description
|
||||
#[serde(rename = "de")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
// loRA / checkpoint name and description
|
||||
#[serde(rename = "na")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,6 @@ pub mod generic_inference_args;
|
||||
pub mod lipsync_payload;
|
||||
pub mod tts_payload;
|
||||
pub mod videofilter_payload;
|
||||
pub mod image_generation_payload;
|
||||
pub mod mocap_payload;
|
||||
pub mod workflow_payload;
|
||||
pub mod workflow_payload;
|
||||
@@ -1,30 +1,16 @@
|
||||
use std::collections::HashMap;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum FileSource {
|
||||
F(String),
|
||||
U(String),
|
||||
}
|
||||
|
||||
impl FileSource {
|
||||
pub fn media_file_token(token: &str) -> Self {
|
||||
FileSource::F(token.to_string())
|
||||
}
|
||||
pub fn media_upload_token(token: &str) -> Self {
|
||||
FileSource::U(token.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
enum NewValue {
|
||||
pub enum NewValue {
|
||||
String(String),
|
||||
Float(f32),
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||
pub struct WorkflowArgs {
|
||||
#[serde(rename = "sd")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
use anyhow::anyhow;
|
||||
use log::error;
|
||||
use sqlx::{MySql, QueryBuilder, Transaction};
|
||||
|
||||
use composite_identifiers::by_table::batch_generations::batch_generation_entity::BatchGenerationEntity;
|
||||
use errors::AnyhowResult;
|
||||
use tokens::tokens::batch_generations::BatchGenerationToken;
|
||||
|
||||
pub struct BatchEntry {
|
||||
pub batch_token: BatchGenerationToken,
|
||||
pub entity: BatchGenerationEntity,
|
||||
}
|
||||
|
||||
pub struct InsertBatchArgs<'a, 'b> {
|
||||
pub entries: Vec<BatchGenerationEntity>,
|
||||
pub transaction: &'a mut Transaction<'b, MySql>,
|
||||
}
|
||||
|
||||
/// Insert a list of entities into a "batch" together for grouping; returns the new batch token identifier to return
|
||||
/// to the HTTP caller.
|
||||
///
|
||||
/// NB: Calling code is responsible for rolling back the transaction if this fails.
|
||||
pub async fn insert_batch_generation_records<'a, 'b>(args: InsertBatchArgs<'a, 'b>) -> AnyhowResult<BatchGenerationToken> {
|
||||
let batch_token = BatchGenerationToken::generate();
|
||||
|
||||
let mut query_builder = QueryBuilder::new(r#"
|
||||
INSERT INTO batch_generations (token, entity_type, entity_token) VALUES
|
||||
"#);
|
||||
|
||||
for (i, entry) in args.entries.iter().enumerate() {
|
||||
let (entity_type, entity_token) = entry.get_composite_keys();
|
||||
|
||||
query_builder.push("(");
|
||||
query_builder.push_bind(&batch_token);
|
||||
query_builder.push(",");
|
||||
|
||||
query_builder.push_bind(entity_type);
|
||||
query_builder.push(",");
|
||||
|
||||
query_builder.push_bind(entity_token);
|
||||
query_builder.push(")");
|
||||
|
||||
if i < args.entries.len() - 1 {
|
||||
query_builder.push(",");
|
||||
}
|
||||
}
|
||||
|
||||
let query = query_builder.build();
|
||||
|
||||
let query_result = query.execute(&mut **args.transaction).await;
|
||||
|
||||
match query_result {
|
||||
Ok(_) => Ok(batch_token),
|
||||
Err(err) => {
|
||||
error!("Error with batch generation query: {:?}", &err);
|
||||
Err(anyhow!("model category creation error: {:?}", &err))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
|
||||
use composite_identifiers::by_table::batch_generations::batch_generation_entity::BatchGenerationEntity;
|
||||
use config::shared_constants::DEFAULT_MYSQL_CONNECTION_STRING;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
use crate::queries::batch_generations::insert_batch_generation_records::{insert_batch_generation_records, InsertBatchArgs};
|
||||
|
||||
async fn setup() -> sqlx::Pool<sqlx::MySql> {
|
||||
MySqlPoolOptions::new()
|
||||
.max_connections(3)
|
||||
.connect(&DEFAULT_MYSQL_CONNECTION_STRING).await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
let pool = setup().await;
|
||||
|
||||
let mut transaction = pool.begin().await.unwrap();
|
||||
|
||||
let entries = vec![
|
||||
BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_foo")),
|
||||
BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_bar")),
|
||||
BatchGenerationEntity::MediaFile(MediaFileToken::new_from_str("media_baz")),
|
||||
];
|
||||
|
||||
let r = insert_batch_generation_records(InsertBatchArgs {
|
||||
entries,
|
||||
transaction: &mut transaction,
|
||||
}).await;
|
||||
|
||||
transaction.commit().await.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod insert_batch_generation_records;
|
||||
@@ -179,6 +179,7 @@ fn raw_record_to_public_result(record: RawGenericInferenceJobStatus) -> GenericI
|
||||
InferenceCategory::TextToSpeech => record.maybe_tts_model_title.as_deref(),
|
||||
InferenceCategory::VoiceConversion => record.maybe_voice_conversion_model_title.as_deref(),
|
||||
InferenceCategory::VideoFilter => Some("Video Filter"),
|
||||
InferenceCategory::ImageGeneration => Some("Image Generation"),
|
||||
InferenceCategory::Mocap => Some("Mocap"),
|
||||
InferenceCategory::Workflow => Some("Workflow"),
|
||||
};
|
||||
@@ -190,6 +191,7 @@ fn raw_record_to_public_result(record: RawGenericInferenceJobStatus) -> GenericI
|
||||
InferenceCategory::TextToSpeech => (false, record.maybe_tts_public_bucket_path.as_deref()),
|
||||
InferenceCategory::VoiceConversion => (true, record.maybe_voice_conversion_public_bucket_hash.as_deref()),
|
||||
InferenceCategory::VideoFilter => (true, record.maybe_media_file_public_bucket_directory_hash.as_deref()),
|
||||
InferenceCategory::ImageGeneration => (true, record.maybe_media_file_public_bucket_directory_hash.as_deref()),
|
||||
InferenceCategory::Mocap => (true, record.maybe_media_file_public_bucket_directory_hash.as_deref()),
|
||||
InferenceCategory::Workflow => (true, record.maybe_media_file_public_bucket_directory_hash.as_deref()),
|
||||
};
|
||||
|
||||
+4
-4
@@ -18,6 +18,7 @@ pub struct InsertArgs<'a> {
|
||||
pub pool: &'a MySqlPool,
|
||||
pub job: &'a AvailableInferenceJob,
|
||||
|
||||
pub origin_model_type: MediaFileOriginModelType,
|
||||
pub maybe_mime_type: Option<&'a str>,
|
||||
pub file_size_bytes: u64,
|
||||
pub sha256_checksum: &'a str,
|
||||
@@ -65,11 +66,10 @@ pub async fn insert_media_file_from_zero_shot(
|
||||
maybe_creator_category_synthetic_id = Some(next_lipsync_id);
|
||||
}
|
||||
|
||||
// TODO: Ask if it make sense to use ONE function to do the insert
|
||||
// TODO: Ask if it make sense to use ONE function to do the insert * I agree it does .... use insert media file generic and eventually remove all this.
|
||||
// Since fill this out apart of the funtion this seems like the only thing to change.
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::ZeroShotVoice;
|
||||
const ORIGIN_MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::VallEX;
|
||||
const MEDIA_TYPE : MediaFileType = MediaFileType::Audio;
|
||||
|
||||
let record_id = {
|
||||
@@ -111,8 +111,8 @@ pub async fn insert_media_file_from_zero_shot(
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
ORIGIN_MODEL_TYPE.to_str(),
|
||||
|
||||
args.origin_model_type.to_str(),
|
||||
|
||||
MEDIA_TYPE.to_str(),
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
use anyhow::anyhow;
|
||||
use sqlx;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use enums::by_table::generic_synthetic_ids::id_category::IdCategory;
|
||||
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
|
||||
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
|
||||
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
|
||||
use enums::by_table::media_files::media_file_type::MediaFileType;
|
||||
use errors::AnyhowResult;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::weight_model_weight;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::queries::generic_inference::job::list_available_generic_inference_jobs::AvailableInferenceJob;
|
||||
use crate::queries::generic_synthetic_ids::transactional_increment_generic_synthetic_id::transactional_increment_generic_synthetic_id;
|
||||
// thought about this it seems like this can be a bit more geneneric instead of having this we can ...
|
||||
pub struct InsertArgs<'a> {
|
||||
pub pool: &'a MySqlPool,
|
||||
pub job: &'a AvailableInferenceJob,
|
||||
|
||||
pub maybe_mime_type: Option<&'a str>,
|
||||
pub file_size_bytes: u64,
|
||||
pub sha256_checksum: &'a str,
|
||||
|
||||
pub public_bucket_directory_hash: &'a str,
|
||||
pub maybe_public_bucket_prefix: Option<&'a str>,
|
||||
pub maybe_public_bucket_extension: Option<&'a str>,
|
||||
|
||||
pub is_on_prem: bool,
|
||||
|
||||
pub worker_hostname: &'a str,
|
||||
pub worker_cluster: &'a str,
|
||||
|
||||
pub maybe_creator_user_token: Option<&'a UserToken>,
|
||||
pub maybe_creator_anonymous_visitor_token: Option<&'a AnonymousVisitorTrackingToken>,
|
||||
pub creator_ip_address: &'a str,
|
||||
pub creator_set_visibility: Visibility,
|
||||
pub upload_type: UploadType,
|
||||
pub media_file_type: MediaFileType,
|
||||
pub duration_millis: u64,
|
||||
|
||||
pub media_file_origin: MediaFileOriginProductCategory,
|
||||
pub media_file_origin_product_category: MediaFileOriginProductCategory,
|
||||
pub media_file_origin_model_type: Mediafile,
|
||||
pub maybe_origin_filename: String,
|
||||
pub maybe_origin_model_token:WeightsModelToken
|
||||
}
|
||||
pub async fn insert_media_file_generic(
|
||||
args: InsertArgs<'_>
|
||||
) -> AnyhowResult<(MediaFileToken, u64)>
|
||||
{
|
||||
|
||||
let result_token = MediaFileToken::generate();
|
||||
|
||||
let mut maybe_creator_file_synthetic_id : Option<u64> = None;
|
||||
let mut maybe_creator_category_synthetic_id : Option<u64> = None;
|
||||
|
||||
let mut transaction = args.pool.begin().await?;
|
||||
|
||||
// create a user token
|
||||
if let Some(creator_user_token) = args.job.maybe_creator_user_token.as_deref() {
|
||||
let user_token = UserToken::new_from_str(creator_user_token);
|
||||
|
||||
let next_media_file_id = transactional_increment_generic_synthetic_id(
|
||||
&user_token,
|
||||
IdCategory::MediaFile,
|
||||
&mut transaction
|
||||
).await?;
|
||||
|
||||
let next_lipsync_id = transactional_increment_generic_synthetic_id(
|
||||
&user_token,
|
||||
IdCategory::ZeroShotTtsResult,
|
||||
&mut transaction
|
||||
).await?;
|
||||
|
||||
maybe_creator_file_synthetic_id = Some(next_media_file_id);
|
||||
maybe_creator_category_synthetic_id = Some(next_lipsync_id);
|
||||
}
|
||||
|
||||
// TODO: Ask if it make sense to use ONE function to do the insert * I agree it does .... use insert media file generic and eventually remove all this.
|
||||
// Since fill this out apart of the funtion this seems like the only thing to change.
|
||||
const ORIGIN_CATEGORY : MediaFileOriginCategory = MediaFileOriginCategory::Inference;
|
||||
const ORIGIN_PRODUCT_CATEGORY : MediaFileOriginProductCategory = MediaFileOriginProductCategory::ZeroShotVoice;
|
||||
const ORIGIN_MODEL_TYPE : MediaFileOriginModelType = MediaFileOriginModelType::VallEX;
|
||||
const MEDIA_TYPE : MediaFileType = MediaFileType::Audio;
|
||||
|
||||
let record_id = {
|
||||
let query_result = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO media_files
|
||||
SET
|
||||
token = ?,
|
||||
|
||||
origin_category = ?,
|
||||
origin_product_category = ?,
|
||||
maybe_origin_model_type = ?,
|
||||
|
||||
media_type = ?,
|
||||
maybe_mime_type = ?,
|
||||
file_size_bytes = ?,
|
||||
|
||||
checksum_sha2 = ?,
|
||||
|
||||
public_bucket_directory_hash = ?,
|
||||
maybe_public_bucket_prefix = ?,
|
||||
maybe_public_bucket_extension = ?,
|
||||
|
||||
maybe_creator_user_token = ?,
|
||||
maybe_creator_anonymous_visitor_token = ?,
|
||||
creator_ip_address = ?,
|
||||
|
||||
creator_set_visibility = ?,
|
||||
|
||||
maybe_creator_file_synthetic_id = ?,
|
||||
maybe_creator_category_synthetic_id = ?,
|
||||
|
||||
is_generated_on_prem = ?,
|
||||
generated_by_worker = ?,
|
||||
generated_by_cluster = ?
|
||||
|
||||
"#,
|
||||
result_token.as_str(),
|
||||
|
||||
ORIGIN_CATEGORY.to_str(),
|
||||
ORIGIN_PRODUCT_CATEGORY.to_str(),
|
||||
ORIGIN_MODEL_TYPE.to_str(),
|
||||
|
||||
MEDIA_TYPE.to_str(),
|
||||
args.maybe_mime_type,
|
||||
args.file_size_bytes,
|
||||
|
||||
args.sha256_checksum,
|
||||
|
||||
args.public_bucket_directory_hash,
|
||||
args.maybe_public_bucket_prefix,
|
||||
args.maybe_public_bucket_extension,
|
||||
|
||||
args.job.maybe_creator_user_token,
|
||||
args.job.maybe_creator_anonymous_visitor_token,
|
||||
args.job.creator_ip_address,
|
||||
|
||||
args.job.creator_set_visibility.to_str(),
|
||||
|
||||
maybe_creator_file_synthetic_id,
|
||||
maybe_creator_category_synthetic_id,
|
||||
|
||||
args.is_on_prem,
|
||||
args.worker_hostname,
|
||||
args.worker_cluster
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await;
|
||||
|
||||
let record_id = match query_result {
|
||||
Ok(res) => {
|
||||
res.last_insert_id()
|
||||
},
|
||||
Err(err) => {
|
||||
// TODO: handle better
|
||||
//transaction.rollback().await?;
|
||||
return Err(anyhow!("Mysql error: {:?}", err));
|
||||
}
|
||||
};
|
||||
|
||||
record_id
|
||||
};
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok((result_token, record_id))
|
||||
}
|
||||
@@ -30,9 +30,13 @@ pub struct MediaFileListItem {
|
||||
|
||||
pub origin_category: MediaFileOriginCategory,
|
||||
pub origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
pub maybe_origin_model_token: Option<String>,
|
||||
|
||||
// NB: The title won't be populated for `tts_models` records or non-`model_weights` records.
|
||||
pub maybe_origin_model_title: Option<String>,
|
||||
|
||||
pub media_type: MediaFileType,
|
||||
pub public_bucket_directory_hash: String,
|
||||
pub maybe_public_bucket_prefix: Option<String>,
|
||||
@@ -98,6 +102,7 @@ pub async fn list_media_files(args: ListMediaFilesArgs<'_>) -> AnyhowResult<Medi
|
||||
origin_product_category: record.origin_product_category,
|
||||
maybe_origin_model_type: record.maybe_origin_model_type,
|
||||
maybe_origin_model_token: record.maybe_origin_model_token,
|
||||
maybe_origin_model_title: record.maybe_origin_model_title,
|
||||
media_type: record.media_type,
|
||||
public_bucket_directory_hash: record.public_bucket_directory_hash,
|
||||
maybe_public_bucket_prefix: record.maybe_public_bucket_prefix,
|
||||
@@ -143,13 +148,15 @@ SELECT
|
||||
m.id,
|
||||
m.token,
|
||||
|
||||
m.media_type,
|
||||
|
||||
m.origin_category,
|
||||
m.origin_product_category,
|
||||
|
||||
m.maybe_origin_model_type,
|
||||
m.maybe_origin_model_token,
|
||||
|
||||
m.media_type,
|
||||
w.title as maybe_origin_model_title,
|
||||
|
||||
m.public_bucket_directory_hash,
|
||||
m.maybe_public_bucket_prefix,
|
||||
@@ -176,6 +183,8 @@ FROM media_files AS m
|
||||
|
||||
LEFT OUTER JOIN users AS u
|
||||
ON m.maybe_creator_user_token = u.token
|
||||
LEFT OUTER JOIN model_weights as w
|
||||
ON m.maybe_origin_model_token = w.token
|
||||
LEFT OUTER JOIN favorites as f
|
||||
ON f.entity_type = 'media_file' AND f.entity_token = m.token
|
||||
LEFT OUTER JOIN comments as c
|
||||
@@ -269,6 +278,7 @@ struct MediaFileListItemInternal {
|
||||
origin_product_category: MediaFileOriginProductCategory,
|
||||
maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
maybe_origin_model_token: Option<String>,
|
||||
maybe_origin_model_title: Option<String>,
|
||||
|
||||
media_type: MediaFileType,
|
||||
public_bucket_directory_hash: String,
|
||||
@@ -317,6 +327,7 @@ impl FromRow<'_, MySqlRow> for MediaFileListItemInternal {
|
||||
origin_product_category: MediaFileOriginProductCategory::try_from_mysql_row(row, "origin_product_category")?,
|
||||
maybe_origin_model_type: MediaFileOriginModelType::try_from_mysql_row_nullable(row, "maybe_origin_model_type")?,
|
||||
maybe_origin_model_token: row.try_get("maybe_origin_model_token")?,
|
||||
maybe_origin_model_title: row.try_get("maybe_origin_model_title")?,
|
||||
media_type: MediaFileType::try_from_mysql_row(row, "media_type")?,
|
||||
public_bucket_directory_hash: row.try_get("public_bucket_directory_hash")?,
|
||||
maybe_public_bucket_prefix: row.try_get("maybe_public_bucket_prefix")?,
|
||||
|
||||
@@ -19,9 +19,13 @@ pub struct MediaFilesByTokensRecord {
|
||||
|
||||
pub origin_category: MediaFileOriginCategory,
|
||||
pub origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
pub maybe_origin_model_token: Option<String>,
|
||||
|
||||
// NB: The title won't be populated for `tts_models` records or non-`model_weights` records.
|
||||
pub maybe_origin_model_title: Option<String>,
|
||||
|
||||
pub public_bucket_directory_hash: String,
|
||||
pub maybe_public_bucket_prefix: Option<String>,
|
||||
pub maybe_public_bucket_extension: Option<String>,
|
||||
@@ -68,9 +72,12 @@ async fn get_raw_media_files_by_tokens(
|
||||
|
||||
m.origin_category,
|
||||
m.origin_product_category,
|
||||
|
||||
m.maybe_origin_model_type,
|
||||
m.maybe_origin_model_token,
|
||||
|
||||
w.title as maybe_origin_model_title,
|
||||
|
||||
users.token as maybe_creator_user_token,
|
||||
users.username as maybe_creator_username,
|
||||
users.display_name as maybe_creator_display_name,
|
||||
@@ -90,6 +97,8 @@ async fn get_raw_media_files_by_tokens(
|
||||
FROM media_files as m
|
||||
LEFT OUTER JOIN users
|
||||
ON users.token = m.maybe_creator_user_token
|
||||
LEFT OUTER JOIN model_weights as w
|
||||
ON m.maybe_origin_model_token = w.token
|
||||
LEFT OUTER JOIN entity_stats
|
||||
ON entity_stats.entity_type = "media_file"
|
||||
AND entity_stats.entity_token = m.token
|
||||
@@ -107,9 +116,12 @@ async fn get_raw_media_files_by_tokens(
|
||||
|
||||
m.origin_category,
|
||||
m.origin_product_category,
|
||||
|
||||
m.maybe_origin_model_type,
|
||||
m.maybe_origin_model_token,
|
||||
|
||||
w.title as maybe_origin_model_title,
|
||||
|
||||
users.token as maybe_creator_user_token,
|
||||
users.username as maybe_creator_username,
|
||||
users.display_name as maybe_creator_display_name,
|
||||
@@ -129,6 +141,8 @@ async fn get_raw_media_files_by_tokens(
|
||||
FROM media_files as m
|
||||
LEFT OUTER JOIN users
|
||||
ON users.token = m.maybe_creator_user_token
|
||||
LEFT OUTER JOIN model_weights as w
|
||||
ON m.maybe_origin_model_token = w.token
|
||||
LEFT OUTER JOIN entity_stats
|
||||
ON entity_stats.entity_type = "media_file"
|
||||
AND entity_stats.entity_token = m.token
|
||||
@@ -173,6 +187,7 @@ fn map_to_media_files(dataset:Vec<RawMediaFileJoinUser>) -> Vec<MediaFilesByToke
|
||||
origin_product_category: media_file.origin_product_category,
|
||||
maybe_origin_model_type: media_file.maybe_origin_model_type,
|
||||
maybe_origin_model_token: media_file.maybe_origin_model_token,
|
||||
maybe_origin_model_title: media_file.maybe_origin_model_title,
|
||||
|
||||
maybe_creator_user_token: media_file.maybe_creator_user_token,
|
||||
maybe_creator_username: media_file.maybe_creator_username,
|
||||
@@ -205,9 +220,12 @@ fn map_to_media_files(dataset:Vec<RawMediaFileJoinUser>) -> Vec<MediaFilesByToke
|
||||
|
||||
pub origin_category: MediaFileOriginCategory,
|
||||
pub origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
pub maybe_origin_model_token: Option<String>,
|
||||
|
||||
pub maybe_origin_model_title: Option<String>,
|
||||
|
||||
pub maybe_creator_user_token: Option<UserToken>,
|
||||
pub maybe_creator_username: Option<String>,
|
||||
pub maybe_creator_display_name: Option<String>,
|
||||
@@ -246,6 +264,7 @@ impl FromRow<'_, MySqlRow> for RawMediaFileJoinUser {
|
||||
origin_product_category: MediaFileOriginProductCategory::try_from_mysql_row(row, "origin_product_category")?,
|
||||
maybe_origin_model_type: MediaFileOriginModelType::try_from_mysql_row_nullable(row, "maybe_origin_model_type")?,
|
||||
maybe_origin_model_token: row.try_get("maybe_origin_model_token")?,
|
||||
maybe_origin_model_title: row.try_get("maybe_origin_model_title")?,
|
||||
maybe_creator_user_token: row.try_get::<Option<String>, _>("maybe_creator_user_token")?
|
||||
.and_then(|token| Some(UserToken::new_from_str(&token))),
|
||||
maybe_creator_username: row.try_get("maybe_creator_username")?,
|
||||
|
||||
@@ -26,8 +26,12 @@ pub struct MediaFileListItem {
|
||||
|
||||
pub origin_category: MediaFileOriginCategory,
|
||||
pub origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
pub maybe_origin_model_token: Option<String>,
|
||||
|
||||
// NB: The title won't be populated for `tts_models` records or non-`model_weights` records.
|
||||
pub maybe_origin_model_title: Option<String>,
|
||||
|
||||
pub media_type: MediaFileType,
|
||||
pub public_bucket_directory_hash: String,
|
||||
@@ -97,6 +101,7 @@ pub async fn list_media_files_for_user(args: ListMediaFileForUserArgs<'_>) -> An
|
||||
origin_product_category: record.origin_product_category,
|
||||
maybe_origin_model_type: record.maybe_origin_model_type,
|
||||
maybe_origin_model_token: record.maybe_origin_model_token,
|
||||
maybe_origin_model_title: record.maybe_origin_model_title,
|
||||
media_type: record.media_type,
|
||||
public_bucket_directory_hash: record.public_bucket_directory_hash,
|
||||
maybe_public_bucket_prefix: record.maybe_public_bucket_prefix,
|
||||
@@ -125,13 +130,15 @@ fn select_result_fields() -> String {
|
||||
m.id,
|
||||
m.token,
|
||||
|
||||
m.media_type,
|
||||
|
||||
m.origin_category,
|
||||
m.origin_product_category,
|
||||
|
||||
m.maybe_origin_model_type,
|
||||
m.maybe_origin_model_token,
|
||||
|
||||
m.media_type,
|
||||
|
||||
w.title as maybe_origin_model_title,
|
||||
|
||||
m.public_bucket_directory_hash,
|
||||
m.maybe_public_bucket_prefix,
|
||||
@@ -175,6 +182,8 @@ SELECT
|
||||
FROM media_files AS m
|
||||
LEFT OUTER JOIN users AS u
|
||||
ON m.maybe_creator_user_token = u.token
|
||||
LEFT OUTER JOIN model_weights as w
|
||||
ON m.maybe_origin_model_token = w.token
|
||||
LEFT OUTER JOIN entity_stats
|
||||
ON entity_stats.entity_type = "media_file"
|
||||
AND entity_stats.entity_token = m.token
|
||||
@@ -227,8 +236,12 @@ struct MediaFileListItemInternal {
|
||||
|
||||
origin_category: MediaFileOriginCategory,
|
||||
origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
maybe_origin_model_token: Option<String>,
|
||||
|
||||
// NB: The title won't be populated for `tts_models` records or non-`model_weights` records.
|
||||
maybe_origin_model_title: Option<String>,
|
||||
|
||||
media_type: MediaFileType,
|
||||
public_bucket_directory_hash: String,
|
||||
@@ -266,6 +279,7 @@ impl FromRow<'_, MySqlRow> for MediaFileListItemInternal {
|
||||
origin_product_category: MediaFileOriginProductCategory::try_from_mysql_row(row, "origin_product_category")?,
|
||||
maybe_origin_model_type: MediaFileOriginModelType::try_from_mysql_row_nullable(row, "maybe_origin_model_type")?,
|
||||
maybe_origin_model_token: row.try_get("maybe_origin_model_token")?,
|
||||
maybe_origin_model_title: row.try_get("maybe_origin_model_title")?,
|
||||
media_type: MediaFileType::try_from_mysql_row(row, "media_type")?,
|
||||
public_bucket_directory_hash: row.try_get("public_bucket_directory_hash")?,
|
||||
maybe_public_bucket_prefix: row.try_get("maybe_public_bucket_prefix")?,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod api_tokens;
|
||||
pub mod audit_logs;
|
||||
pub mod batch_generations;
|
||||
pub mod billing;
|
||||
pub mod comments;
|
||||
pub mod email_sender_jobs;
|
||||
@@ -18,12 +19,9 @@ pub mod stats;
|
||||
pub mod trending_model_analytics;
|
||||
pub mod tts;
|
||||
pub mod twitch;
|
||||
pub mod user_bookmarks;
|
||||
pub mod users;
|
||||
pub mod vocoder;
|
||||
pub mod voice_clone_requests;
|
||||
pub mod voice_conversion;
|
||||
pub mod voice_designer;
|
||||
pub mod w2l;
|
||||
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::MySql;
|
||||
use sqlx::pool::PoolConnection;
|
||||
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ModelWeightForTts {
|
||||
pub token: ModelWeightToken,
|
||||
pub weight_type: WeightsType,
|
||||
|
||||
pub title: String,
|
||||
|
||||
// We only supported tacotron2 in the legacy case
|
||||
//pub tts_model_type: String,
|
||||
|
||||
pub ietf_language_tag: String,
|
||||
pub ietf_primary_language_subtag: String,
|
||||
|
||||
pub creator_user_token: UserToken,
|
||||
pub creator_username: String,
|
||||
pub creator_display_name: String,
|
||||
pub creator_gravatar_hash: String,
|
||||
|
||||
// NB: We won't port these...
|
||||
//pub is_locked_from_use: bool,
|
||||
//pub is_front_page_featured: bool,
|
||||
//pub is_twitch_featured: bool,
|
||||
//pub maybe_suggested_unique_bot_command: Option<String>,
|
||||
//pub user_ratings_positive_count: u32,
|
||||
//pub user_ratings_negative_count: u32,
|
||||
//pub user_ratings_total_count: u32, // NB: Does not include "neutral" ratings.
|
||||
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
// TODO(bt,2024-01-13): This is written to support the migration to the `model_weights`
|
||||
// table from the `tts_models` table. We should write a more cross-cutting
|
||||
// query to treat this not as a special cased thing. All weights should be listable.
|
||||
|
||||
/// This is to support the tts model list page.
|
||||
/// Later this will be migrated or replaced with a more generic query.
|
||||
pub async fn list_model_weights_for_text_to_speech(
|
||||
mysql_connection: &mut PoolConnection<MySql>,
|
||||
) -> AnyhowResult<Vec<ModelWeightForTts>> {
|
||||
|
||||
let models =
|
||||
list_tts_models_for_all_creators(mysql_connection).await?;
|
||||
|
||||
Ok(models.into_iter()
|
||||
.map(|model| {
|
||||
ModelWeightForTts {
|
||||
token: model.token,
|
||||
weight_type: model.weight_type,
|
||||
creator_user_token: model.creator_user_token,
|
||||
creator_username: model.creator_username,
|
||||
creator_display_name: model.creator_display_name,
|
||||
creator_gravatar_hash: model.creator_gravatar_hash,
|
||||
title: model.title,
|
||||
ietf_language_tag: model.ietf_language_tag.unwrap_or("en".to_string()),
|
||||
ietf_primary_language_subtag: model.ietf_primary_language_subtag.unwrap_or("en".to_string()),
|
||||
creator_set_visibility: model.creator_set_visibility,
|
||||
created_at: model.created_at,
|
||||
updated_at: model.updated_at,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<ModelWeightForTts>>())
|
||||
}
|
||||
|
||||
async fn list_tts_models_for_all_creators(
|
||||
mysql_connection: &mut PoolConnection<MySql>,
|
||||
) -> AnyhowResult<Vec<RawModelWeightForTts>> {
|
||||
// NB: Scoped to only tt2 weights
|
||||
let maybe_results = sqlx::query_as!(
|
||||
RawModelWeightForTts,
|
||||
r#"
|
||||
SELECT
|
||||
w.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
|
||||
w.weights_type as `weight_type: enums::by_table::model_weights::weights_types::WeightsType`,
|
||||
w.title,
|
||||
w.creator_user_token as `creator_user_token: tokens::tokens::users::UserToken`,
|
||||
users.username as creator_username,
|
||||
users.display_name as creator_display_name,
|
||||
users.email_gravatar_hash as creator_gravatar_hash,
|
||||
w_extension.ietf_language_tag,
|
||||
w_extension.ietf_primary_language_subtag,
|
||||
w.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
|
||||
w.created_at,
|
||||
w.updated_at
|
||||
FROM model_weights as w
|
||||
LEFT OUTER JOIN model_weights_extension_tts_details as w_extension
|
||||
ON w_extension.model_weights_token = w.token
|
||||
JOIN users
|
||||
ON users.token = w.creator_user_token
|
||||
WHERE
|
||||
w.weights_type IN ("tt2")
|
||||
AND w.user_deleted_at IS NULL
|
||||
AND w.mod_deleted_at IS NULL
|
||||
"#
|
||||
)
|
||||
.fetch_all(&mut **mysql_connection)
|
||||
.await;
|
||||
|
||||
match maybe_results {
|
||||
Ok(results) => Ok(results),
|
||||
Err(err) => match err {
|
||||
sqlx::Error::RowNotFound => Ok(Vec::new()),
|
||||
_ => {
|
||||
Err(anyhow!("error querying : {:?}", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RawModelWeightForTts {
|
||||
pub token: ModelWeightToken,
|
||||
pub weight_type: WeightsType,
|
||||
|
||||
pub title: String,
|
||||
|
||||
// We only supported tacotron2 in the legacy case
|
||||
//pub tts_model_type: String,
|
||||
|
||||
pub ietf_language_tag: Option<String>,
|
||||
pub ietf_primary_language_subtag: Option<String>,
|
||||
|
||||
pub creator_user_token: UserToken,
|
||||
pub creator_username: String,
|
||||
pub creator_display_name: String,
|
||||
pub creator_gravatar_hash: String,
|
||||
|
||||
// NB: We won't port these...
|
||||
//pub is_locked_from_use: bool,
|
||||
//pub is_front_page_featured: bool,
|
||||
//pub is_twitch_featured: bool,
|
||||
//pub maybe_suggested_unique_bot_command: Option<String>,
|
||||
//pub user_ratings_positive_count: u32,
|
||||
//pub user_ratings_negative_count: u32,
|
||||
//pub user_ratings_total_count: u32, // NB: Does not include "neutral" ratings.
|
||||
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod list_model_weights_for_elastic_search_backfill_using_cursor;
|
||||
pub mod list_model_weights_for_text_to_speech;
|
||||
pub mod list_model_weights_for_voice_conversion;
|
||||
pub mod list_weights_by_tokens;
|
||||
pub mod list_weights_by_user;
|
||||
pub mod list_model_weights_for_elastic_search_backfill_using_cursor;
|
||||
pub mod list_weights_query_builder;
|
||||
@@ -1 +1,2 @@
|
||||
pub mod upsert_model_weight_from_tts_model;
|
||||
pub mod upsert_model_weight_from_voice_conversion_model;
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
use sqlx::{MySql, MySqlPool, Transaction};
|
||||
|
||||
use buckets::public::weight_files::bucket_file_path::WeightFileBucketPath;
|
||||
use enums::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
use errors::AnyhowResult;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use crate::queries::tts::tts_models::migration::list_whole_tts_models_using_cursor::WholeTtsModelRecord;
|
||||
|
||||
pub struct CopiedTtsFileData {
|
||||
pub bucket_path: WeightFileBucketPath,
|
||||
pub file_sha_hash: String,
|
||||
}
|
||||
|
||||
/// Migrate `tts_models` records to `model_weights` + `model_weights_extension_tts_details` records.
|
||||
/// This is designed to be idempotent and re-runnable. Any time we re-run the query, we should get the same result.
|
||||
/// This will enable us to perfect the query and get the write flows online and switched over.
|
||||
///
|
||||
pub async fn upsert_model_weight_from_tts_model(
|
||||
record: &WholeTtsModelRecord,
|
||||
mysql_pool: &MySqlPool,
|
||||
copied_data: &CopiedTtsFileData,
|
||||
) -> AnyhowResult<()> {
|
||||
|
||||
let mut transaction = mysql_pool.begin().await?;
|
||||
|
||||
let model_weight_token = create_or_generate_token(record);
|
||||
|
||||
upsert_model_weights_record(record, &model_weight_token, copied_data, &mut transaction).await?;
|
||||
upsert_model_weights_extension_record(record, &model_weight_token, &mut transaction).await?;
|
||||
|
||||
update_original_record(record, &model_weight_token, &mut transaction).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_or_generate_token(record: &WholeTtsModelRecord) -> ModelWeightToken {
|
||||
match record.maybe_migration_new_model_weights_token {
|
||||
Some(ref token) => token.clone(),
|
||||
None => ModelWeightToken::generate(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn upsert_model_weights_record(
|
||||
record: &WholeTtsModelRecord,
|
||||
model_weight_token: &ModelWeightToken,
|
||||
copied_data: &CopiedTtsFileData,
|
||||
mut transaction: &mut Transaction<'_, MySql>,
|
||||
) -> AnyhowResult<()> {
|
||||
|
||||
// NB: We never supported other TTS models in the tts_models table.
|
||||
const WEIGHTS_TYPE : WeightsType = WeightsType::Tacotron2;
|
||||
const WEIGHTS_CATEGORY : WeightsCategory = WeightsCategory::TextToSpeech;
|
||||
|
||||
// NB: Not setting a few fields (for now)
|
||||
// maybe_last_update_user_token - seems like bad design
|
||||
// TODO(bt): file checksum
|
||||
// TODO(bt): rename maybe_public_bucket_extension to maybe_public_bucket_suffix (!!!)
|
||||
// TODO(bt): do we need model_weights.ip_address_last_update without audit logs?
|
||||
// TODO(bt): rename creator_ip_address to ip_address_creation (and add ip_address_last_update)
|
||||
// TODO(bt): Check model_weights column integer types - signed vs unsigned
|
||||
let query = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO model_weights
|
||||
SET
|
||||
token = ?,
|
||||
weights_type = ?,
|
||||
weights_category = ?,
|
||||
title = ?,
|
||||
maybe_cover_image_media_file_token = NULL,
|
||||
maybe_description_markdown = ?,
|
||||
maybe_description_rendered_html = ?,
|
||||
creator_user_token = ?,
|
||||
creator_ip_address = ?,
|
||||
|
||||
creator_set_visibility = ?,
|
||||
maybe_last_update_user_token = NULL,
|
||||
original_download_url = ?,
|
||||
original_filename = ?,
|
||||
file_size_bytes = ?,
|
||||
file_checksum_sha2 = ?,
|
||||
|
||||
public_bucket_hash = ?,
|
||||
maybe_public_bucket_prefix = ?,
|
||||
maybe_public_bucket_extension = ?,
|
||||
|
||||
maybe_migration_old_model_token = ?,
|
||||
version = ?,
|
||||
created_at = ?,
|
||||
updated_at = ?,
|
||||
user_deleted_at = ?,
|
||||
mod_deleted_at = ?
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
weights_type = ?,
|
||||
weights_category = ?,
|
||||
title = ?,
|
||||
maybe_cover_image_media_file_token = NULL,
|
||||
maybe_description_markdown = ?,
|
||||
maybe_description_rendered_html = ?,
|
||||
creator_user_token = ?,
|
||||
creator_ip_address = ?,
|
||||
creator_set_visibility = ?,
|
||||
maybe_last_update_user_token = NULL,
|
||||
original_download_url = ?,
|
||||
original_filename = ?,
|
||||
file_size_bytes = ?,
|
||||
file_checksum_sha2 = ?,
|
||||
public_bucket_hash = ?,
|
||||
maybe_public_bucket_prefix = ?,
|
||||
maybe_public_bucket_extension = ?,
|
||||
maybe_migration_old_model_token = ?,
|
||||
version = ?,
|
||||
created_at = ?,
|
||||
updated_at = ?,
|
||||
user_deleted_at = ?,
|
||||
mod_deleted_at = ?
|
||||
"#,
|
||||
// Insert
|
||||
model_weight_token,
|
||||
WEIGHTS_TYPE,
|
||||
WEIGHTS_CATEGORY,
|
||||
record.title,
|
||||
record.description_markdown,
|
||||
record.description_rendered_html,
|
||||
record.creator_user_token,
|
||||
record.creator_ip_address_creation,
|
||||
record.creator_set_visibility.to_str(),
|
||||
record.original_download_url,
|
||||
record.original_filename,
|
||||
record.file_size_bytes,
|
||||
|
||||
copied_data.file_sha_hash,
|
||||
copied_data.bucket_path.get_object_hash(),
|
||||
copied_data.bucket_path.get_optional_prefix(),
|
||||
copied_data.bucket_path.get_optional_extension(),
|
||||
|
||||
record.token.as_str(),
|
||||
record.version,
|
||||
record.created_at,
|
||||
record.updated_at,
|
||||
record.user_deleted_at,
|
||||
record.mod_deleted_at,
|
||||
|
||||
// Update
|
||||
WEIGHTS_TYPE,
|
||||
WEIGHTS_CATEGORY,
|
||||
record.title,
|
||||
record.description_markdown,
|
||||
record.description_rendered_html,
|
||||
record.creator_user_token,
|
||||
record.creator_ip_address_creation,
|
||||
record.creator_set_visibility.to_str(),
|
||||
record.original_download_url,
|
||||
record.original_filename,
|
||||
record.file_size_bytes,
|
||||
|
||||
copied_data.file_sha_hash,
|
||||
copied_data.bucket_path.get_object_hash(),
|
||||
copied_data.bucket_path.get_optional_prefix(),
|
||||
copied_data.bucket_path.get_optional_extension(),
|
||||
|
||||
record.token.as_str(),
|
||||
record.version,
|
||||
record.created_at,
|
||||
record.updated_at,
|
||||
record.user_deleted_at,
|
||||
record.mod_deleted_at,
|
||||
);
|
||||
|
||||
let _r = query.execute(&mut **transaction).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn upsert_model_weights_extension_record(
|
||||
record: &WholeTtsModelRecord,
|
||||
model_weight_token: &ModelWeightToken,
|
||||
transaction: &mut Transaction<'_, MySql>
|
||||
) -> AnyhowResult<()> {
|
||||
let query = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO model_weights_extension_tts_details
|
||||
SET
|
||||
model_weights_token = ?,
|
||||
ietf_language_tag = ?,
|
||||
ietf_primary_language_subtag = ?,
|
||||
text_pipeline_type = ?,
|
||||
use_default_mel_multiply_factor = ?,
|
||||
maybe_custom_mel_multiply_factor = ?,
|
||||
maybe_default_pretrained_vocoder = ?,
|
||||
maybe_custom_vocoder_token = ?
|
||||
ON DUPLICATE KEY UPDATE
|
||||
ietf_language_tag = ?,
|
||||
ietf_primary_language_subtag = ?,
|
||||
text_pipeline_type = ?,
|
||||
use_default_mel_multiply_factor = ?,
|
||||
maybe_custom_mel_multiply_factor = ?,
|
||||
maybe_default_pretrained_vocoder = ?,
|
||||
maybe_custom_vocoder_token = ?
|
||||
"#,
|
||||
// Insert
|
||||
&model_weight_token,
|
||||
record.ietf_language_tag,
|
||||
record.ietf_primary_language_subtag,
|
||||
record.text_pipeline_type,
|
||||
record.use_default_mel_multiply_factor,
|
||||
record.maybe_custom_mel_multiply_factor,
|
||||
record.maybe_default_pretrained_vocoder,
|
||||
record.maybe_custom_vocoder_token,
|
||||
|
||||
// Update
|
||||
record.ietf_language_tag,
|
||||
record.ietf_primary_language_subtag,
|
||||
record.text_pipeline_type,
|
||||
record.use_default_mel_multiply_factor,
|
||||
record.maybe_custom_mel_multiply_factor,
|
||||
record.maybe_default_pretrained_vocoder,
|
||||
record.maybe_custom_vocoder_token
|
||||
);
|
||||
|
||||
let _r = query.execute(&mut **transaction).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_original_record(
|
||||
record: &WholeTtsModelRecord,
|
||||
model_weight_token: &ModelWeightToken,
|
||||
transaction: &mut Transaction<'_, MySql>
|
||||
) -> AnyhowResult<()> {
|
||||
let query = sqlx::query!(
|
||||
r#"
|
||||
UPDATE tts_models
|
||||
SET
|
||||
maybe_migration_new_model_weights_token = ?
|
||||
WHERE token = ?
|
||||
"#,
|
||||
model_weight_token,
|
||||
record.token,
|
||||
);
|
||||
|
||||
let _r = query.execute(&mut **transaction).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -293,6 +293,8 @@ mod tests {
|
||||
maybe_scoped_weight_type: None,
|
||||
maybe_scoped_weight_category: None,
|
||||
mysql_pool: &pool,
|
||||
maybe_scoped_weight_type: None,
|
||||
maybe_scoped_weight_category: None,
|
||||
}).await?;
|
||||
for weight in weights_by_username.records.iter() {
|
||||
// print weight
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::helpers::boolean_converters::i8_to_bool;
|
||||
// FIXME: This is the old style of query scoping and shouldn't be copied.
|
||||
|
||||
// TODO/FIXME : This struct is returned publicly in some endpoints!
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct TtsModelRecordForList {
|
||||
pub model_token: String,
|
||||
pub tts_model_type: String,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod user;
|
||||
pub mod user_badges;
|
||||
pub mod user_bookmarks;
|
||||
pub mod user_password_resets;
|
||||
pub mod user_profiles;
|
||||
pub mod user_ratings;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+2
-2
@@ -1,11 +1,11 @@
|
||||
use anyhow::anyhow;
|
||||
use log::warn;
|
||||
use sqlx::{MySql};
|
||||
use sqlx::MySql;
|
||||
use sqlx::pool::PoolConnection;
|
||||
|
||||
use errors::AnyhowResult;
|
||||
|
||||
use crate::queries::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
use crate::queries::users::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
|
||||
pub struct BookmarkCount {
|
||||
pub total_count: usize,
|
||||
File renamed without changes.
+1
-1
@@ -7,7 +7,7 @@ use errors::AnyhowResult;
|
||||
use tokens::tokens::user_bookmarks::UserBookmarkToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::queries::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
use crate::queries::users::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
|
||||
pub struct UserBookmark {
|
||||
pub token: UserBookmarkToken,
|
||||
+2
-2
@@ -6,8 +6,8 @@ use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
use enums::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
use crate::queries::user_bookmarks::list_user_bookmarks_result::RawUserBookmarkRecord;
|
||||
use crate::queries::user_bookmarks::list_user_bookmarks_result::UserBookmark;
|
||||
use crate::queries::users::user_bookmarks::list_user_bookmarks_result::RawUserBookmarkRecord;
|
||||
use crate::queries::users::user_bookmarks::list_user_bookmarks_result::UserBookmark;
|
||||
|
||||
pub struct UserBookmarkListPage {
|
||||
pub results: Vec<UserBookmark>,
|
||||
+1
-1
@@ -7,7 +7,7 @@ use errors::AnyhowResult;
|
||||
use tokens::tokens::user_bookmarks::UserBookmarkToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::queries::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
use crate::queries::users::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
|
||||
pub struct UserBookmark {
|
||||
pub token: UserBookmarkToken,
|
||||
+37
-37
@@ -70,56 +70,56 @@ pub struct UserBookmark {
|
||||
}
|
||||
|
||||
pub struct RawUserBookmarkRecord {
|
||||
pub (crate) token: UserBookmarkToken,
|
||||
pub(crate) token: UserBookmarkToken,
|
||||
|
||||
pub (crate) entity_type: UserBookmarkEntityType,
|
||||
pub (crate) entity_token: String,
|
||||
pub(crate) entity_type: UserBookmarkEntityType,
|
||||
pub(crate) entity_token: String,
|
||||
|
||||
// TODO(bt,2023-12-30): I don't think these user fields are necessary.
|
||||
// We already know the user we're querying on behalf of, so presumably we
|
||||
// already have their info (ie. profile page use).
|
||||
pub (crate) user_token: UserToken,
|
||||
pub (crate) username: String,
|
||||
pub (crate) user_display_name: String,
|
||||
pub (crate) user_gravatar_hash: String,
|
||||
pub(crate) user_token: UserToken,
|
||||
pub(crate) username: String,
|
||||
pub(crate) user_display_name: String,
|
||||
pub(crate) user_gravatar_hash: String,
|
||||
|
||||
pub (crate) created_at: DateTime<Utc>,
|
||||
pub (crate) updated_at: DateTime<Utc>,
|
||||
pub (crate) deleted_at: Option<DateTime<Utc>>,
|
||||
pub(crate) created_at: DateTime<Utc>,
|
||||
pub(crate) updated_at: DateTime<Utc>,
|
||||
pub(crate) deleted_at: Option<DateTime<Utc>>,
|
||||
|
||||
pub (crate) maybe_ratings_positive_count: Option<u32>,
|
||||
pub (crate) maybe_ratings_negative_count: Option<u32>,
|
||||
pub (crate) maybe_bookmark_count: Option<u32>,
|
||||
pub(crate) maybe_ratings_positive_count: Option<u32>,
|
||||
pub(crate) maybe_ratings_negative_count: Option<u32>,
|
||||
pub(crate) maybe_bookmark_count: Option<u32>,
|
||||
|
||||
pub (crate) maybe_media_file_type: Option<MediaFileType>,
|
||||
pub (crate) maybe_media_file_origin_category: Option<MediaFileOriginCategory>,
|
||||
pub (crate) maybe_media_file_public_bucket_hash: Option<String>,
|
||||
pub (crate) maybe_media_file_public_bucket_prefix: Option<String>,
|
||||
pub (crate) maybe_media_file_public_bucket_extension: Option<String>,
|
||||
pub(crate) maybe_media_file_type: Option<MediaFileType>,
|
||||
pub(crate) maybe_media_file_origin_category: Option<MediaFileOriginCategory>,
|
||||
pub(crate) maybe_media_file_public_bucket_hash: Option<String>,
|
||||
pub(crate) maybe_media_file_public_bucket_prefix: Option<String>,
|
||||
pub(crate) maybe_media_file_public_bucket_extension: Option<String>,
|
||||
|
||||
pub (crate) maybe_media_file_creator_user_token: Option<UserToken>,
|
||||
pub (crate) maybe_media_file_creator_username: Option<String>,
|
||||
pub (crate) maybe_media_file_creator_display_name: Option<String>,
|
||||
pub (crate) maybe_media_file_creator_gravatar_hash: Option<String>,
|
||||
pub(crate) maybe_media_file_creator_user_token: Option<UserToken>,
|
||||
pub(crate) maybe_media_file_creator_username: Option<String>,
|
||||
pub(crate) maybe_media_file_creator_display_name: Option<String>,
|
||||
pub(crate) maybe_media_file_creator_gravatar_hash: Option<String>,
|
||||
|
||||
pub (crate) maybe_model_weight_type: Option<WeightsType>,
|
||||
pub (crate) maybe_model_weight_category: Option<WeightsCategory>,
|
||||
pub(crate) maybe_model_weight_type: Option<WeightsType>,
|
||||
pub(crate) maybe_model_weight_category: Option<WeightsCategory>,
|
||||
|
||||
pub (crate) maybe_model_weight_cover_image_public_bucket_hash: Option<String>,
|
||||
pub (crate) maybe_model_weight_cover_image_public_bucket_prefix: Option<String>,
|
||||
pub (crate) maybe_model_weight_cover_image_public_bucket_extension: Option<String>,
|
||||
pub(crate) maybe_model_weight_cover_image_public_bucket_hash: Option<String>,
|
||||
pub(crate) maybe_model_weight_cover_image_public_bucket_prefix: Option<String>,
|
||||
pub(crate) maybe_model_weight_cover_image_public_bucket_extension: Option<String>,
|
||||
|
||||
pub (crate) maybe_model_weight_creator_user_token: Option<UserToken>,
|
||||
pub (crate) maybe_model_weight_creator_username: Option<String>,
|
||||
pub (crate) maybe_model_weight_creator_display_name: Option<String>,
|
||||
pub (crate) maybe_model_weight_creator_gravatar_hash: Option<String>,
|
||||
pub(crate) maybe_model_weight_creator_user_token: Option<UserToken>,
|
||||
pub(crate) maybe_model_weight_creator_username: Option<String>,
|
||||
pub(crate) maybe_model_weight_creator_display_name: Option<String>,
|
||||
pub(crate) maybe_model_weight_creator_gravatar_hash: Option<String>,
|
||||
|
||||
pub (crate) maybe_descriptive_text_model_weight_title: Option<String>,
|
||||
pub (crate) maybe_descriptive_text_tts_model_title: Option<String>,
|
||||
pub (crate) maybe_descriptive_text_tts_result_inference_text: Option<String>,
|
||||
pub (crate) maybe_descriptive_text_user_display_name: Option<String>,
|
||||
pub (crate) maybe_descriptive_text_voice_conversion_model_title: Option<String>,
|
||||
pub (crate) maybe_descriptive_text_zs_voice_title: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_model_weight_title: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_tts_model_title: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_tts_result_inference_text: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_user_display_name: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_voice_conversion_model_title: Option<String>,
|
||||
pub(crate) maybe_descriptive_text_zs_voice_title: Option<String>,
|
||||
}
|
||||
|
||||
impl RawUserBookmarkRecord {
|
||||
File renamed without changes.
+1
-1
@@ -7,7 +7,7 @@ use errors::AnyhowResult;
|
||||
use tokens::tokens::user_bookmarks::UserBookmarkToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::queries::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
use crate::queries::users::user_bookmarks::user_bookmark_entity_token::UserBookmarkEntityToken;
|
||||
|
||||
pub struct CreateUserBookmarkArgs<'e, 'c, E>
|
||||
where E: 'e + Executor<'c, Database = MySql>
|
||||
File renamed without changes.
@@ -76,6 +76,8 @@ pub async fn do_process_single_job(job_state: &JobState, job: &AvailableDownload
|
||||
return Err(anyhow!("Bad download URL: `{}`", &job.download_url));
|
||||
}
|
||||
|
||||
// TODO USE THIS DOWNLOADER
|
||||
|
||||
let download_filename = match job_state.sidecar_configs.google_drive_downloader.download_file(&job.download_url, &temp_dir).await {
|
||||
Ok(filename) => filename,
|
||||
Err(e) => {
|
||||
|
||||
@@ -70,7 +70,7 @@ pub struct PretrainedModels {
|
||||
|
||||
/// Configurations and interfaces to code deployed as sidecars or container mounts.
|
||||
pub struct SidecarConfigs {
|
||||
pub google_drive_downloader: GoogleDriveDownloadCommand,
|
||||
pub(crate) google_drive_downloader: GoogleDriveDownloadCommand,
|
||||
pub rvc_v2_model_check_command: RvcV2ModelCheckCommand,
|
||||
pub softvc_model_check_command: SoftVcModelCheckCommand,
|
||||
pub so_vits_svc_model_check_command: SoVitsSvcModelCheckCommand,
|
||||
|
||||
@@ -19,7 +19,9 @@ actix_helpers = { path = "../../../lib/actix_helpers" }
|
||||
bootstrap = { path = "../../../lib/bootstrap" }
|
||||
buckets = { path = "../../../_types/buckets" }
|
||||
cloud_storage = { path = "../../../lib/api_clients/cloud_storage" }
|
||||
google_drive_common = { path = "../../../lib/api_clients/google_drive_common" }
|
||||
collections = { path = "../../../lib/collections" }
|
||||
composite_identifiers = { path = "../../../_types/composite_identifiers" }
|
||||
concurrency = { path = "../../../lib/concurrency" }
|
||||
config = { path = "../../../lib/deprecated/config" }
|
||||
easyenv = { path = "../../../lib/easyenv" }
|
||||
|
||||
@@ -103,6 +103,14 @@ VITS_INFERENCE_MAYBE_DOCKER_IMAGE_SHA="03017896367b"
|
||||
RERENDER_INFERENCE_ROOT_DIRECTORY="/home/salt/clone/storyteller-ml/animation/rerender-lora/"
|
||||
RERENDER_INFERENCE_EXECUTABLE_OR_COMMAND="venv/bin/python rerender.py"
|
||||
|
||||
# ================================= #
|
||||
# #
|
||||
# STABLE DIFFUSION #
|
||||
# #
|
||||
# ================================= #
|
||||
STABLE_DIFFUSION_INFERENCE_ROOT_DIRECTORY="/home/tensor/code/storyteller/storyteller-ml/image_generation/Storyteller-Studio-Filter/"
|
||||
STABLE_DIFFUSION_INFERENCE_COMMAND=".venv/bin/python main.py"
|
||||
|
||||
# ================================= #
|
||||
# #
|
||||
# MocapNET #
|
||||
|
||||
@@ -188,7 +188,7 @@ async fn get_model_record_from_cacheable_query(job_dependencies: &JobDependencie
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!("Job does not have a category or a model token: {:?} - category: {:?}, token: {:?}",
|
||||
warn!("Only applies to older job workflows. Job does not have a category or a model token: {:?} - category: {:?}, token: {:?}",
|
||||
job.id, job.inference_category, job.maybe_model_token);
|
||||
|
||||
MaybeInferenceModel::None
|
||||
|
||||
@@ -17,6 +17,7 @@ use crate::job::job_types::lipsync::process_single_lipsync_job::process_single_l
|
||||
use crate::job::job_types::tts::process_single_tts_job::process_single_tts_job;
|
||||
use crate::job::job_types::vc::process_single_vc_job::process_single_vc_job;
|
||||
use crate::job::job_types::videofilter::process_single_vf_job::process_single_vf_job;
|
||||
use crate::job::job_types::image_generation::process_single_ig_job::process_single_ig_job;
|
||||
use crate::job::job_types::mocap::process_single_mc_job::process_single_mc_job;
|
||||
use crate::job::job_types::workflow::process_single_wf_job::process_single_wf_job;
|
||||
use crate::job_dependencies::JobDependencies;
|
||||
@@ -188,6 +189,9 @@ async fn do_process_single_job(
|
||||
InferenceCategory::VideoFilter => {
|
||||
process_single_vf_job(job_dependencies, job).await?
|
||||
}
|
||||
InferenceCategory::ImageGeneration => {
|
||||
process_single_ig_job(job_dependencies, job).await?
|
||||
}
|
||||
InferenceCategory::Mocap => {
|
||||
process_single_mc_job(job_dependencies, job).await?
|
||||
}
|
||||
|
||||
Loaded 100 of 164 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user