mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 02:00:46 +00:00
port legacy GET TTS endpoint to model weights
This commit is contained in:
1 parent
65c5138533
commit
0811e12c0b
7 files changed
+660
-69
No files matched your search
@@ -43,6 +43,7 @@ CREATE TABLE tts_models (
|
||||
has_self_contained_pitch_model BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- NB(2022-07-05): THIS IS NOW MEANINGLESS AND SUPERSEDED BY `TEXT_PIPELINE_TYPE`.
|
||||
-- NB(2024-01-20): All 8720 records in the database are "basic".
|
||||
-- NB: DO NOT CHANGE ORDER; APPEND ONLY!
|
||||
-- How text should be handled.
|
||||
text_preprocessing_algorithm ENUM(
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use sqlx::MySql;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use enums::by_table::tts_models::tts_model_type::TtsModelType;
|
||||
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
use mysql_queries::column_types::vocoder_type::VocoderType;
|
||||
use mysql_queries::queries::model_weights::get::get_weight_for_legacy_tts_info::{get_weight_for_legacy_tts_info_with_connection, ModelWeightForLegacyTtsInfo};
|
||||
use mysql_queries::queries::tts::tts_models::get_tts_model::{get_tts_model_by_token_using_connection, TtsModelRecord};
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
/// Get TTS model
|
||||
/// This is for the tts model info page
|
||||
pub async fn get_tts_model_info_migration(
|
||||
token: &str,
|
||||
mysql_connection: &mut PoolConnection<MySql>,
|
||||
can_see_deleted: bool,
|
||||
use_weights_table: bool,
|
||||
) -> AnyhowResult<Option<TtsModelInfoMigration>> {
|
||||
// NB: This is temporary migration code as we switch from the `tts_models` table to the `model_weights` table.
|
||||
if use_weights_table {
|
||||
let token = ModelWeightToken::new_from_str(token);
|
||||
|
||||
let maybe_model = get_weight_for_legacy_tts_info_with_connection(
|
||||
&token,
|
||||
can_see_deleted,
|
||||
mysql_connection
|
||||
).await?;
|
||||
|
||||
Ok(maybe_model.map(|model| TtsModelInfoMigration::ModelWeight(model)))
|
||||
|
||||
} else {
|
||||
let maybe_model = get_tts_model_by_token_using_connection(
|
||||
&token,
|
||||
true,
|
||||
mysql_connection
|
||||
).await?;
|
||||
|
||||
Ok(maybe_model.map(|model| TtsModelInfoMigration::LegacyTts(model)))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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, Serialize, Deserialize)]
|
||||
pub enum TtsModelInfoMigration {
|
||||
/// Old type from the `tts_models` table, on the way out
|
||||
LegacyTts(TtsModelRecord),
|
||||
/// New type, replacing the `tts_models` table.
|
||||
ModelWeight(ModelWeightForLegacyTtsInfo),
|
||||
}
|
||||
|
||||
impl TtsModelInfoMigration {
|
||||
pub fn token(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.model_token.as_str(),
|
||||
Self::ModelWeight(ref model) => model.token.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.title,
|
||||
Self::ModelWeight(ref model) => &model.title,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ietf_language_tag(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.ietf_language_tag,
|
||||
Self::ModelWeight(ref model) => model.maybe_ietf_language_tag.as_deref().unwrap_or("en"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ietf_primary_language_subtag(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.ietf_primary_language_subtag,
|
||||
Self::ModelWeight(ref model) => model.maybe_ietf_primary_language_subtag.as_deref().unwrap_or("en"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_user_token(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.creator_user_token,
|
||||
Self::ModelWeight(ref model) => model.creator_user_token.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_username(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.creator_username,
|
||||
Self::ModelWeight(ref model) => &model.creator_username,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_display_name(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.creator_display_name,
|
||||
Self::ModelWeight(ref model) => &model.creator_display_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_gravatar_hash(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.creator_gravatar_hash,
|
||||
Self::ModelWeight(ref model) => &model.creator_gravatar_hash,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn creator_set_visibility(&self) -> Visibility{
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.creator_set_visibility,
|
||||
Self::ModelWeight(ref model) => model.creator_set_visibility,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn created_at(&self) -> &DateTime<Utc> {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.created_at,
|
||||
Self::ModelWeight(ref model) => &model.created_at,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updated_at(&self) -> &DateTime<Utc> {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.updated_at,
|
||||
Self::ModelWeight(ref model) => &model.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn is_front_page_featured(&self) -> bool {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.is_front_page_featured,
|
||||
Self::ModelWeight(ref _model) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn is_twitch_featured(&self) -> bool {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.is_twitch_featured,
|
||||
Self::ModelWeight(ref _model) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn is_locked_from_use(&self) -> bool {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.is_locked_from_use,
|
||||
Self::ModelWeight(ref _model) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn is_locked_from_user_modification(&self) -> bool {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.is_locked_from_user_modification,
|
||||
Self::ModelWeight(ref _model) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_positive_count(&self) -> u32 {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.user_ratings_positive_count,
|
||||
Self::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_negative_count(&self) -> u32 {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.user_ratings_negative_count,
|
||||
Self::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn user_ratings_total_count(&self) -> u32 {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.user_ratings_total_count,
|
||||
Self::ModelWeight(ref _model) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Not supported in the new table
|
||||
pub fn maybe_suggested_unique_bot_command(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.maybe_suggested_unique_bot_command.as_deref(),
|
||||
Self::ModelWeight(ref _model) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tts_model_type(&self) -> TtsModelType {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.tts_model_type,
|
||||
Self::ModelWeight(ref _model) => TtsModelType::Tacotron2, // NB: Always TT2
|
||||
}
|
||||
}
|
||||
|
||||
pub fn description_markdown(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.description_markdown,
|
||||
Self::ModelWeight(ref model) => &model.maybe_description_markdown.as_deref().unwrap_or(""),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn description_rendered_html(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.description_rendered_html,
|
||||
Self::ModelWeight(ref model) => &model.maybe_description_rendered_html.as_deref().unwrap_or(""),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_default_pretrained_vocoder(&self) -> Option<VocoderType> {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.maybe_default_pretrained_vocoder,
|
||||
Self::ModelWeight(ref model) => model.maybe_default_pretrained_vocoder,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn text_preprocessing_algorithm(&self) -> &str {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => &model.text_preprocessing_algorithm,
|
||||
Self::ModelWeight(ref _model) => "basic", // NB: All records in the DB are "basic"
|
||||
}
|
||||
}
|
||||
|
||||
/* NB(bt, 2024-01-20): Breakdown of the text_pipeline_type values in the DB:
|
||||
mysql> select text_pipeline_type , count(*) from tts_models group by text_pipeline_type ;
|
||||
+--------------------+----------+
|
||||
| text_pipeline_type | count(*) |
|
||||
+--------------------+----------+
|
||||
| NULL | 4406 |
|
||||
| legacy_fakeyou | 2572 |
|
||||
| english_v1 | 1548 |
|
||||
| spanish_v2 | 194 |
|
||||
+--------------------+----------+
|
||||
*/
|
||||
pub fn text_pipeline_type(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::LegacyTts(ref model) => model.text_pipeline_type.as_deref(),
|
||||
Self::ModelWeight(ref model) => model.maybe_text_pipeline_type.as_deref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod list_tts_models_for_migration;
|
||||
pub mod get_tts_model_for_inference_migration;
|
||||
pub mod get_tts_model_for_inference_migration;
|
||||
pub mod get_tts_model_info_migration;
|
||||
pub mod list_tts_models_for_migration;
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
use sqlx::{MySql, MySqlPool};
|
||||
use sqlx::pool::PoolConnection;
|
||||
|
||||
use container_common::anyhow_result::AnyhowResult;
|
||||
use enums::by_table::model_weights::weights_category::WeightsCategory;
|
||||
use enums::by_table::model_weights::weights_types::WeightsType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use tokens::tokens::{model_weights::ModelWeightToken, users::UserToken};
|
||||
use crate::column_types::vocoder_type::VocoderType;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ModelWeightForLegacyTtsInfo {
|
||||
pub token: ModelWeightToken,
|
||||
pub title: String,
|
||||
pub weights_type: WeightsType,
|
||||
pub weights_category: WeightsCategory,
|
||||
pub maybe_description_markdown: Option<String>,
|
||||
pub maybe_description_rendered_html: Option<String>,
|
||||
|
||||
pub creator_user_token: UserToken,
|
||||
pub creator_username: String,
|
||||
pub creator_display_name: String,
|
||||
pub creator_gravatar_hash: String,
|
||||
|
||||
pub creator_ip_address: String,
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub maybe_last_update_user_token: Option<UserToken>,
|
||||
pub original_download_url: Option<String>,
|
||||
pub original_filename: Option<String>,
|
||||
pub file_size_bytes: i32,
|
||||
pub file_checksum_sha2: String,
|
||||
pub public_bucket_hash: String,
|
||||
pub maybe_public_bucket_prefix: Option<String>,
|
||||
pub maybe_public_bucket_extension: Option<String>,
|
||||
|
||||
pub maybe_cover_image_public_bucket_hash: Option<String>,
|
||||
pub maybe_cover_image_public_bucket_prefix: Option<String>,
|
||||
pub maybe_cover_image_public_bucket_extension: Option<String>,
|
||||
|
||||
pub maybe_ratings_positive_count: Option<u32>,
|
||||
pub maybe_ratings_negative_count: Option<u32>,
|
||||
pub maybe_bookmark_count: Option<u32>,
|
||||
|
||||
pub maybe_ietf_language_tag: Option<String>,
|
||||
pub maybe_ietf_primary_language_subtag: Option<String>,
|
||||
pub maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
pub maybe_text_pipeline_type: Option<String>,
|
||||
|
||||
pub version: i32,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub user_deleted_at: Option<DateTime<Utc>>,
|
||||
pub mod_deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
pub async fn get_weight_for_legacy_tts_info(
|
||||
weight_token: &ModelWeightToken,
|
||||
can_see_deleted: bool,
|
||||
mysql_pool: &MySqlPool
|
||||
) -> AnyhowResult<Option<ModelWeightForLegacyTtsInfo>> {
|
||||
let mut connection = mysql_pool.acquire().await?;
|
||||
get_weight_for_legacy_tts_info_with_connection(weight_token, can_see_deleted, &mut connection).await
|
||||
}
|
||||
|
||||
pub async fn get_weight_for_legacy_tts_info_with_connection(
|
||||
weight_token: &ModelWeightToken,
|
||||
can_see_deleted: bool,
|
||||
mysql_connection: &mut PoolConnection<MySql>
|
||||
) -> AnyhowResult<Option<ModelWeightForLegacyTtsInfo>> {
|
||||
let maybe_result = if can_see_deleted {
|
||||
select_include_deleted(weight_token, mysql_connection).await
|
||||
} else {
|
||||
select_without_deleted(weight_token, mysql_connection).await
|
||||
};
|
||||
|
||||
let record: RawWeight = match maybe_result {
|
||||
Ok(record) => record,
|
||||
Err(sqlx::Error::RowNotFound) => {
|
||||
return Ok(None);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error fetching weights by token: {:?}", err);
|
||||
return Err(anyhow!("Error fetching weights by token: {:?}", err));
|
||||
}
|
||||
};
|
||||
|
||||
// unwrap the result
|
||||
|
||||
Ok(
|
||||
Some(ModelWeightForLegacyTtsInfo {
|
||||
token: record.token,
|
||||
title: record.title,
|
||||
weights_type: record.weights_type,
|
||||
weights_category: record.weights_category,
|
||||
maybe_description_markdown: record.maybe_description_markdown,
|
||||
maybe_description_rendered_html: record.maybe_description_rendered_html,
|
||||
creator_user_token: record.creator_user_token,
|
||||
creator_username: record.creator_username,
|
||||
creator_display_name: record.creator_display_name,
|
||||
creator_gravatar_hash: record.creator_gravatar_hash,
|
||||
creator_ip_address: record.creator_ip_address,
|
||||
creator_set_visibility: record.creator_set_visibility,
|
||||
maybe_last_update_user_token: record.maybe_last_update_user_token,
|
||||
original_download_url: record.original_download_url,
|
||||
original_filename: record.original_filename,
|
||||
file_size_bytes: record.file_size_bytes,
|
||||
file_checksum_sha2: record.file_checksum_sha2,
|
||||
public_bucket_hash: record.public_bucket_hash,
|
||||
maybe_public_bucket_prefix: record.maybe_public_bucket_prefix,
|
||||
maybe_public_bucket_extension: record.maybe_public_bucket_extension,
|
||||
maybe_cover_image_public_bucket_hash: record.maybe_cover_image_public_bucket_hash,
|
||||
maybe_cover_image_public_bucket_prefix: record.maybe_cover_image_public_bucket_prefix,
|
||||
maybe_cover_image_public_bucket_extension: record.maybe_cover_image_public_bucket_extension,
|
||||
maybe_ratings_positive_count: record.maybe_ratings_positive_count,
|
||||
maybe_ratings_negative_count: record.maybe_ratings_negative_count,
|
||||
maybe_bookmark_count: record.maybe_bookmark_count,
|
||||
maybe_ietf_language_tag: record.maybe_ietf_language_tag,
|
||||
maybe_ietf_primary_language_subtag: record.maybe_ietf_primary_language_subtag,
|
||||
maybe_default_pretrained_vocoder: record.maybe_default_pretrained_vocoder,
|
||||
maybe_text_pipeline_type: record.maybe_text_pipeline_type,
|
||||
version: record.version,
|
||||
created_at: record.created_at,
|
||||
updated_at: record.updated_at,
|
||||
user_deleted_at: record.user_deleted_at,
|
||||
mod_deleted_at: record.mod_deleted_at,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async fn select_include_deleted(
|
||||
weight_token: &ModelWeightToken,
|
||||
mysql_connection: &mut PoolConnection<MySql>
|
||||
) -> Result<RawWeight, sqlx::Error> {
|
||||
sqlx
|
||||
::query_as!(
|
||||
RawWeight,
|
||||
r#"
|
||||
SELECT
|
||||
wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
|
||||
wt.title,
|
||||
wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
|
||||
wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
|
||||
wt.maybe_description_markdown,
|
||||
wt.maybe_description_rendered_html,
|
||||
|
||||
wt.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,
|
||||
|
||||
wt.creator_ip_address,
|
||||
wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
|
||||
wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
|
||||
wt.original_download_url,
|
||||
wt.original_filename,
|
||||
wt.file_size_bytes,
|
||||
wt.file_checksum_sha2,
|
||||
|
||||
wt.public_bucket_hash,
|
||||
wt.maybe_public_bucket_prefix,
|
||||
wt.maybe_public_bucket_extension,
|
||||
|
||||
cover_image.public_bucket_directory_hash as maybe_cover_image_public_bucket_hash,
|
||||
cover_image.maybe_public_bucket_prefix as maybe_cover_image_public_bucket_prefix,
|
||||
cover_image.maybe_public_bucket_extension as maybe_cover_image_public_bucket_extension,
|
||||
|
||||
entity_stats.ratings_positive_count as maybe_ratings_positive_count,
|
||||
entity_stats.ratings_negative_count as maybe_ratings_negative_count,
|
||||
entity_stats.bookmark_count as maybe_bookmark_count,
|
||||
|
||||
w_extension.ietf_language_tag as maybe_ietf_language_tag,
|
||||
w_extension.ietf_primary_language_subtag as maybe_ietf_primary_language_subtag,
|
||||
w_extension.maybe_default_pretrained_vocoder as `maybe_default_pretrained_vocoder: crate::column_types::vocoder_type::VocoderType`,
|
||||
w_extension.text_pipeline_type as maybe_text_pipeline_type,
|
||||
|
||||
wt.version,
|
||||
wt.created_at,
|
||||
wt.updated_at,
|
||||
wt.user_deleted_at,
|
||||
wt.mod_deleted_at
|
||||
|
||||
FROM model_weights as wt
|
||||
JOIN users
|
||||
ON users.token = wt.creator_user_token
|
||||
LEFT OUTER JOIN media_files as cover_image
|
||||
ON cover_image.token = wt.maybe_cover_image_media_file_token
|
||||
LEFT OUTER JOIN entity_stats
|
||||
ON entity_stats.entity_type = "model_weight"
|
||||
AND entity_stats.entity_token = wt.token
|
||||
|
||||
LEFT OUTER JOIN model_weights_extension_tts_details as w_extension
|
||||
ON w_extension.model_weights_token = wt.token
|
||||
|
||||
WHERE
|
||||
wt.token = ?
|
||||
"#,
|
||||
weight_token.as_str()
|
||||
)
|
||||
.fetch_one(&mut **mysql_connection).await
|
||||
}
|
||||
|
||||
async fn select_without_deleted(
|
||||
weight_token: &ModelWeightToken,
|
||||
mysql_connection: &mut PoolConnection<MySql>
|
||||
) -> Result<RawWeight, sqlx::Error> {
|
||||
//as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
|
||||
//as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`
|
||||
sqlx
|
||||
::query_as!(
|
||||
RawWeight,
|
||||
r#"
|
||||
SELECT
|
||||
wt.token as `token: tokens::tokens::model_weights::ModelWeightToken`,
|
||||
wt.title,
|
||||
wt.weights_type as `weights_type: enums::by_table::model_weights::weights_types::WeightsType`,
|
||||
wt.weights_category as `weights_category: enums::by_table::model_weights::weights_category::WeightsCategory`,
|
||||
wt.maybe_description_markdown,
|
||||
wt.maybe_description_rendered_html,
|
||||
wt.creator_ip_address,
|
||||
wt.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
|
||||
|
||||
wt.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,
|
||||
|
||||
wt.maybe_last_update_user_token as `maybe_last_update_user_token: tokens::tokens::users::UserToken`,
|
||||
wt.original_download_url,
|
||||
wt.original_filename,
|
||||
wt.file_size_bytes,
|
||||
wt.file_checksum_sha2,
|
||||
wt.public_bucket_hash,
|
||||
wt.maybe_public_bucket_prefix,
|
||||
wt.maybe_public_bucket_extension,
|
||||
|
||||
cover_image.public_bucket_directory_hash as maybe_cover_image_public_bucket_hash,
|
||||
cover_image.maybe_public_bucket_prefix as maybe_cover_image_public_bucket_prefix,
|
||||
cover_image.maybe_public_bucket_extension as maybe_cover_image_public_bucket_extension,
|
||||
|
||||
entity_stats.ratings_positive_count as maybe_ratings_positive_count,
|
||||
entity_stats.ratings_negative_count as maybe_ratings_negative_count,
|
||||
entity_stats.bookmark_count as maybe_bookmark_count,
|
||||
|
||||
w_extension.ietf_language_tag as maybe_ietf_language_tag,
|
||||
w_extension.ietf_primary_language_subtag as maybe_ietf_primary_language_subtag,
|
||||
w_extension.maybe_default_pretrained_vocoder as `maybe_default_pretrained_vocoder: crate::column_types::vocoder_type::VocoderType`,
|
||||
w_extension.text_pipeline_type as maybe_text_pipeline_type,
|
||||
|
||||
wt.version,
|
||||
wt.created_at,
|
||||
wt.updated_at,
|
||||
wt.user_deleted_at,
|
||||
wt.mod_deleted_at
|
||||
|
||||
FROM model_weights as wt
|
||||
JOIN users
|
||||
ON users.token = wt.creator_user_token
|
||||
LEFT OUTER JOIN media_files as cover_image
|
||||
ON cover_image.token = wt.maybe_cover_image_media_file_token
|
||||
LEFT OUTER JOIN entity_stats
|
||||
ON entity_stats.entity_type = "model_weight"
|
||||
AND entity_stats.entity_token = wt.token
|
||||
|
||||
LEFT OUTER JOIN model_weights_extension_tts_details as w_extension
|
||||
ON w_extension.model_weights_token = wt.token
|
||||
|
||||
WHERE
|
||||
wt.token = ?
|
||||
AND wt.user_deleted_at IS NULL
|
||||
AND wt.mod_deleted_at IS NULL
|
||||
"#,
|
||||
weight_token.as_str()
|
||||
)
|
||||
.fetch_one(&mut **mysql_connection).await
|
||||
}
|
||||
|
||||
// RawWeight is the struct that is returned from the database in raw form.
|
||||
#[derive(Serialize)]
|
||||
pub struct RawWeight {
|
||||
pub token: ModelWeightToken,
|
||||
pub title: String,
|
||||
pub weights_type: WeightsType,
|
||||
pub weights_category: WeightsCategory,
|
||||
pub maybe_description_markdown: Option<String>,
|
||||
pub maybe_description_rendered_html: Option<String>,
|
||||
|
||||
pub creator_user_token: UserToken,
|
||||
pub creator_username: String,
|
||||
pub creator_display_name: String,
|
||||
pub creator_gravatar_hash: String,
|
||||
|
||||
pub creator_ip_address: String,
|
||||
pub creator_set_visibility: Visibility,
|
||||
pub maybe_last_update_user_token: Option<UserToken>,
|
||||
pub original_download_url: Option<String>,
|
||||
pub original_filename: Option<String>,
|
||||
pub file_size_bytes: i32,
|
||||
pub file_checksum_sha2: String,
|
||||
pub public_bucket_hash: String,
|
||||
pub maybe_public_bucket_prefix: Option<String>,
|
||||
pub maybe_public_bucket_extension: Option<String>,
|
||||
|
||||
pub maybe_cover_image_public_bucket_hash: Option<String>,
|
||||
pub maybe_cover_image_public_bucket_prefix: Option<String>,
|
||||
pub maybe_cover_image_public_bucket_extension: Option<String>,
|
||||
|
||||
pub maybe_ratings_positive_count: Option<u32>,
|
||||
pub maybe_ratings_negative_count: Option<u32>,
|
||||
pub maybe_bookmark_count: Option<u32>,
|
||||
|
||||
pub maybe_ietf_language_tag: Option<String>,
|
||||
pub maybe_ietf_primary_language_subtag: Option<String>,
|
||||
pub maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
pub maybe_text_pipeline_type: Option<String>,
|
||||
|
||||
pub version: i32,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub user_deleted_at: Option<DateTime<Utc>>,
|
||||
pub mod_deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod get_weight;
|
||||
pub mod get_weight_for_legacy_tts_enqueue;
|
||||
pub mod get_weight_for_legacy_tts_info;
|
||||
@@ -9,8 +9,12 @@ impl RedisCacheKeys {
|
||||
format!("get_tts_model:{}", model_token)
|
||||
}
|
||||
|
||||
pub fn get_tts_model_for_info_migration_endpoint(model_token: &str) -> String {
|
||||
format!("get_tts_inf1:{}", model_token)
|
||||
}
|
||||
|
||||
pub fn get_tts_model_for_inference_migration_endpoint(model_token: &str) -> String {
|
||||
format!("get_tts_inf:{}", model_token)
|
||||
format!("get_tts_inf2:{}", model_token)
|
||||
}
|
||||
|
||||
pub fn get_unified_queue_stats_endpoint() -> &'static str {
|
||||
|
||||
@@ -16,8 +16,8 @@ use log::warn;
|
||||
use enums::by_table::tts_models::tts_model_type::TtsModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use migration::text_to_speech::get_tts_model_info_migration::get_tts_model_info_migration;
|
||||
use mysql_queries::column_types::vocoder_type::VocoderType;
|
||||
use mysql_queries::queries::tts::tts_models::get_tts_model::get_tts_model_by_token_using_connection;
|
||||
use redis_common::redis_cache_keys::RedisCacheKeys;
|
||||
use tts_common::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic;
|
||||
use tts_common::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
@@ -204,13 +204,16 @@ pub async fn get_tts_model_handler(
|
||||
|
||||
let model_token = path.token.clone();
|
||||
|
||||
let switch_to_weights_flag = server_state.flags.switch_tts_to_model_weights;
|
||||
|
||||
let get_tts_model = move || {
|
||||
// NB: async closures are not yet stable in Rust, so we include an async block.
|
||||
async move {
|
||||
get_tts_model_by_token_using_connection(
|
||||
get_tts_model_info_migration(
|
||||
&model_token,
|
||||
show_deleted_models,
|
||||
&mut mysql_connection,
|
||||
show_deleted_models,
|
||||
switch_to_weights_flag,
|
||||
).await
|
||||
}
|
||||
};
|
||||
@@ -221,14 +224,14 @@ pub async fn get_tts_model_handler(
|
||||
get_tts_model().await
|
||||
}
|
||||
Ok(mut redis_ttl_cache) => {
|
||||
let cache_key = RedisCacheKeys::get_tts_model_endpoint(&path.token);
|
||||
let cache_key = RedisCacheKeys::get_tts_model_for_info_migration_endpoint(&path.token);
|
||||
redis_ttl_cache.lazy_load_if_not_cached(&cache_key, move || {
|
||||
get_tts_model()
|
||||
}).await
|
||||
}
|
||||
};
|
||||
|
||||
let mut model = match model_query_result {
|
||||
let model = match model_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(GetTtsModelError::ServerError);
|
||||
@@ -238,22 +241,24 @@ pub async fn get_tts_model_handler(
|
||||
};
|
||||
|
||||
if let Some(user_session) = &maybe_user_session {
|
||||
is_original_author = user_session.user_token == model.creator_user_token;
|
||||
is_original_author = user_session.user_token == model.creator_user_token();
|
||||
}
|
||||
|
||||
if let Some(moderator_fields) = model.maybe_moderator_fields.as_ref() {
|
||||
// NB: The moderator fields will always be present before removal
|
||||
// We don't want non-mods seeing stuff made by banned users.
|
||||
if moderator_fields.creator_is_banned && !is_moderator {
|
||||
return Err(GetTtsModelError::NotFound);
|
||||
}
|
||||
}
|
||||
// NB(bt, 2024-01-20): Removing to make porting easier.
|
||||
//if let Some(moderator_fields) = model.maybe_moderator_fields.as_ref() {
|
||||
// // NB: The moderator fields will always be present before removal
|
||||
// // We don't want non-mods seeing stuff made by banned users.
|
||||
// if moderator_fields.creator_is_banned && !is_moderator {
|
||||
// return Err(GetTtsModelError::NotFound);
|
||||
// }
|
||||
//}
|
||||
|
||||
if !is_moderator {
|
||||
model.maybe_moderator_fields = None;
|
||||
}
|
||||
// NB(bt, 2024-01-20): Removing to make porting easier.
|
||||
//if !is_moderator {
|
||||
// model.maybe_moderator_fields = None;
|
||||
//}
|
||||
|
||||
let text_pipeline_type = model.text_pipeline_type
|
||||
let text_pipeline_type = model.text_pipeline_type()
|
||||
.as_deref()
|
||||
.and_then(|pipeline_type| {
|
||||
// If there's an error deserializing, turn it to None instead of 500ing. The column is
|
||||
@@ -273,64 +278,68 @@ pub async fn get_tts_model_handler(
|
||||
|
||||
// TODO: Use language to infer as well.
|
||||
let text_pipeline_type_guess =
|
||||
guess_text_pipeline_heuristic(Some(model.created_at.clone()));
|
||||
guess_text_pipeline_heuristic(Some(model.created_at().clone()));
|
||||
|
||||
// Map to public response type.
|
||||
let response = GetTtsModelSuccessResponse {
|
||||
success: true,
|
||||
model: TtsModelInfo {
|
||||
model_token: model.model_token,
|
||||
tts_model_type: model.tts_model_type,
|
||||
model_token: model.token().to_string(),
|
||||
tts_model_type: model.tts_model_type(),
|
||||
text_pipeline_type,
|
||||
text_pipeline_type_guess,
|
||||
maybe_custom_vocoder: match model.maybe_custom_vocoder {
|
||||
None => None,
|
||||
Some(vocoder) => Some(CustomVocoderInfo {
|
||||
vocoder_token: vocoder.vocoder_token,
|
||||
vocoder_title: vocoder.vocoder_title,
|
||||
creator_user_token: vocoder.creator_user_token,
|
||||
creator_username: vocoder.creator_username,
|
||||
creator_display_name: vocoder.creator_display_name,
|
||||
creator_gravatar_hash: vocoder.creator_gravatar_hash,
|
||||
})
|
||||
},
|
||||
maybe_default_pretrained_vocoder: model.maybe_default_pretrained_vocoder,
|
||||
text_preprocessing_algorithm: model.text_preprocessing_algorithm,
|
||||
creator_user_token: model.creator_user_token,
|
||||
creator_username: model.creator_username.to_string(), // NB: Cloned because of ref use for avatar below
|
||||
creator_display_name: model.creator_display_name,
|
||||
creator_gravatar_hash: model.creator_gravatar_hash,
|
||||
creator_default_avatar_index: default_avatar_from_username(&model.creator_username),
|
||||
creator_default_avatar_color_index: default_avatar_color_from_username(&model.creator_username),
|
||||
title: model.title,
|
||||
description_markdown: model.description_markdown,
|
||||
description_rendered_html: model.description_rendered_html,
|
||||
ietf_language_tag: model.ietf_language_tag,
|
||||
ietf_primary_language_subtag: model.ietf_primary_language_subtag,
|
||||
is_front_page_featured: model.is_front_page_featured,
|
||||
is_twitch_featured: model.is_twitch_featured,
|
||||
maybe_suggested_unique_bot_command: model.maybe_suggested_unique_bot_command,
|
||||
// NB(bt, 2024-01-20): We won't be needing these much longer.
|
||||
maybe_custom_vocoder: None,
|
||||
//maybe_custom_vocoder: match model.maybe_custom_vocoder {
|
||||
// None => None,
|
||||
// Some(vocoder) => Some(CustomVocoderInfo {
|
||||
// vocoder_token: vocoder.vocoder_token,
|
||||
// vocoder_title: vocoder.vocoder_title,
|
||||
// creator_user_token: vocoder.creator_user_token,
|
||||
// creator_username: vocoder.creator_username,
|
||||
// creator_display_name: vocoder.creator_display_name,
|
||||
// creator_gravatar_hash: vocoder.creator_gravatar_hash,
|
||||
// })
|
||||
//},
|
||||
maybe_default_pretrained_vocoder: model.maybe_default_pretrained_vocoder(),
|
||||
text_preprocessing_algorithm: model.text_preprocessing_algorithm().to_string(),
|
||||
creator_user_token: model.creator_user_token().to_string(),
|
||||
creator_username: model.creator_username().to_string(), // NB: Cloned because of ref use for avatar below
|
||||
creator_display_name: model.creator_display_name().to_string(),
|
||||
creator_gravatar_hash: model.creator_gravatar_hash().to_string(),
|
||||
creator_default_avatar_index: default_avatar_from_username(&model.creator_username().to_string()),
|
||||
creator_default_avatar_color_index: default_avatar_color_from_username(&model.creator_username().to_string()),
|
||||
title: model.title().to_string(),
|
||||
description_markdown: model.description_markdown().to_string(),
|
||||
description_rendered_html: model.description_rendered_html().to_string(),
|
||||
ietf_language_tag: model.ietf_language_tag().to_string(),
|
||||
ietf_primary_language_subtag: model.ietf_primary_language_subtag().to_string(),
|
||||
is_front_page_featured: model.is_front_page_featured(),
|
||||
is_twitch_featured: model.is_twitch_featured(),
|
||||
maybe_suggested_unique_bot_command: model.maybe_suggested_unique_bot_command().map(|s| s.to_string()),
|
||||
user_ratings: UserRatingsStats {
|
||||
positive_count: model.user_ratings_positive_count,
|
||||
negative_count: model.user_ratings_negative_count,
|
||||
total_count: model.user_ratings_total_count,
|
||||
positive_count: model.user_ratings_positive_count(),
|
||||
negative_count: model.user_ratings_negative_count(),
|
||||
total_count: model.user_ratings_total_count(),
|
||||
},
|
||||
creator_set_visibility: model.creator_set_visibility,
|
||||
is_locked_from_use: model.is_locked_from_use,
|
||||
is_locked_from_user_modification: model.is_locked_from_user_modification,
|
||||
created_at: model.created_at,
|
||||
updated_at: model.updated_at,
|
||||
maybe_moderator_fields: model.maybe_moderator_fields.map(|mod_fields| {
|
||||
TtsModelModeratorFieldInfo {
|
||||
use_default_m_factor: mod_fields.use_default_mel_multiply_factor,
|
||||
maybe_custom_m_factor: mod_fields.maybe_custom_mel_multiply_factor,
|
||||
creator_is_banned: mod_fields.creator_is_banned,
|
||||
creator_ip_address_creation: mod_fields.creator_ip_address_creation,
|
||||
creator_ip_address_last_update: mod_fields.creator_ip_address_last_update,
|
||||
user_deleted_at: mod_fields.user_deleted_at,
|
||||
mod_deleted_at: mod_fields.mod_deleted_at,
|
||||
}
|
||||
})
|
||||
creator_set_visibility: model.creator_set_visibility(),
|
||||
is_locked_from_use: model.is_locked_from_use(),
|
||||
is_locked_from_user_modification: model.is_locked_from_user_modification(),
|
||||
created_at: model.created_at().clone(),
|
||||
updated_at: model.updated_at().clone(),
|
||||
maybe_moderator_fields: None,
|
||||
// NB(bt, 2024-01-20): We won't be needing these much longer.
|
||||
//maybe_moderator_fields: model.maybe_moderator_fields.map(|mod_fields| {
|
||||
// TtsModelModeratorFieldInfo {
|
||||
// use_default_m_factor: mod_fields.use_default_mel_multiply_factor,
|
||||
// maybe_custom_m_factor: mod_fields.maybe_custom_mel_multiply_factor,
|
||||
// creator_is_banned: mod_fields.creator_is_banned,
|
||||
// creator_ip_address_creation: mod_fields.creator_ip_address_creation,
|
||||
// creator_ip_address_last_update: mod_fields.creator_ip_address_last_update,
|
||||
// user_deleted_at: mod_fields.user_deleted_at,
|
||||
// mod_deleted_at: mod_fields.mod_deleted_at,
|
||||
// }
|
||||
//})
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user