diff --git a/Readme.md b/Readme.md index 160fc55..ea228ed 100644 --- a/Readme.md +++ b/Readme.md @@ -3,14 +3,16 @@ 💠 **aivmlib**: **Ai**vis **V**oice **M**odel File (.aivm/.aivmx) Utility **Lib**rary -**AIVM** (**Ai**vis **V**oice **M**odel) / **AIVMX** (**Ai**vis **V**oice **M**odel for ONN**X**) は、学習済みモデル・ハイパーパラメータ・スタイルベクトル・話者メタデータ(名前 / 概要 / アイコン / ボイスサンプル など)を 1 つのファイルにギュッとまとめた、AI 音声合成モデル用オープンファイルフォーマットです。 +**AIVM** (**Ai**vis **V**oice **M**odel) / **AIVMX** (**Ai**vis **V**oice **M**odel for ONN**X**) は、学習済みモデル・ハイパーパラメータ・スタイルベクトル・話者メタデータ(名前・概要・ライセンス・アイコン・ボイスサンプル など)を 1 つのファイルにギュッとまとめた、AI 音声合成モデル用オープンファイルフォーマットです。 > [!NOTE] -> 「AIVM」は、AIVM と AIVMX 両方のフォーマットを包含する仕様の総称でもあります。 +> **「AIVM」は、AIVM / AIVMX 両方のフォーマット仕様・メタデータ仕様の総称でもあります。** +> 具体的には、AIVM ファイルは「AIVM メタデータを追加した Safetensors 形式」、AIVMX ファイルは「AIVM メタデータを追加した ONNX 形式」のモデルファイルです。 +> 「AIVM メタデータ」とは、AIVM 仕様に定義されている、学習済みモデルに紐づく各種メタデータのことをいいます。 [AivisSpeech](https://github.com/Aivis-Project/AivisSpeech) / [AivisSpeech-Engine](https://github.com/Aivis-Project/AivisSpeech-Engine) をはじめとした AIVM 仕様に対応したソフトウェアに AIVM / AIVMX ファイルを追加することで、AI 音声合成モデルを簡単に利用できます。 -このライブラリでは、AIVM / AIVMX ファイルのメタデータを読み書きするためのユーティリティを提供します。 +**この aivmlib ライブラリでは、AIVM / AIVMX ファイル内のメタデータを読み書きするためのユーティリティを提供します。** この Readme の後半では、aivmlib で対応している各 AIVM 仕様についても説明しています。 > [!TIP] @@ -22,13 +24,13 @@ - [Usage](#usage) - [License](#license) - [AIVM Specifications](#aivm-specifications) + - [Overview](#overview) - [AIVM File Format Specification](#aivm-file-format-specification) - - [概要](#概要) - [Safetensors 形式との互換性](#safetensors-形式との互換性) - [参考資料](#参考資料) - [AIVMX File Format Specification](#aivmx-file-format-specification) - - [概要](#概要-1) - [ONNX 形式との互換性](#onnx-形式との互換性) + - [参考資料](#参考資料-1) - [AIVM Manifest Specification (Version 1.0)](#aivm-manifest-specification-version-10) - [サポートされるモデルアーキテクチャ](#サポートされるモデルアーキテクチャ) - [AIVM マニフェストのフィールド定義](#aivm-マニフェストのフィールド定義) @@ -59,11 +61,28 @@ $ aivmlib --help │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ────────────────────────────────────────────────────────────────────────╮ -│ create-aivm 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, │ -│ スタイルベクトルから AIVM メタデータを生成した上で、 │ -│ それを書き込んだ仮の AIVM ファイルを生成する │ -│ show-metadata 指定されたパスの AIVM ファイル内に記録されている AIVM │ -│ メタデータを見やすく出力する │ +│ create-aivm 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, │ +│ スタイルベクトルから AIVM メタデータを生成した上で、 │ +│ それを書き込んだ仮の AIVM ファイルを生成する │ +│ create-aivmx 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, │ +│ スタイルベクトルから AIVM メタデータを生成した上で、 │ +│ それを書き込んだ仮の AIVMX ファイルを生成する │ +│ show-metadata 指定されたパスの AIVM / AIVMX ファイル内に記録されている AIVM │ +│ メタデータを見やすく出力する │ +╰───────────────────────────────────────────────────────────────────────────────────╯ + +$ aivmlib show-metadata --help + + Usage: aivmlib show-metadata [OPTIONS] FILE_PATH + + 指定されたパスの AIVM / AIVMX ファイル内に記録されている AIVM メタデータを見やすく出力する + +╭─ Arguments ───────────────────────────────────────────────────────────────────────╮ +│ * file_path PATH Path to the AIVM / AIVMX file [default: None] │ +│ [required] │ +╰───────────────────────────────────────────────────────────────────────────────────╯ +╭─ Options ─────────────────────────────────────────────────────────────────────────╮ +│ --help Show this message and exit. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ $ aivmlib create-aivm --help @@ -71,7 +90,7 @@ $ aivmlib create-aivm --help Usage: aivmlib create-aivm [OPTIONS] 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, スタイルベクトルから - AIVM メタデータを生成した上で、 それを書き込んだ仮の AIVM ファイルを生成する + AIVM メタデータを生成した上で、それを書き込んだ仮の AIVM ファイルを生成する ╭─ Options ─────────────────────────────────────────────────────────────────────────╮ │ * --output -o PATH Path to the output AIVM │ @@ -97,17 +116,35 @@ $ aivmlib create-aivm --help │ exit. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ -$ aivmlib show-metadata --help +$ aivmlib create-aivmx --help - Usage: aivmlib show-metadata [OPTIONS] AIVM_FILE_PATH + Usage: aivmlib create-aivmx [OPTIONS] - 指定されたパスの AIVM ファイル内に記録されている AIVM メタデータを見やすく出力する + 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, スタイルベクトルから + AIVM メタデータを生成した上で、それを書き込んだ仮の AIVMX ファイルを生成する -╭─ Arguments ───────────────────────────────────────────────────────────────────────╮ -│ * aivm_file_path PATH Path to the AIVM file [default: None] [required] │ -╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────────────────────╮ -│ --help Show this message and exit. │ +│ * --output -o PATH Path to the output AIVMX │ +│ file │ +│ [default: None] │ +│ [required] │ +│ * --model -m PATH Path to the ONNX model │ +│ file │ +│ [default: None] │ +│ [required] │ +│ * --hyper-parameters -h PATH Path to the hyper │ +│ parameters file │ +│ [default: None] │ +│ [required] │ +│ --style-vectors -s PATH Path to the style │ +│ vectors file (optional) │ +│ [default: None] │ +│ --model-architecture -a [Style-Bert-VITS2|Styl Model architecture │ +│ e-Bert-VITS2 [default: │ +│ (JP-Extra)] Style-Bert-VITS2 │ +│ (JP-Extra)] │ +│ --help Show this message and │ +│ exit. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ``` @@ -133,27 +170,28 @@ $ aivmlib show-metadata --help - [AIVMX File Format Specification](#aivmx-file-format-specification) - [AIVM Manifest Specification (Version 1.0)](#aivm-manifest-specification-version-10) -## AIVM File Format Specification - -以下に、AIVM ファイルフォーマットの仕様を示す。 - -**AIVM** (**Ai**vis **V**oice **M**odel) は、[Safetensors](https://github.com/huggingface/safetensors) (.safetensors) 形式で保存された学習済み AI 音声合成モデルのヘッダー領域の中に、カスタムメタデータとして話者メタデータ ([AIVM マニフェスト](#aivm-manifest-specification-version-10)) ・ハイパーパラメータ・スタイルベクトルといった各種情報を格納した、Safetensors 形式の拡張仕様である。 -「AI 音声合成モデル向けの、Safetensors 形式の共通メタデータ記述仕様」とも言える。 - -### 概要 +## Overview 学習済み AI 音声合成モデルと、その利用に必要な各種メタデータを単一ファイルにまとめることで、**ファイルの散逸や混乱を防ぎ、モデルの利用や共有を容易にすることを目的としている。** **AIVM 仕様は、音声合成モデルのモデルアーキテクチャに依存しない。** 異なるモデルアーキテクチャの音声合成モデルを共通のファイルフォーマットで扱えるよう、拡張性や汎用性を考慮して設計されている。 -大元の学習済み AI 音声合成モデルが Safetensors 形式で保存されているならば、原則どのようなモデルアーキテクチャであっても、メタデータを追加して AIVM ファイルを生成できる。 +大元の学習済みモデルが Safetensors または ONNX 形式で保存されているならば、原則どのようなモデルアーキテクチャであっても、メタデータを追加して AIVM / AIVMX ファイルを生成できる。 > [!IMPORTANT] > **AIVM 仕様は、各モデルアーキテクチャごとの推論方法を定義しない。あくまでも「AI 音声合成モデルのメタデータをまとめたファイル」としての仕様のみを定義する。** -> たとえば格納されている AI 音声合成モデルは PyTorch 用かもしれないし、TensorFlow 用かもしれない。 +> たとえば AIVM ファイルの場合、格納されている AI 音声合成モデルは PyTorch 用かもしれないし、TensorFlow 用かもしれない。 > どのように AI 音声合成モデルの推論を行うかは、AIVM ファイルをサポートするソフトウェアの実装に委ねられている。 +## AIVM File Format Specification + +以下に、AIVM ファイルフォーマットの仕様を示す。 + +**AIVM** (**Ai**vis **V**oice **M**odel) は、[Safetensors](https://github.com/huggingface/safetensors) (.safetensors) 形式で保存された学習済みモデルのヘッダー領域の中に、カスタムメタデータとして話者メタデータ ([AIVM マニフェスト](#aivm-manifest-specification-version-10)) ・ハイパーパラメータ・スタイルベクトルといった各種情報を格納した、Safetensors 形式の拡張仕様である。 + +**「Safetensors 形式で保存された AI 音声合成モデル向けの、共通メタデータ記述仕様」** とも言える。 + ### Safetensors 形式との互換性 Safetensors 形式の拡張仕様のため、そのまま通常の Safetensors ファイルとしてロードできる。 @@ -183,17 +221,20 @@ Safetensors のヘッダー JSON にはテンソルのオフセット等が格 以下に、AIVMX ファイルフォーマットの仕様を示す。 -**AIVMX** (**Ai**vis **V**oice **M**odel for ONN**X**) は、[ONNX](https://onnx.ai/) 形式で保存された学習済み AI 音声合成モデルのヘッダー領域の中に、カスタムメタデータとして話者メタデータ ([AIVM マニフェスト](#aivm-manifest-specification-version-10)) ・ハイパーパラメータ・スタイルベクトルといった各種情報を格納した、ONNX 形式の拡張仕様である。 -「AI 音声合成モデル向けの、ONNX 形式の共通メタデータ記述仕様」とも言える。 - -### 概要 +**AIVMX** (**Ai**vis **V**oice **M**odel for ONN**X**) は、[ONNX](https://onnx.ai/) 形式で保存された学習済みモデルのメタデータ領域の中に、カスタムメタデータとして話者メタデータ ([AIVM マニフェスト](#aivm-manifest-specification-version-10)) ・ハイパーパラメータ・スタイルベクトルといった各種情報を格納した、ONNX 形式の拡張仕様である。 -執筆中... +**「ONNX 形式で保存された AI 音声合成モデル向けの、共通メタデータ記述仕様」** とも言える。 ### ONNX 形式との互換性 執筆中... +### 参考資料 + +- [ONNX](https://onnx.ai/) +- [ONNX Metadata](https://onnx.ai/onnx/repo-docs/MetadataProps.html) +- [How to populate onnx model with custom meta data map ?](https://github.com/onnx/sklearn-onnx/issues/214) + ## AIVM Manifest Specification (Version 1.0) 以下に、AIVM ファイルフォーマットに含まれる、AIVM マニフェスト (Version 1.0) の仕様を示す。 diff --git a/aivmlib/__init__.py b/aivmlib/__init__.py index 689db75..77f5a43 100755 --- a/aivmlib/__init__.py +++ b/aivmlib/__init__.py @@ -1,7 +1,10 @@ import base64 import json +import onnx +import onnx.onnx_pb import traceback import uuid +from google.protobuf.message import DecodeError from pydantic import ValidationError from typing import BinaryIO @@ -12,6 +15,7 @@ AivmManifestSpeakerStyle, DEFAULT_AIVM_MANIFEST, ModelArchitecture, + ModelFormat, ) from aivmlib.schemas.aivm_manifest_constants import DEFAULT_ICON_DATA_URL from aivmlib.schemas.style_bert_vits2 import StyleBertVITS2HyperParameters @@ -36,6 +40,9 @@ def generate_aivm_metadata( Returns: AivmMetadata: AIVM メタデータ + + Raises: + AivmValidationError: ハイパーパラメータのフォーマットが不正・スタイルベクトルが未指定・サポートされていないモデルアーキテクチャの場合 """ # 引数として受け取った BinaryIO のカーソルを先頭にシーク @@ -68,7 +75,10 @@ def generate_aivm_metadata( manifest = DEFAULT_AIVM_MANIFEST.model_copy() manifest.name = hyper_parameters.model_name # モデルアーキテクチャは Style-Bert-VITS2 系であれば異なる値が指定されても動作するよう、ハイパーパラメータの値を元に設定する - manifest.model_architecture = ModelArchitecture.StyleBertVITS2JPExtra if hyper_parameters.data.use_jp_extra else ModelArchitecture.StyleBertVITS2 + if hyper_parameters.data.use_jp_extra: + manifest.model_architecture = ModelArchitecture.StyleBertVITS2JPExtra + else: + manifest.model_architecture = ModelArchitecture.StyleBertVITS2 # モデル UUID はランダムに生成 manifest.uuid = uuid.uuid4() @@ -101,60 +111,44 @@ def generate_aivm_metadata( ] return AivmMetadata( - manifest=manifest, - hyper_parameters=hyper_parameters, - style_vectors=style_vectors, + manifest = manifest, + hyper_parameters = hyper_parameters, + style_vectors = style_vectors, ) raise AivmValidationError(f"Unsupported model architecture: {model_architecture}.") -def read_aivm_metadata(aivm_file: BinaryIO) -> AivmMetadata: +def validate_aivm_metadata(raw_metadata: dict[str, str]) -> AivmMetadata: """ - AIVM ファイルから AIVM メタデータを読み込む + AIVM メタデータをバリデーションする Args: - aivm_file (BinaryIO): AIVM ファイル + raw_metadata (dict[str, str]): 辞書形式の生のメタデータ Returns: - AivmMetadata: AIVM メタデータ - """ - - # 引数として受け取った BinaryIO のカーソルを先頭にシーク - aivm_file.seek(0) - - # ファイルの内容を読み込む - array_buffer = aivm_file.read() - header_size = int.from_bytes(array_buffer[:8], 'little') - - # 引数として受け取った BinaryIO のカーソルを再度先頭に戻す - aivm_file.seek(0) + AivmMetadata: バリデーションが完了した AIVM メタデータ - # ヘッダー部分を抽出 - header_bytes = array_buffer[8:8 + header_size] - header_text = header_bytes.decode('utf-8') - try: - header_json = json.loads(header_text) - except json.JSONDecodeError: - raise AivmValidationError('File format is invalid. This file is not an AIVM (Safetensors) file.') + Raises: + AivmValidationError: AIVM メタデータのバリデーションに失敗した場合 + """ - # "__metadata__" キーから AIVM メタデータを取得 - metadata = header_json.get('__metadata__') - if not metadata or not metadata.get('aivm_manifest'): + # AIVM マニフェストが存在しない場合 + if not raw_metadata or not raw_metadata.get('aivm_manifest'): raise AivmValidationError('AIVM manifest not found.') - # AIVM マニフェストをパースしてバリデーション + # AIVM マニフェストのバリデーション try: - aivm_manifest = AivmManifest.model_validate_json(metadata['aivm_manifest']) + aivm_manifest = AivmManifest.model_validate_json(raw_metadata['aivm_manifest']) except ValidationError: traceback.print_exc() raise AivmValidationError('Invalid AIVM manifest format.') # ハイパーパラメータのバリデーション - if 'aivm_hyper_parameters' in metadata: + if 'aivm_hyper_parameters' in raw_metadata: try: if aivm_manifest.model_architecture.startswith('Style-Bert-VITS2'): - aivm_hyper_parameters = StyleBertVITS2HyperParameters.model_validate_json(metadata['aivm_hyper_parameters']) + aivm_hyper_parameters = StyleBertVITS2HyperParameters.model_validate_json(raw_metadata['aivm_hyper_parameters']) else: raise AivmValidationError(f"Unsupported hyper-parameters for model architecture: {aivm_manifest.model_architecture}.") except ValidationError: @@ -165,54 +159,117 @@ def read_aivm_metadata(aivm_file: BinaryIO) -> AivmMetadata: # スタイルベクトルのデコード aivm_style_vectors = None - if 'aivm_style_vectors' in metadata: + if 'aivm_style_vectors' in raw_metadata: try: - base64_string = metadata['aivm_style_vectors'] + base64_string = raw_metadata['aivm_style_vectors'] aivm_style_vectors = base64.b64decode(base64_string) except Exception: traceback.print_exc() raise AivmValidationError('Failed to decode style vectors.') + # AivmMetadata オブジェクトを構築して返す return AivmMetadata( - manifest=aivm_manifest, - hyper_parameters=aivm_hyper_parameters, - style_vectors=aivm_style_vectors, + manifest = aivm_manifest, + hyper_parameters = aivm_hyper_parameters, + style_vectors = aivm_style_vectors, ) -def write_aivm_metadata(aivm_file: BinaryIO, aivm_metadata: AivmMetadata) -> bytes: +def read_aivm_metadata(aivm_file: BinaryIO) -> AivmMetadata: """ - AIVM メタデータを AIVM ファイルに書き込む + AIVM ファイルから AIVM メタデータを読み込む Args: aivm_file (BinaryIO): AIVM ファイル - aivm_metadata (AivmMetadata): AIVM メタデータ Returns: - bytes: 書き込みが完了した AIVM or (メタデータが書き込まれていない素の Safetensors) ファイルのバイト列 + AivmMetadata: AIVM メタデータ + + Raises: + AivmValidationError: AIVM ファイルのフォーマットが不正・AIVM メタデータのバリデーションに失敗した場合 """ - # Style-Bert-VITS2 系の音声合成モデルでは、AIVM マニフェストの内容をハイパーパラメータにも反映する - if aivm_metadata.manifest.model_architecture.startswith('Style-Bert-VITS2'): + # 引数として受け取った BinaryIO のカーソルを先頭にシーク + aivm_file.seek(0) - # スタイルベクトルが設定されていなければエラー - if aivm_metadata.style_vectors is None: - raise AivmValidationError('Style vectors are not set.') + # ファイルの内容を読み込む + array_buffer = aivm_file.read() + header_size = int.from_bytes(array_buffer[:8], 'little') - # モデル名を反映 - aivm_metadata.hyper_parameters.model_name = aivm_metadata.manifest.name + # 引数として受け取った BinaryIO のカーソルを再度先頭に戻す + aivm_file.seek(0) - # 環境依存のパスが含まれるため、training_files と validation_files は固定値に変更 - aivm_metadata.hyper_parameters.data.training_files = 'train.list' - aivm_metadata.hyper_parameters.data.validation_files = 'val.list' + # ヘッダー部分を抽出 + header_bytes = array_buffer[8:8 + header_size] + header_text = header_bytes.decode('utf-8') + try: + header_json = json.loads(header_text) + except json.JSONDecodeError: + raise AivmValidationError('Failed to decode AIVM metadata. This file is not an AIVM (Safetensors) file.') - # 話者名を反映 - new_spk2id = {speaker.name: speaker.local_id for speaker in aivm_metadata.manifest.speakers} - aivm_metadata.hyper_parameters.data.spk2id = new_spk2id + # "__metadata__" キーから AIVM メタデータを取得 + raw_metadata = header_json.get('__metadata__') - # スタイル名を反映 - new_style2id = {style.name: style.local_id for speaker in aivm_metadata.manifest.speakers for style in speaker.styles} - aivm_metadata.hyper_parameters.data.style2id = new_style2id + # バリデーションを行った上で、AivmMetadata オブジェクトを構築して返す + return validate_aivm_metadata(raw_metadata) + + +def read_aivmx_metadata(aivmx_file: BinaryIO) -> AivmMetadata: + """ + AIVMX ファイルから AIVM メタデータを読み込む + + Args: + aivmx_file (BinaryIO): AIVMX ファイル + + Returns: + AivmMetadata: AIVM メタデータ + + Raises: + AivmValidationError: AIVMX ファイルのフォーマットが不正・AIVM メタデータのバリデーションに失敗した場合 + """ + + # 引数として受け取った BinaryIO のカーソルを先頭にシーク + aivmx_file.seek(0) + + # ONNX モデル (Protobuf) をロード + try: + model = onnx.load_model(aivmx_file) + except DecodeError: + traceback.print_exc() + raise AivmValidationError('Failed to decode AIVM metadata. This file is not an AIVMX (ONNX) file.') + + # 引数として受け取った BinaryIO のカーソルを再度先頭に戻す + aivmx_file.seek(0) + + # AIVM メタデータを取得 + raw_metadata = {prop.key: prop.value for prop in model.metadata_props} + + # バリデーションを行った上で、AivmMetadata オブジェクトを構築して返す + return validate_aivm_metadata(raw_metadata) + + +def write_aivm_metadata(aivm_file: BinaryIO, aivm_metadata: AivmMetadata) -> bytes: + """ + AIVM メタデータを AIVM ファイルに書き込む + + Args: + aivm_file (BinaryIO): AIVM ファイル + aivm_metadata (AivmMetadata): AIVM メタデータ + + Returns: + bytes: 書き込みが完了した AIVM ファイルのバイト列 + + Raises: + AivmValidationError: AIVM ファイルのフォーマットが不正・スタイルベクトルが未指定の場合 + """ + + # モデル形式を Safetensors に設定 + # AIVM ファイルのモデル形式は Safetensors のため、AIVM マニフェストにも明示的に反映する + aivm_metadata.manifest.model_format = ModelFormat.Safetensors + + # AIVM マニフェストの内容をハイパーパラメータにも反映する + # 結果は AivmMetadata オブジェクトに直接 in-place で反映される + apply_aivm_manifest_to_hyper_parameters(aivm_metadata) # AIVM メタデータをシリアライズ # Safetensors のメタデータ領域はネストなしの string から string への map でなければならないため、 @@ -236,7 +293,7 @@ def write_aivm_metadata(aivm_file: BinaryIO, aivm_metadata: AivmMetadata) -> byt try: existing_header = json.loads(existing_header_text) except json.JSONDecodeError: - raise AivmValidationError('File format is invalid. This file is not an AIVM (Safetensors) file.') + raise AivmValidationError('Failed to decode AIVM metadata. This file is not an AIVM (Safetensors) file.') # 引数として受け取った BinaryIO のカーソルを再度先頭に戻す aivm_file.seek(0) @@ -262,8 +319,100 @@ def write_aivm_metadata(aivm_file: BinaryIO, aivm_metadata: AivmMetadata) -> byt return new_aivm_file_content +def write_aivmx_metadata(aivmx_file: BinaryIO, aivm_metadata: AivmMetadata) -> bytes: + """ + AIVM メタデータを AIVMX ファイルに書き込む + + Args: + aivmx_file (BinaryIO): AIVMX ファイル + aivm_metadata (AivmMetadata): AIVM メタデータ + + Returns: + bytes: 書き込みが完了した AIVMX ファイルのバイト列 + + Raises: + AivmValidationError: AIVMX ファイルのフォーマットが不正・スタイルベクトルが未指定の場合 + """ + + # モデル形式を ONNX に設定 + # AIVMX ファイルのモデル形式は ONNX のため、AIVM マニフェストにも明示的に反映する + aivm_metadata.manifest.model_format = ModelFormat.ONNX + + # AIVM マニフェストの内容をハイパーパラメータにも反映する + # 結果は AivmMetadata オブジェクトに直接 in-place で反映される + apply_aivm_manifest_to_hyper_parameters(aivm_metadata) + + # 引数として受け取った BinaryIO のカーソルを先頭にシーク + aivmx_file.seek(0) + + # ONNX モデル (Protobuf) をロード + try: + model = onnx.load_model(aivmx_file) + except DecodeError: + traceback.print_exc() + raise AivmValidationError('Failed to decode AIVM metadata. This file is not an AIVMX (ONNX) file.') + + # 引数として受け取った BinaryIO のカーソルを再度先頭に戻す + aivmx_file.seek(0) + + # AIVM メタデータをシリアライズ + # ONNX のメタデータ領域はネストなしの string から string への key-value でなければならないため、 + # すべてのメタデータを文字列にシリアライズして格納する + metadata = { + 'aivm_manifest': aivm_metadata.manifest.model_dump_json(), + 'aivm_hyper_parameters': aivm_metadata.hyper_parameters.model_dump_json(), + } + if aivm_metadata.style_vectors is not None: + # スタイルベクトルが存在する場合は Base64 エンコードして追加 + metadata['aivm_style_vectors'] = base64.b64encode(aivm_metadata.style_vectors).decode('utf-8') + + # メタデータを ONNX モデルに追加 + for key, value in metadata.items(): + model.metadata_props.append(onnx.StringStringEntryProto(key=key, value=value)) + + # 新しい AIVMX ファイルの内容をシリアライズ + new_aivmx_file_content = model.SerializeToString() + + return new_aivmx_file_content + + +def apply_aivm_manifest_to_hyper_parameters(aivm_metadata: AivmMetadata) -> None: + """ + AIVM マニフェストの内容をハイパーパラメータにも反映する + 結果は AivmMetadata オブジェクトに直接 in-place で反映される + + Args: + aivm_metadata (AivmMetadata): AIVM メタデータ + + Raises: + AivmValidationError: スタイルベクトルが未指定の場合 + """ + + # Style-Bert-VITS2 系の音声合成モデルの場合 + if aivm_metadata.manifest.model_architecture.startswith('Style-Bert-VITS2'): + + # スタイルベクトルが設定されていなければエラー + if aivm_metadata.style_vectors is None: + raise AivmValidationError('Style vectors are not set.') + + # モデル名を反映 + aivm_metadata.hyper_parameters.model_name = aivm_metadata.manifest.name + + # 環境依存のパスが含まれるため、training_files と validation_files は固定値に変更 + aivm_metadata.hyper_parameters.data.training_files = 'train.list' + aivm_metadata.hyper_parameters.data.validation_files = 'val.list' + + # 話者名を反映 + new_spk2id = {speaker.name: speaker.local_id for speaker in aivm_metadata.manifest.speakers} + aivm_metadata.hyper_parameters.data.spk2id = new_spk2id + + # スタイル名を反映 + new_style2id = {style.name: style.local_id for speaker in aivm_metadata.manifest.speakers for style in speaker.styles} + aivm_metadata.hyper_parameters.data.style2id = new_style2id + + class AivmValidationError(Exception): """ - AIVM ファイルの読み取り中にエラーが発生したときに発生する例外 + AIVM / AIVMX ファイルの読み取り中にエラーが発生したときに発生する例外 """ pass diff --git a/aivmlib/__main__.py b/aivmlib/__main__.py index d1aeb26..21f101a 100755 --- a/aivmlib/__main__.py +++ b/aivmlib/__main__.py @@ -6,7 +6,13 @@ from rich.style import Style from typing import Annotated, Union -from aivmlib import read_aivm_metadata, generate_aivm_metadata, write_aivm_metadata +from aivmlib import ( + generate_aivm_metadata, + read_aivm_metadata, + read_aivmx_metadata, + write_aivm_metadata, + write_aivmx_metadata, +) from aivmlib.schemas.aivm_manifest import ModelArchitecture @@ -15,14 +21,19 @@ @app.command() def show_metadata( - aivm_file_path: Annotated[Path, typer.Argument(help='Path to the AIVM file')] + file_path: Annotated[Path, typer.Argument(help='Path to the AIVM / AIVMX file')] ): """ - 指定されたパスの AIVM ファイル内に記録されている AIVM メタデータを見やすく出力する + 指定されたパスの AIVM / AIVMX ファイル内に記録されている AIVM メタデータを見やすく出力する """ + try: - with aivm_file_path.open('rb') as aivm_file: - metadata = read_aivm_metadata(aivm_file) + with file_path.open('rb') as file: + if file_path.suffix == '.aivmx': + metadata = read_aivmx_metadata(file) + else: + metadata = read_aivm_metadata(file) + for speaker in metadata.manifest.speakers: for style in speaker.styles: style.icon = '(Image Base64 DataURL)' @@ -35,7 +46,7 @@ def show_metadata( rich.print(Rule(characters='=', style=Style(color='#E33157'))) except Exception as e: rich.print(Rule(characters='=', style=Style(color='#E33157'))) - rich.print(f'[red]Error reading AIVM file: {e}[/red]') + rich.print(f'[red]Error reading AIVM or AIVMX file: {e}[/red]') rich.print(Rule(characters='=', style=Style(color='#E33157'))) @@ -51,14 +62,16 @@ def create_aivm( 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, スタイルベクトルから AIVM メタデータを生成した上で、 それを書き込んだ仮の AIVM ファイルを生成する """ + try: with hyper_parameters_path.open('rb') as hyper_parameters_file: style_vectors_file = style_vectors_path.open('rb') if style_vectors_path else None metadata = generate_aivm_metadata(model_architecture, hyper_parameters_file, style_vectors_file) + if style_vectors_file: + style_vectors_file.close() with safetensors_model_path.open('rb') as safetensors_file: new_aivm_file_content = write_aivm_metadata(safetensors_file, metadata) - with output_path.open('wb') as f: f.write(new_aivm_file_content) rich.print(Rule(characters='=', style=Style(color='#E33157'))) @@ -70,5 +83,38 @@ def create_aivm( rich.print(Rule(characters='=', style=Style(color='#E33157'))) +@app.command() +def create_aivmx( + output_path: Annotated[Path, typer.Option('-o', '--output', help='Path to the output AIVMX file')], + onnx_model_path: Annotated[Path, typer.Option('-m', '--model', help='Path to the ONNX model file')], + hyper_parameters_path: Annotated[Path, typer.Option('-h', '--hyper-parameters', help='Path to the hyper parameters file')], + style_vectors_path: Annotated[Union[Path, None], typer.Option('-s', '--style-vectors', help='Path to the style vectors file (optional)')] = None, + model_architecture: Annotated[ModelArchitecture, typer.Option('-a', '--model-architecture', help='Model architecture')] = ModelArchitecture.StyleBertVITS2JPExtra, +): + """ + 与えられたアーキテクチャ, 学習済みモデル, ハイパーパラメータ, スタイルベクトルから AIVM メタデータを生成した上で、 + それを書き込んだ仮の AIVMX ファイルを生成する + """ + + try: + with hyper_parameters_path.open('rb') as hyper_parameters_file: + style_vectors_file = style_vectors_path.open('rb') if style_vectors_path else None + metadata = generate_aivm_metadata(model_architecture, hyper_parameters_file, style_vectors_file) + if style_vectors_file: + style_vectors_file.close() + + with onnx_model_path.open('rb') as onnx_file: + new_aivmx_file_content = write_aivmx_metadata(onnx_file, metadata) + with output_path.open('wb') as f: + f.write(new_aivmx_file_content) + rich.print(Rule(characters='=', style=Style(color='#E33157'))) + rich.print(f'Generated AIVMX file: {output_path}') + rich.print(Rule(characters='=', style=Style(color='#E33157'))) + except Exception as e: + rich.print(Rule(characters='=', style=Style(color='#E33157'))) + rich.print(f'[red]Error creating AIVMX file: {e}[/red]') + rich.print(Rule(characters='=', style=Style(color='#E33157'))) + + if __name__ == '__main__': app() diff --git a/poetry.lock b/poetry.lock index ab86144..6e4e7f1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,6 +71,130 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "numpy" +version = "2.1.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.10" +files = [ + {file = "numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648"}, + {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d"}, + {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86"}, + {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7"}, + {file = "numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03"}, + {file = "numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466"}, + {file = "numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb"}, + {file = "numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f"}, + {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4"}, + {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a"}, + {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1"}, + {file = "numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2"}, + {file = "numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146"}, + {file = "numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c"}, + {file = "numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1"}, + {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426"}, + {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0"}, + {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df"}, + {file = "numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366"}, + {file = "numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142"}, + {file = "numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550"}, + {file = "numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e"}, + {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3"}, + {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8"}, + {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a"}, + {file = "numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98"}, + {file = "numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe"}, + {file = "numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a"}, + {file = "numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17"}, + {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6"}, + {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8"}, + {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35"}, + {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62"}, + {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7"}, + {file = "numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e"}, + {file = "numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c"}, +] + +[[package]] +name = "onnx" +version = "1.17.0" +description = "Open Neural Network Exchange" +optional = false +python-versions = ">=3.8" +files = [ + {file = "onnx-1.17.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:38b5df0eb22012198cdcee527cc5f917f09cce1f88a69248aaca22bd78a7f023"}, + {file = "onnx-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d545335cb49d4d8c47cc803d3a805deb7ad5d9094dc67657d66e568610a36d7d"}, + {file = "onnx-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3193a3672fc60f1a18c0f4c93ac81b761bc72fd8a6c2035fa79ff5969f07713e"}, + {file = "onnx-1.17.0-cp310-cp310-win32.whl", hash = "sha256:0141c2ce806c474b667b7e4499164227ef594584da432fd5613ec17c1855e311"}, + {file = "onnx-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:dfd777d95c158437fda6b34758f0877d15b89cbe9ff45affbedc519b35345cf9"}, + {file = "onnx-1.17.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:d6fc3a03fc0129b8b6ac03f03bc894431ffd77c7d79ec023d0afd667b4d35869"}, + {file = "onnx-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01a4b63d4e1d8ec3e2f069e7b798b2955810aa434f7361f01bc8ca08d69cce4"}, + {file = "onnx-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a183c6178be001bf398260e5ac2c927dc43e7746e8638d6c05c20e321f8c949"}, + {file = "onnx-1.17.0-cp311-cp311-win32.whl", hash = "sha256:081ec43a8b950171767d99075b6b92553901fa429d4bc5eb3ad66b36ef5dbe3a"}, + {file = "onnx-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:95c03e38671785036bb704c30cd2e150825f6ab4763df3a4f1d249da48525957"}, + {file = "onnx-1.17.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:0e906e6a83437de05f8139ea7eaf366bf287f44ae5cc44b2850a30e296421f2f"}, + {file = "onnx-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d955ba2939878a520a97614bcf2e79c1df71b29203e8ced478fa78c9a9c63c2"}, + {file = "onnx-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f3fb5cc4e2898ac5312a7dc03a65133dd2abf9a5e520e69afb880a7251ec97a"}, + {file = "onnx-1.17.0-cp312-cp312-win32.whl", hash = "sha256:317870fca3349d19325a4b7d1b5628f6de3811e9710b1e3665c68b073d0e68d7"}, + {file = "onnx-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:659b8232d627a5460d74fd3c96947ae83db6d03f035ac633e20cd69cfa029227"}, + {file = "onnx-1.17.0-cp38-cp38-macosx_12_0_universal2.whl", hash = "sha256:23b8d56a9df492cdba0eb07b60beea027d32ff5e4e5fe271804eda635bed384f"}, + {file = "onnx-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecf2b617fd9a39b831abea2df795e17bac705992a35a98e1f0363f005c4a5247"}, + {file = "onnx-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea5023a8dcdadbb23fd0ed0179ce64c1f6b05f5b5c34f2909b4e927589ebd0e4"}, + {file = "onnx-1.17.0-cp38-cp38-win32.whl", hash = "sha256:f0e437f8f2f0c36f629e9743d28cf266312baa90be6a899f405f78f2d4cb2e1d"}, + {file = "onnx-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:e4673276b558b5b572b960b7f9ef9214dce9305673683eb289bb97a7df379a4b"}, + {file = "onnx-1.17.0-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:67e1c59034d89fff43b5301b6178222e54156eadd6ab4cd78ddc34b2f6274a66"}, + {file = "onnx-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e19fd064b297f7773b4c1150f9ce6213e6d7d041d7a9201c0d348041009cdcd"}, + {file = "onnx-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8167295f576055158a966161f8ef327cb491c06ede96cc23392be6022071b6ed"}, + {file = "onnx-1.17.0-cp39-cp39-win32.whl", hash = "sha256:76884fe3e0258c911c749d7d09667fb173365fd27ee66fcedaf9fa039210fd13"}, + {file = "onnx-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:5ca7a0894a86d028d509cdcf99ed1864e19bfe5727b44322c11691d834a1c546"}, + {file = "onnx-1.17.0.tar.gz", hash = "sha256:48ca1a91ff73c1d5e3ea2eef20ae5d0e709bb8a2355ed798ffc2169753013fd3"}, +] + +[package.dependencies] +numpy = ">=1.20" +protobuf = ">=3.20.2" + +[package.extras] +reference = ["Pillow", "google-re2"] + +[[package]] +name = "protobuf" +version = "5.28.2" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-5.28.2-cp310-abi3-win32.whl", hash = "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d"}, + {file = "protobuf-5.28.2-cp310-abi3-win_amd64.whl", hash = "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132"}, + {file = "protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7"}, + {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f"}, + {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f"}, + {file = "protobuf-5.28.2-cp38-cp38-win32.whl", hash = "sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0"}, + {file = "protobuf-5.28.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3"}, + {file = "protobuf-5.28.2-cp39-cp39-win32.whl", hash = "sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36"}, + {file = "protobuf-5.28.2-cp39-cp39-win_amd64.whl", hash = "sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276"}, + {file = "protobuf-5.28.2-py3-none-any.whl", hash = "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece"}, + {file = "protobuf-5.28.2.tar.gz", hash = "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0"}, +] + [[package]] name = "pydantic" version = "2.9.2" @@ -276,4 +400,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.11" -content-hash = "7a4095ffc88d1e036398e27550cad210a2f81abd2ba4a0dd8d4a9cec168d27e6" +content-hash = "f9f4e2112f59cec1ff2033e5853c79eca4d3d3e9fdbc5f519c34d7eab98d843e" diff --git a/pyproject.toml b/pyproject.toml index f84a4b3..9979565 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ license = "MIT" readme = "Readme.md" [tool.poetry.dependencies] +onnx = "^1.17.0" python = ">=3.11" pydantic = "^2.4.0" typer = {extras = ["all"], version = "^0.9.0"}