mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-02 00:18:17 +00:00
Edit TTS model with text pipeline type
This commit is contained in:
1 parent
f75f55fa22
commit
b801f7c19e
7 files changed
+54
-40
No files matched your search
@@ -14,6 +14,7 @@ pub async fn edit_tts_model_details_as_author(
|
||||
ietf_primary_language_subtag: &str,
|
||||
creator_set_visibility: RecordVisibility,
|
||||
maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
text_pipeline_type: Option<&str>,
|
||||
// Author fields
|
||||
author_ip_address: &str,
|
||||
) -> Result<MySqlQueryResult, sqlx::Error> {
|
||||
@@ -23,6 +24,7 @@ pub async fn edit_tts_model_details_as_author(
|
||||
UPDATE tts_models
|
||||
SET
|
||||
maybe_default_pretrained_vocoder = ?,
|
||||
text_pipeline_type = ?,
|
||||
title = ?,
|
||||
description_markdown = ?,
|
||||
description_rendered_html = ?,
|
||||
@@ -35,6 +37,7 @@ WHERE token = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
maybe_default_pretrained_vocoder.map(|v| v.to_str()),
|
||||
text_pipeline_type,
|
||||
title,
|
||||
description_markdown,
|
||||
description_html,
|
||||
@@ -58,6 +61,7 @@ pub async fn edit_tts_model_details_as_mod(
|
||||
ietf_primary_language_subtag: &str,
|
||||
creator_set_visibility: RecordVisibility,
|
||||
maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
text_pipeline_type: Option<&str>,
|
||||
// moderator fields
|
||||
moderator_user_token: &str,
|
||||
) -> Result<MySqlQueryResult, sqlx::Error> {
|
||||
@@ -67,6 +71,7 @@ pub async fn edit_tts_model_details_as_mod(
|
||||
UPDATE tts_models
|
||||
SET
|
||||
maybe_default_pretrained_vocoder = ?,
|
||||
text_pipeline_type = ?,
|
||||
title = ?,
|
||||
description_markdown = ?,
|
||||
description_rendered_html = ?,
|
||||
@@ -79,6 +84,7 @@ WHERE token = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
maybe_default_pretrained_vocoder.map(|v| v.to_str()),
|
||||
text_pipeline_type,
|
||||
title,
|
||||
description_markdown,
|
||||
description_html,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::ops::Deref;
|
||||
use chrono::{DateTime, Utc};
|
||||
use once_cell::sync::Lazy;
|
||||
use crate::text_pipelines::text_pipeline::TtsTextPipeline;
|
||||
use crate::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
|
||||
const ENGLISH_V1_EPOCH_STR : &'static str = "2022-05-01T00:00:00.00Z";
|
||||
|
||||
@@ -20,28 +20,28 @@ static ENGLISH_V1_EPOCH : Lazy<DateTime<Utc>> = Lazy::new(|| {
|
||||
/// There will always be a guess returned.
|
||||
///
|
||||
/// maybe_model_created_at - `created_at` timestamp from database
|
||||
pub fn guess_text_pipeline_heuristic(maybe_model_created_at: Option<DateTime<Utc>>) -> TtsTextPipeline {
|
||||
pub fn guess_text_pipeline_heuristic(maybe_model_created_at: Option<DateTime<Utc>>) -> TextPipelineType {
|
||||
|
||||
// TODO: Use language to infer as well.
|
||||
|
||||
if let Some(created_at) = maybe_model_created_at {
|
||||
if created_at < *ENGLISH_V1_EPOCH {
|
||||
return TtsTextPipeline::LegacyFakeYou;
|
||||
return TextPipelineType::LegacyFakeYou;
|
||||
}
|
||||
}
|
||||
|
||||
TtsTextPipeline::EnglishV1
|
||||
TextPipelineType::EnglishV1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::{DateTime, Utc};
|
||||
use crate::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic;
|
||||
use crate::text_pipelines::text_pipeline::TtsTextPipeline;
|
||||
use crate::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
|
||||
#[test]
|
||||
fn new_models_just_created_with_no_date_use_english_v1() {
|
||||
assert_eq!(guess_text_pipeline_heuristic(None), TtsTextPipeline::EnglishV1);
|
||||
assert_eq!(guess_text_pipeline_heuristic(None), TextPipelineType::EnglishV1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -49,7 +49,7 @@ mod tests {
|
||||
let datetime = DateTime::parse_from_rfc3339("2022-07-01T00:00:00.00Z")
|
||||
.expect("should parse")
|
||||
.with_timezone(&Utc);
|
||||
assert_eq!(guess_text_pipeline_heuristic(Some(datetime)), TtsTextPipeline::EnglishV1);
|
||||
assert_eq!(guess_text_pipeline_heuristic(Some(datetime)), TextPipelineType::EnglishV1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -57,6 +57,6 @@ mod tests {
|
||||
let datetime = DateTime::parse_from_rfc3339("2022-01-01T00:00:00.00Z")
|
||||
.expect("should parse")
|
||||
.with_timezone(&Utc);
|
||||
assert_eq!(guess_text_pipeline_heuristic(Some(datetime)), TtsTextPipeline::LegacyFakeYou);
|
||||
assert_eq!(guess_text_pipeline_heuristic(Some(datetime)), TextPipelineType::LegacyFakeYou);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
pub mod guess_pipeline;
|
||||
pub mod text_pipeline;
|
||||
pub mod text_pipeline_type;
|
||||
+23
-23
@@ -7,7 +7,7 @@ use container_common::anyhow_result::AnyhowResult;
|
||||
/// This is *not* a database enum, but the text serializations get stored in the database in a
|
||||
/// varchar field and communicated over the API.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum TtsTextPipeline {
|
||||
pub enum TextPipelineType {
|
||||
|
||||
// TODO: Introduce old vocodes models.
|
||||
//#[serde(rename = "legacy_vocodes")]
|
||||
@@ -46,7 +46,7 @@ const ENGLISH_V1 : &'static str = "english_v1";
|
||||
const SPANISH_V1 : &'static str = "spanish_v1";
|
||||
const SPANISH_V2 : &'static str = "spanish_v2";
|
||||
|
||||
impl TtsTextPipeline {
|
||||
impl TextPipelineType {
|
||||
|
||||
/// Check if the text pipeline name is valid and supported.
|
||||
pub fn is_valid_name(tts_text_pipeline: &str) -> bool {
|
||||
@@ -57,10 +57,10 @@ impl TtsTextPipeline {
|
||||
// `serde_variant` looks like a fix, but it's GPL3.
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
TtsTextPipeline::LegacyFakeYou => LEGACY_FAKEYOU,
|
||||
TtsTextPipeline::EnglishV1 => ENGLISH_V1,
|
||||
TtsTextPipeline::SpanishV1 => SPANISH_V1,
|
||||
TtsTextPipeline::SpanishV2 => SPANISH_V2,
|
||||
TextPipelineType::LegacyFakeYou => LEGACY_FAKEYOU,
|
||||
TextPipelineType::EnglishV1 => ENGLISH_V1,
|
||||
TextPipelineType::SpanishV1 => SPANISH_V1,
|
||||
TextPipelineType::SpanishV2 => SPANISH_V2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,36 +77,36 @@ impl TtsTextPipeline {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::text_pipelines::text_pipeline::TtsTextPipeline;
|
||||
use crate::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
|
||||
#[test]
|
||||
fn valid_text_pipeline_names() {
|
||||
assert!(TtsTextPipeline::is_valid_name("legacy_fakeyou"));
|
||||
assert!(TtsTextPipeline::is_valid_name("english_v1"));
|
||||
assert!(TtsTextPipeline::is_valid_name("spanish_v1"));
|
||||
assert!(TtsTextPipeline::is_valid_name("spanish_v2"));
|
||||
assert!(TextPipelineType::is_valid_name("legacy_fakeyou"));
|
||||
assert!(TextPipelineType::is_valid_name("english_v1"));
|
||||
assert!(TextPipelineType::is_valid_name("spanish_v1"));
|
||||
assert!(TextPipelineType::is_valid_name("spanish_v2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_text_pipeline_names() {
|
||||
// Garbage
|
||||
assert!(!TtsTextPipeline::is_valid_name(""));
|
||||
assert!(!TtsTextPipeline::is_valid_name("asdf"));
|
||||
assert!(!TextPipelineType::is_valid_name(""));
|
||||
assert!(!TextPipelineType::is_valid_name("asdf"));
|
||||
|
||||
// NB: Must be lower case
|
||||
assert!(!TtsTextPipeline::is_valid_name("LEGACY_FAKEYOU"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("ENGLISH_V1"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("SPANISH_V1"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("SPANISH_V2"));
|
||||
assert!(!TextPipelineType::is_valid_name("LEGACY_FAKEYOU"));
|
||||
assert!(!TextPipelineType::is_valid_name("ENGLISH_V1"));
|
||||
assert!(!TextPipelineType::is_valid_name("SPANISH_V1"));
|
||||
assert!(!TextPipelineType::is_valid_name("SPANISH_V2"));
|
||||
|
||||
// NB: Not yet supported
|
||||
assert!(!TtsTextPipeline::is_valid_name("legacy_vocodes"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("spanish_v3"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("english_v2"));
|
||||
assert!(!TextPipelineType::is_valid_name("legacy_vocodes"));
|
||||
assert!(!TextPipelineType::is_valid_name("spanish_v3"));
|
||||
assert!(!TextPipelineType::is_valid_name("english_v2"));
|
||||
|
||||
// Wrong names
|
||||
assert!(!TtsTextPipeline::is_valid_name("english"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("spanish"));
|
||||
assert!(!TtsTextPipeline::is_valid_name("vocodes"));
|
||||
assert!(!TextPipelineType::is_valid_name("english"));
|
||||
assert!(!TextPipelineType::is_valid_name("spanish"));
|
||||
assert!(!TextPipelineType::is_valid_name("vocodes"));
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use database_queries::queries::tts::tts_models::edit_tts_model_details::{edit_tts_model_details_as_author, edit_tts_model_details_as_mod};
|
||||
use database_queries::queries::tts::tts_models::edit_tts_model_moderator_details::edit_tts_model_moderator_details;
|
||||
use tts_common::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
use user_input_common::check_for_slurs::contains_slurs;
|
||||
|
||||
const DEFAULT_IETF_LANGUAGE_TAG : &'static str = "en-US";
|
||||
@@ -47,11 +48,13 @@ pub struct EditTtsModelRequest {
|
||||
pub creator_set_visibility: Option<String>,
|
||||
pub maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
|
||||
// Text pipeline won't be set by default on model upload (for now),
|
||||
// and a lot of existing models will have null values.
|
||||
pub text_pipeline_type: Option<TextPipelineType>,
|
||||
|
||||
// NB: We calculate 'ietf_primary_language_subtag' from this value.
|
||||
pub ietf_language_tag: Option<String>,
|
||||
|
||||
pub text_pipeline_type: Option<String>,
|
||||
|
||||
//pub updatable_slug: Option<String>,
|
||||
//pub tts_model_type: Option<String>,
|
||||
//pub vocoder_token: Option<String>,
|
||||
@@ -245,6 +248,9 @@ pub async fn edit_tts_model_handler(
|
||||
maybe_default_pretrained_vocoder = Some(vocoder);
|
||||
}
|
||||
|
||||
let text_pipeline_type = request.text_pipeline_type
|
||||
.map(|pipeline_type| pipeline_type.to_str());
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
|
||||
let query_result = if is_author {
|
||||
@@ -259,6 +265,7 @@ pub async fn edit_tts_model_handler(
|
||||
&ietf_primary_language_subtag,
|
||||
creator_set_visibility,
|
||||
maybe_default_pretrained_vocoder,
|
||||
text_pipeline_type,
|
||||
&ip_address,
|
||||
).await
|
||||
} else {
|
||||
@@ -273,6 +280,7 @@ pub async fn edit_tts_model_handler(
|
||||
&ietf_primary_language_subtag,
|
||||
creator_set_visibility,
|
||||
maybe_default_pretrained_vocoder,
|
||||
text_pipeline_type,
|
||||
&user_session.user_token,
|
||||
).await
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ use sqlx::mysql::MySqlDatabaseError;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use tts_common::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic;
|
||||
use tts_common::text_pipelines::text_pipeline::TtsTextPipeline;
|
||||
use tts_common::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -50,8 +50,8 @@ pub struct TtsModelInfo {
|
||||
///
|
||||
/// >> NB: text_pipeline_type may not always be present in the database, but if absent we'll
|
||||
/// inform the frontend (and inference pipeline) of our best guess according to a heuristic.
|
||||
pub text_pipeline_type: Option<TtsTextPipeline>,
|
||||
pub text_pipeline_type_guess: TtsTextPipeline,
|
||||
pub text_pipeline_type: Option<TextPipelineType>,
|
||||
pub text_pipeline_type_guess: TextPipelineType,
|
||||
|
||||
pub maybe_default_pretrained_vocoder: Option<VocoderType>,
|
||||
pub text_preprocessing_algorithm: String,
|
||||
@@ -187,7 +187,7 @@ pub async fn get_tts_model_handler(
|
||||
// If there's an error deserializing, turn it to None.
|
||||
let text_pipeline_type = model.text_pipeline_type
|
||||
.as_deref()
|
||||
.and_then(|pipeline_type| TtsTextPipeline::from_str(pipeline_type).ok());
|
||||
.and_then(|pipeline_type| TextPipelineType::from_str(pipeline_type).ok());
|
||||
|
||||
// TODO: Use language to infer as well.
|
||||
let text_pipeline_type_guess =
|
||||
|
||||
@@ -51,7 +51,7 @@ use storage_buckets_common::bucket_path_unifier::BucketPathUnifier;
|
||||
use tempdir::TempDir;
|
||||
use tts_common::clean_symbols::clean_symbols;
|
||||
use tts_common::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic;
|
||||
use tts_common::text_pipelines::text_pipeline::TtsTextPipeline;
|
||||
use tts_common::text_pipelines::text_pipeline_type::TextPipelineType;
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
struct FileMetadata {
|
||||
@@ -327,7 +327,7 @@ pub async fn process_single_job(
|
||||
let text_pipeline_type_or_guess = model_record.text_pipeline_type
|
||||
.as_deref()
|
||||
.and_then(|pipeline_type|
|
||||
TtsTextPipeline::from_str(pipeline_type).ok())// NB: If there's an error deserializing, turn it to None.
|
||||
TextPipelineType::from_str(pipeline_type).ok())// NB: If there's an error deserializing, turn it to None.
|
||||
.unwrap_or_else(||
|
||||
guess_text_pipeline_heuristic(Some(model_record.created_at)));
|
||||
|
||||
|
||||
Reference in new issue
Block a user