Closed qwerty2501 closed 1 year ago
確かにvvmファイルから読み込むことを考えるとmodelを隠蔽しきるのは無理ですね。 しかしModelSetについてはやはり必要性が感じられないと思います。 下手に抽象化せず、Model structとして読み込んだほうが良いのかも?
ModelSetができることは、VoicevoxCoreでもできるModelの隠蔽(unloadは不可なのも一緒)なので、とりあえず考えるのはModelを隠蔽するかしないか決まったあとが良さそうかもです
今Model隠蔽周り整理すると、一応この3択ですよね( https://github.com/VOICEVOX/voicevox_core/issues/280#issuecomment-1252395184 とほぼ同じですが )
3はまあいったん1と同じとみなして除外で良さそうとして、1か2を考えるにはこの議論より外のモチベーションを整理する必要があるのかなと思いました。 まず2でいく結論を出すには、ユースケースの洗い出しをすれば可能な気がします。が、実際洗い出すのは結構厳しいので、ちょっと考えてえいやで決める形になりそう。 1でいく結論を出すにも、コアの配布目的である「使ってもらうため」に反するのでなかなか厳しく、こちらもえいやで決める形になりそう・・・。
いったんペンディングにして、別の観点を見つけたり、違う論点を探すのもありかも。
別の観点なのですが、ModelのことをVoiceSetと呼ぶとわかりやすくなったりしませんかね。 声がいっぱいあるなにか、という説明です。これなら複数話者の声が入っていても不思議ではないのかなぁと。
まあ、いろんな話者の声が同じVoiceSetにあるのはそこそこ直感できそうですが、同じ話者の別の声が別のVoiceSetにあるのは直感に反するかもなのですが・・・。
@Hiroshiba 3 についてですが、unloadについてもVoiceを引数に与えるかたちでユーザーにわかりやすい実装はできそうなのですが、問題となってるのはファイルからvvmファイルをロードする際にどうしてもModelを意識せざるを得ずに隠蔽しきれなくなってしまうことだと思います。
別の観点なのですが、ModelのことをVoiceSetと呼ぶとわかりやすくなったりしませんかね。 声がいっぱいあるなにか、という説明です。これなら複数話者の声が入っていても不思議ではないのかなぁと。
もとがコアドメインではない機械学習文脈のModelでそれを無理やり名前変えただけとも見れなくもないので妥当かどうかは判断が難しいですね。 すくなくとも見極める時間は必要かと。
ペンディングについては私も賛成です。
もとがコアドメインではない機械学習文脈のModelでそれを無理やり名前変えただけとも見れなくもないので妥当かどうかは判断が難しいですね。
たしかに、なぜその声の組み合わせなのかを完璧に説明できるのは結局Modelなので、謎感は残りそうですね・・・ まあでも、少なくともModelを意識する必要はなくなり、用意された声セットをとりあえずやりくりせざるを得ないんだなと、わかりやすくなるかもです。(使いやすくはなってないですが・・・。)
ちょっと通り過ぎちゃったのですがこちらの
これですが、「どのvoiceのために今loadされているのか」の情報が無いと駄目ですね。じゃないとある声に対するunloadで無条件でモデルがunloadされてしまい、ModelSetで扱うメリットが皆無になります。
というのの、voiceごとにユーザーがloadしたのかフラグを持つのも面白いアイデアだなと思いました。 (別のvoiceをloadしたら、同じModelに所属するものも一緒に使えるようになる形を想像していたので) まあ結局Modelを隠蔽するのかしないのか問題に帰着するのでこちらもペンディングになっちゃいますが・・・。
fileでまとめるのをModelにするかVoiceSetにするかで変わってきそうですね。 VoiceSet
にするなら Model
は隠蔽路線だし、 fileを Model
として扱うなら他のAPIも Model
を意識させたほうが良いでしょう
あれ、また認識違いがあるかも・・・? 僕の中ではVoiceSet==Model(ただの別名)だったのですが、 @qwerty2501 さんの中では違ってそうな印象を受けました。 VoiceSet==「1つ以上のModelが含まれるなにか」とかでしたら納得です!
いえ、私も VoiceSet==Modelであると思ってますがなにが引っかかりましたか?
なるほどです! 引っかかったのはfileでまとめるのをModelにするかVoiceSetにするか、の部分です。 どちらも中身は同じなので、ファイル構造も同じになる印象でした。 メタ情報が含まれてるが含まれてないか、などの違いでしょうか。(どちらもメタ情報は含んでる想定でした)
私もメタ情報はどちらになったとしても含まれると思ってます
fileかどうかは気にせずにModelをそのままModelとするかVoiceSetとするか
という説明で納得しました! おっしゃるとおり、隠蔽路線にしたければVoiceSet、モデルを意識させたいならModelだと思います
@Hiroshiba そういえばこの議論いつ頃再開できそうですかね? 0.14リリースするときにC APIをこの議論を反映した形にするのかどうかも決めたほうが良いかも
もう再開できると思います!
設計を決める上での制約として1つ思いついたのですが、今のAPIはそのまま提供できたほうが良いかなと思いました。 (まあこれはModelにするかVoiceSetにするかとはあまり関係ないのですが、一応の共有な感じです!)
かなり前の議論になってしまったのでdiscordでのまとめを転載
つまるところこの二択のどっち行くよという話だった気が。 「モデルを直接ロード・パージできるように、Modelクラスを作ってmodel_indexやmodel_keyで制御する」 「ボイスを暗黙的にロード・パージできるように、VoiceSetクラスを作ってvoice_indexやvoice_keyで制御する」 前者はユーザーにとってあまり関心のないモデルを意識しないといけないが、慣れてくると直感的。 後者はユーザーにとって関心のあるボイスを意識すればいいけど、拘ったことしようとすると結局モデルを意識しないといけなくなる。
@Hiroshiba
VoiceSetについてですが、これはもともとModelSetだったものであり、一つのVoiceSetには 一つのdecode.onnxと一つのpredict_curation.onnxと一つのpredict_intonation.onnx とmetas.jsonが含まれているということで良かったでしたっけ?
いや、VoiceSetなので複数のonnxファイルが含まれている感じですかね
あ、前の文脈ではModel==VoiceSetでした!(1モデルに複数の声が含まれてるので)
では入ってる内容としてはこれであってます?
一つのdecode.onnxと一つのpredict_curation.onnxと一つのpredict_intonation.onnx とmetas.json
合ってます!! 個人的には(ちょっと冗長ですが)こんな感じの構成で良いのではとちょっと思っています。
それを見る限りVoiceSetとModelは別物に見えますが定義を変えるということでしょうか? Model==VoiceSetなんですよね?
Model==VoiceSetなんですよね?
ですね、以前の定義ではそうです!
話が飛躍してしまいました。 今のVOICEVOX CORE APIみたいな形のManagerは作るべきだと思っています。APIを今までとなるべく変わらないようにするためです。 となるとそのManager側がユーザーが使うメインAPIになると思うので、そっちと合わせて提案してみた感じです。
Manager側をわかりやすい名称にしたかったので、あたらめてVoiceSetも名前の候補になるかなと思ってVoiceSetという名称も候補に入れていました!
とりあえずModelやModelSet,VoiceSetでsynthesisができてしまうのは違和感があります。Voicevoxが良いかと思いましたがsynthesisすることを考えるとSynthesizerが良いかも core側でsynthesisを提供するということはengineでの処理を持ってくるということですね。こっちのほうが良いと思います。 loadが冗長になっているのを改善することを考えると以下のようにするとよいかと思います(prefix,あまり重要ではない機能やオプションなどは省略)
以前の議論ではmodelを意識させるかさせないかで別れていたかと思いますがやはりvoicevox coreと機械学習モデルはきっても切れない関係でありライブラリユーザーには意識させたほうが良いと思います
Synthesizer+Modelの構造、良いと思います!! 役割が分かれているのがわかりやすいなと思いました!
一応、Modelは機能を持っていてもまあ不自然じゃないと思います。 ここのモデルは機械学習モデルではなく音声合成モデルなので、音声合成機能を持ってもまあという感じです。
個人的にはSynthesizer+Modelの形にするのを、モデルファイルの単一ファイル化と一緒に進めるのが、二度手間にならなくて良さそうだなと思います!
時間がかかることになりそうですがそれも問題ないと思います。 なんにせよエンジン向けのAPIは同じ形で実装し続けるので、VOICEVOXのリリースタイミングに合わせる必要があまり無いので・・・!
@qryxip さんと @PickledChair さん、あとメンテナの @y-chan さんの意見もお伺いしたいです! (つまるところ、こちらの形の実装+エンジン向けのAPI提供し続けになるかなと)
一応、Modelは機能を持っていてもまあ不自然じゃないと思います。 ここのモデルは機械学習モデルではなく音声合成モデルなので、音声合成機能を持ってもまあという感じです。
一応ここがなぜ不自然に思ったかというとモデルが機械学習モデルか音声合成モデルどちらなのかはあまり重要ではなく、モデルはデータそのものを表す構造体であり責務的にデータに対する操作までが可能であり音声合成機能を提供するのは役割として違うかなと思ったからです。 仮にModelでsynthesisできるようにすると処理としてはModelがsynthesisするというふうに見えるのでおかしい。正しくはModelのデータを使用してsynthesisするのはず
discordより実は今まで引数で受け取っていたspeaker_idがspeaker_idではなくstyle_idであることが発覚しました 新しいAPIについては最低限引数名ぐらいは変えないといけないかと思いますがどういうふうに変えたほうが良いですかね
またstyle_idについてvoice_idにすれば良かったという話もありましたがこれの名前もどうしましょうか
1が良いかなと思いました! voice_idの検討もいったんなしで、style_idそのままが良いかなと思います。
理由はコアだけがこの形に変わっても、仕様違いが多くなってメンテナンスが大変になると感じるためです。 他の仕様と違う部分をあわせるのは嬉しいので、speaker_id→style_idはとても賛成です! ユーザーにとっても、style_idが一意なのになぜかspeaker_idを指定する必要があると面倒かなぁと・・・!
ではそれで
で詳細が更に議論されています。 現状こんな感じかなというのをまとめてみます。
モデルファイルのファイル構造についてはこちらで議論するのが良さそうでしょうか。 といってもおそらく2通りくらいかなとか考えてます。
個人的にはzipからバイナリを読めるようなライブラリでまあまあ良い感じのがあるなら、zip方式でいいかなと思ってます。 (エンジン側のVVPPファイルと同じ方式です)
まあzipでいいんじゃないですかね Rust製ダウンローダーでもzipは解凍してるのでそのへんは問題ないでしょう
賛成です! ファイル構造としてはこんな感じですかねぇ。
manifest.json 他のファイルのファイル名・バージョンなどが入ってる metas metas.jsonへのパス predict_duration モデルへのパス predict_intonation decode manifest_version 将来使うかも。最初はいらなそう metas.json 各モデル.onnx model/ モデルディレクトリ。あってもなくても良さそう
manifest.jsonとmetas.jsonって分ける必要ありますか? また各ファイルパスについてはバージョンが同じならファイル配置固定化できるなら不要かもです
作る側的には、意味の異なる情報は分けたほうが管理しやすいので嬉しいです。 manifest.jsonは共通で、metas.jsonだけリプレイスする運用とかができます。 まあでも、どっちでも良いなら分けたいかなくらいの気持ちです。
ファイルパスに関しては拡張子が違うことを考慮してます。 こっちはonnxから別の何かに移ることもあると思うので、冗長性をもたせときたいです。
manifest.jsonは共通で、metas.jsonだけリプレイスする運用とかができます。 まあでも、どっちでも良いなら分けたいかなくらいの気持ちです。
これはスピーカーを新しく追加するときとかですか?
ファイルパスに関しては拡張子が違うことを考慮してます。 こっちはonnxから別の何かに移ることもあると思うので、冗長性をもたせときたいです。
これはmanifestにファイルパスを持たせずにmanifest_versionをもとに読み込むファイルパスを変えるでも対応できそうですがどうしましょうか? manifest_versionは必須ではないとうことですがこれは同じvvmのスタイルが読み込まれているか判定するためのものではないということですかね
これはスピーカーを新しく追加するときとかですか?
新しくVVMを作る時とか、いっぱいあるVVMのマニフェストを刷新する時とか想像してました。 N回ファイル開いて修正して閉じてを繰り返すか、1回修正してN回コピーするか、みたいな。
これはmanifestにファイルパスを持たせずにmanifest_versionをもとに読み込むファイルパスを変えるでも対応できそうですがどうしましょうか?
確かにそうですが、ファイル名をコーディングするとテストやメンテが少し大変だったりしそうです。 あと製品版とOSS版でファイル拡張子が異なるので、2種類コードをメンテすることになって少し煩雑です。
manifest_versionは必須ではないとうことですがこれは同じvvmのスタイルが読み込まれているか判定するためのものではないということですかね
スタイルのバージョンはmetas.jsonにあるのでそっち使うことになると考えてます。 manifest_versionが必須でないのは、最初だからでした。(manifest_versionが無いというバージョンにできる) 互換性考えて、あったほうが良いと思います!
このあたりはどれもAPIには現れないことなので、そこまで議論するようなことではない気もしました…! あまり強い反対理由がなければサッと決めても良いかも?
運用のことを考えると分けたほうが良さそうですね styleごとにバージョンをもつのかなと思ってますが、これはVVMに更新が入るとmetas.json中のバージョンが全て更新されるということでしょうか?
ですです、基本的に同一VVM内のスタイルのバージョンが全部上がる感じです。 であればVVMのバージョンでも良い気もしますが、まあ過去との互換性のためスタイルごとにバージョン振る形でまあ良いかなぁ…。
追記: https://github.com/VOICEVOX/voicevox_core/pull/497に移動しました。
↑このタスクリストですが、#370 マージ後にすぐmain
← vvm-async-api
のdraft PRを作ってしまって、そこにぶら下げるのはどうでしょうか? (ここにあると埋もれて探すのが面倒になりそうに感じました)
なるほどです、良いと思います!! コンフリクトが解消し次第すぐマージしましょう!
@qryxip vvm-async-api
という名前だとブランチprotectにちょっと不便なので、project-vvm-async-apiというブランチ名に変更しました。
プロテクションもかけちゃおうと思います。
そういえばpredict_duration
/predict_intonation
/decode
ですが、ユーザーはあまり使わないと思うのでperform_predict_duration
みたいな名前にした上でドキュメントにはlow-level/internalだということを書いておくのはどうでしょうか?
あ、そういえばproject-vvm-async-apiだと3つとも既に消滅していますね。すみません忘れて下さい。
内容
https://github.com/VOICEVOX/voicevox_core/issues/276#issuecomment-1245472220 , https://github.com/VOICEVOX/voicevox_core/pull/274#issuecomment-1246896362 によりvoicevox_coreの C APIをオブジェクト指向に寄せたAPIにする必要が出てきて、そのための議論をしたいと考えています。 個人的には以下のようなクラスでC APIを考えてるのですがいかがでしょうか? またpython APIについてもこのissueで議論したクラス設計を元にAPI設計を作りたいと考えてます。 今考えてるものとしてはversion,metas,supported_devices情報の取得はVoicevoxCoreクラスのstaticメンバ関数として実装しようと考えています。
voicevox_core_newとvoicevox_core_initializeは一緒にするべきかもしれませんがresultcodeの関係上分けようかと思ってます。 また現在のvoicevox_coreの関数のprefixは
voicevox
ですが、これもきちんとオブジェクト指向的な名前にするとvoicevox_core
にprefixがなると思い、 prefix をvoicevox_core
にしようと考えています。その他
@sevenc-nanashi @shigobu お二人はvoicevox_coreのwrapperを作成されているように見受けられますのでぜひご意見をいただきたいです。