LoRAファインチューニングとは?決定版ガイド

Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
大規模言語モデル(LLM)の台頭は、AIの能力を大きく変革しました。しかし、これらの巨大なモデルをファインチューニングすることは、依然としてコストとリソースを大量に消費する課題です。ここで登場するのがLoRA(Low-Rank Adaptation)です。これは、学習可能なパラメータ数を劇的に削減することで、事前学習済みモデルの効率的なファインチューニングを可能にする画期的な技術です。モデル全体を更新する代わりに、LoRAは軽量で学習可能なモジュールを注入し、ファインチューニングをより速く、より安価に、より利用しやすくします。ドメイン固有のLLMを構築する場合でも、エッジデプロイメントを最適化する場合でも、LoRAは現代のMLワークフローにおいて頼りになる手法となっています。このガイドでは、LoRAとは何か、その仕組み、そしてなぜファインチューニングのあり方を変えているのかを詳しく解説します。
LoRAとは?
LoRAはLow-Rank Adaptationの略で、大規模な事前学習済みモデルを、その全重み行列を更新することなく適応させるために設計された、パラメータ効率の高いファインチューニング手法です。数十億にも及ぶ可能性のある元のモデルパラメータを変更する代わりに、LoRAは既存のレイヤーに小さな学習可能なランク分解行列を導入します。これらのモジュールがファインチューニングタスクを学習する間、ベースモデルは固定されたままです。
LoRAの核となるアイデアは線形代数に根ざしています。大きな重み更新行列ΔWを直接学習する代わりに、LoRAはそれを2つの小さな行列の積として近似します。
ΔW≈A⋅B
ここで、A∈Rd×rおよびB∈Rr×kであり、r≪min(d,k)です。この低ランク分解により、学習する必要のあるパラメータ数が劇的に削減され、多くの場合、数桁も少なくなります。
実際には、LoRAモジュールはトランスフォーマーモデルの特定のレイヤー(通常はアテンション層とフィードフォワード層)に挿入されます。学習中、LoRAパラメータのみが更新され、元のモデルの重みは固定されたままです。これにより、LoRAは計算とメモリ使用量の面で効率的であるだけでなく、モジュール性も備えています。つまり、異なるタスク用に異なるLoRAアダプターを学習させ、必要に応じてそれらを入れ替えることができます。
元々はNLPタスク向けに導入されましたが、LoRAはその後、画像モデル、音声認識、マルチモーダルアーキテクチャにも採用され、そのドメインを超えた汎用性を示しています。
LoRAファインチューニングとは?

LoRAファインチューニングは、BERT、GPT、LLaMAなどの大規模な事前学習済みモデルを、モデル全体を更新するのではなく、少数の追加パラメータのみを学習させることで適応させる手法です。これはLoRA(Low-Rank Adaptation)の核となる原理を活用し、特にモデル全体の再学習が非現実的な環境において、ファインチューニングを計算効率が高く、メモリに優しく、デプロイメントに適したものにします。現代の ファインチューニングツールの中でも、LoRAは、すべてのパラメータを更新することなく大規模モデルを効率的に適応させる能力で際立っています。
従来のファインチューニングでは、すべてのモデルの重みが更新されるため、かなりのGPUメモリ、計算時間、ストレージが必要となります。これは、数十億のパラメータを持つモデルを扱う場合に課題となります。LoRAは、事前学習済みモデルの重みを固定し、軽量な学習可能なアダプターを特定のレイヤー(通常、トランスフォーマーベースのアーキテクチャにおけるクエリおよびバリュー射影層)に挿入することで、この問題を解決します。
LoRAファインチューニング中:
- ベースモデルは変更されず、再利用可能です。
- 低ランクアダプターのパラメータ(通常は数百万個)のみが最適化されます。
- 変更されたレイヤーの出力は、固定された元の重みと学習されたLoRAパラメータの両方を組み合わせたものになります。
この構造のため、LoRAファインチューニングは特に以下のような場合に魅力的です。
- 特定の業界やタスクにおいてモデルが優れた性能を発揮する必要があるドメイン適応。
- 同じベースモデルを使用して、個別のタスク向けに異なるLoRAアダプターを学習させることができるマルチタスク学習。
- メモリと計算能力が制約される環境での、デバイス上またはエッジでのデプロイ。
一度学習させると、これらのLoRAアダプターは個別に保存し、推論のためにベースモデルに統合し直すことも、あるいはモジュールとして保持し、ユースケースに応じて動的に切り替えることも可能です。
LoRAによるファインチューニングは、パフォーマンスを損なうこともありません。多くのベンチマークにおいて、LoRAを使用してファインチューニングされたモデルは、フルファインチューニングと同等かそれ以上の結果を達成し、しかもはるかにリソース効率が高いのです。
LoRAファインチューニングは、最小限の計算量、最大限の柔軟性、そして精度を損なうことなく、大規模モデルをパーソナライズし適応させる能力を解き放ちます。
LoRAの技術的基盤
LoRA(Low-Rank Adaptation)の技術的な妙味は、モデルの能力や下流タスクの性能を犠牲にすることなく、ファインチューニング中に必要となる学習可能なパラメータの数を削減するために線形代数を用いる点にあります。その仕組みを理解するために、その根底にあるメカニズムを詳しく見ていきましょう。
フルランク更新における問題点
標準的なファインチューニングでは、事前学習済みモデルは重み行列WWWを調整することによって新しいタスクを学習します。これらの行列は、特に大規模なTransformerモデルにおいて、非常に巨大です(例:レイヤーあたり数億のパラメータ)。これらを直接更新すると、高いメモリ使用量、長い学習時間、そしてマルチタスク適応やデプロイにおける困難さにつながります。
LoRAの洞察:低ランク分解
LoRAは、モデルを新しいタスクに適応させるために必要な重みの変化は高次元である必要はないと提案します。その代わりに、これらの更新は低ランク行列を用いて近似できるとします。
完全な更新行列ΔWを学習する代わりに、LoRAは2つのより小さな行列を導入します。
ΔW=A⋅B
- A∈Rd×r
- B∈Rr×k
where, r≪min(d,k)
これらの行列は小さなランダム値で初期化され、学習中に更新される唯一のパラメータです。元の行列WWWは固定されたままです。
Transformerレイヤーへの統合
LoRAは通常、トランスフォーマーアーキテクチャのAttention層、特にクエリ(Q)およびバリュー(V)の射影行列に適用されます。ファインチューニング中、適応された出力は次のようになります。
W(x)+α⋅A⋅B(x)
ここでαはスケーリングファクター(多くの場合、経験的に設定されます)であり、A⋅B(x)は入力に適用される学習された低ランク適応を表します。
効率性と逆伝播
学習可能なのは低ランク行列のみであるため、学習可能なパラメータの数は桁違いに削減されます。これにより、以下が削減されます。
- GPUメモリ使用量
- 学習時間
- 過学習のリスク(パラメータが少ないため)
逆伝播はLoRAモジュールのみを介して行われるため、勾配は軽量に保たれ、更新は集中的に行われます。
モデルアーキテクチャに数学的原理を適用することで、LoRAは大規模モデルの適応に対し、非常に効率的でモジュール化された洗練されたソリューションを提供し、現代のLLMファインチューニングワークフローに最適です。
ファインチューニングにLoRAを使用する利点
LoRAは、パラメータ効率の良いファインチューニング(PEFT)分野で最も影響力のある技術の一つとして注目されています。その理由は、大規模言語モデル(LLM)、マルチタスク学習、エッジデプロイメントが関わるシナリオにおいて特に魅力的な、様々な実用的な利点を提供するからです。ファインチューニングにLoRAを使用する主な利点を見ていきましょう。
学習可能なパラメータの大幅な削減
LoRAの際立った利点の一つは、モデルサイズとランク設定に応じて、学習可能なパラメータ数を最大10,000分の1に削減できることです。少数のアダプターパラメータのみを学習することで、LoRAはメモリ消費量と計算オーバーヘッドを最小限に抑え、場合によってはコンシューマーグレードのGPUやCPUでのファインチューニングを可能にします。
事前学習済み知識の保持
LoRAはベースモデルを凍結するため、完全なファインチューニングで有用な汎用知識が上書きされてしまう「壊滅的忘却」を回避します。このため、LoRAは、大規模モデルをニッチなドメイン(例:法律、医療、金融)に適応させつつ、元の言語理解を保持する場合に特に有用です。
モジュール性と再利用性
LoRAを使用すると、異なるタスク用に異なるアダプターを学習させ、個別に保存できます。これにより、以下が可能になります。
- ベースモデルを再学習することなく、タスク固有の特化を実現
- 推論時のアダプターの容易な切り替え
- ファインチューニング済みモデルの軽量な保存と共有
このモジュール性は、マルチテナントプラットフォームや、コンテキストの切り替えが頻繁に発生するユースケースに最適です。
スケーラビリティとデプロイメントの向上
LoRAアダプターはサイズが小さく、ベースモデルのアーキテクチャ変更を必要としません。そのため、既存のモデルデプロイメントパイプラインに簡単に組み込むことができます。また、モデルサイズとメモリが制約されるエッジコンピューティング環境にも適しています。
優れた性能
その軽量性にもかかわらず、LoRAはダウンストリームタスクにおいて、フルファインチューニングの性能に匹敵するか、それを上回ることがよくあります。特に、最新のベースモデルと質の高いデータと組み合わせた場合に顕著です。
LoRAは、コストと複雑さを大幅に抑えながら、ほぼフルモデルの性能を実現するという魅力的なトレードオフを提供します。これによりファインチューニングが民主化され、より幅広いチームや開発者が高度なLLMカスタマイズを利用できるようになります。
LoRAの実践的な実装
このセクションでは、Hugging FaceのPEFTライブラリを使用してLoRAで大規模言語モデルをファインチューニングする方法を解説します。このアプローチにより、最小限のコード変更で学習可能なアダプターを事前学習済みモデルに注入できるため、LoRAはアクセスしやすく、かつ本番環境に対応可能になります。
1. 必要なライブラリをインストールする
モデルの読み込み、トークン化、トレーニング、LoRAの注入に必要なコアライブラリをインストールします。
pip install transformers peft accelerate datasets
2. ベースモデルとトークナイザーを読み込む
ここでは、Hugging FaceのTransformersライブラリを使用して、因果言語モデル(例:LLaMA 2)とそのトークナイザーを読み込みます。これがフリーズされたベースモデルとして機能します。
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
3. モデルにLoRAアダプターを組み込む
以下を指定してLoRA設定を定義します。
- r: 低ランク次元
- lora_alpha: スケーリング係数
- target_modules: LoRA適用対象モジュール(例:クエリおよびバリューの射影)
これはベースモデルをラップし、学習可能なLoRAレイヤーを追加します。
from peft import get_peft_model, LoraConfig, TaskType
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=8,
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "v_proj"]
)
model = get_peft_model(model, lora_config)
4. トレーニング用にデータセットをトークン化する
サンプルデータセット(例:Alpaca形式)を読み込み、指示と入力を結合してフラットなテキスト形式に前処理した後、パディングと切り捨てを行ってトークン化します。
from datasets import load_dataset
dataset = load_dataset("yashishdua/alpaca-cleaned")
def tokenize(example):
return tokenizer(example["instruction"] + example["input"], truncation=True, padding="max_length", max_length=512)
tokenized_dataset = dataset.map(tokenize)
5. Hugging FaceのTrainerでモデルをファインチューニングする
これはTrainerを使ってトレーニングループを設定し、バッチサイズ、エポック数、ロギング、保存戦略を指定します。
from transformers import Trainer, TrainingArguments
trainer = Trainer(
model=model,
args=TrainingArguments(
output_dir="./lora-peft-checkpoint",
per_device_train_batch_size=2,
num_train_epochs=3,
logging_steps=10,
save_strategy="epoch"
),
train_dataset=tokenized_dataset["train"],
tokenizer=tokenizer
)
trainer.train()
6. LoRAアダプターの重みを保存する
トレーニング後、軽量でモジュール性を保つため、LoRAアダプター層のみを保存します(完全なベースモデルは保存しません)。
model.save_pretrained("./lora-peft-checkpoint")
7. 推論用アダプター重みのロード
推論を実行するには、ベースモデルを再ロードし、PeftModelを使用して保存されたLoRAアダプターをアタッチします。これにより、ファインチューニングされたバージョンが効率的に再構築されます。
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
model = PeftModel.from_pretrained(base_model, "./lora-peft-checkpoint")
model.eval()
このコードは、LoRAを使用してサポートされている任意のTransformerモデルをファインチューニングするための出発点として使用できます。お好みのデータセットを組み込み、LoRAの設定やトレーニングのハイパーパラメータを調整し、スクリプトをそのまま実行するだけです。モジュール式に設計されているため、必要に応じて評価、ロギング、デプロイメントのために拡張できます。迅速な実験や軽量な本番環境でのファインチューニングに最適です。
LoRAのケーススタディと応用事例
LoRAが広く普及するにつれて、その実世界での応用は、業界やユースケースを超えて急速に拡大しています。インフラコストの削減から、大規模なパーソナライゼーションの実現まで、LoRAは研究環境と本番環境の両方でその価値を証明してきました。以下に、LoRAが目覚ましい影響を与えた注目すべきシナリオをいくつか紹介します。
ヘルスケアおよび法務AIにおけるドメイン固有のファインチューニング
医療機関やリーガルテックのスタートアップなど、機密性の高いデータや専門的なデータを扱う組織は、大規模言語モデルを自社のドメインに適応させる必要があることがよくあります。完全なファインチューニングを使用すると、膨大な計算が必要となり、プライバシーに関する懸念が生じます。LoRAを使用すると、チームはベースの重みを固定したまま、ドメイン固有のコーパス(例:医療用語や法律契約)で事前学習済みモデルをファインチューニングできます。これにより、軽量でタスクに最適化されたモデルが実現し、セキュリティを維持しつつ、内部でのデプロイも容易になります。
大規模マルチタスク・ファインチューニング
大規模なAIプラットフォームは、要約、分類、対話生成といった複数の下流タスクをサポートする必要があることがよくあります。各タスクのためにモデル全体のコピーを個別に維持する代わりに、LoRAはそれぞれのユースケースに合わせて軽量なアダプターを学習・保存することを可能にします。これらのアダプターは、ユーザーのニーズに基づいて動的にロードできるため、単一の共有基盤からパーソナライズされたモデルや多機能モデルを簡単に提供できます。
オンデバイス&エッジAI
モバイルデバイス、IoTゲートウェイ、エッジ推論プラットフォームのようなリソースが限られた環境は、LoRAから大きな恩恵を受けます。数十億のパラメータではなく、数百万のパラメータのみを学習することで、LoRAはメモリや計算予算を使い果たすことなく、迅速な適応を可能にします。一部のチームは、LoRAを使用してWhisperやDistilBERTのようなモデルを、完全にオンデバイスで動作する音声アシスタントやドキュメントスキャナー向けにファインチューニングしています。
コミュニティとオープンソースエコシステム
Alpaca、Dolly、Vicunaのようなオープンソースプロジェクトは、いずれもLoRAを利用して、命令追従や対話タスクのためにオープンなベースモデル(例:LLaMA)をファインチューニングしてきました。これは、個人の開発者や小規模なチームでも、高価なハードウェアにアクセスすることなく強力なモデルを作成できることを示しています。
これらのユースケース全体において、LoRAはその約束を一貫して果たしています。パフォーマンスを犠牲にすることなく費用対効果の高いファインチューニングを実現し、ドメイン、タスク、環境を横断して柔軟にスケールできます。
LoRAにおける高度なトピック

LoRAの真の力は、軽量なファインチューニングをはるかに超えています。適切にスケールされた場合、本番環境へのデプロイ、マルチドメインシステム、研究ワークフローに最適な、さまざまな高度な構成を可能にします。以下に、実世界のシステムでLoRAを拡張するための最も影響力があり、技術的に重要な方法をいくつか紹介します。
LoRAアダプターのベースモデルへのマージ
デフォルトでは、LoRAアダプターはベースモデルとは分離されており、推論時に適用される残差層として機能します。しかし、レイテンシに敏感な環境や、推論に最適化されたランタイム(例:vLLM、ONNX、TensorRT)でのデプロイの場合、学習後に低ランクのLoRA重みを元のモデル重みにマージすることが有利です。これにより、アダプターロジックの必要がなくなり、推論の複雑さが軽減され、以下のことが可能になります。
- 応答時間の短縮
- サービングインフラストラクチャの簡素化
- 低レベル推論エンジンとの互換性の向上
マージプロセスは通常、線形演算によって行われます。
Wmerged=W+α⋅A⋅B
選択的なモジュール適用
LoRAは、すべてのトランスフォーマー層に適用する必要はありません。多くの場合、アテンション層におけるクエリ(Q)およびバリュー(V)の射影行列など、アーキテクチャの特定の箇所のみをファインチューニングするだけで、より少ないパラメータで同等のパフォーマンスを達成できます。
上級ユーザーは以下をターゲットにすることができます。
- 推論負荷の高いタスク向けのアテンション層
- 分類や要約のためのMLP(フィードフォワード)層
- タスクの感度に応じた深層層と浅層層
このアプローチにより、モデルの動作をより細かく制御でき、パラメータの予算化が可能になり、層レベルでの解釈可能性が向上します。
量子化を伴うLoRA:QLoRA
QLoRAは、LoRAと4ビットまたは8ビット量子化を組み合わせた強力な拡張機能であり、数十億のパラメータを持つモデルを単一のGPUでファインチューニングすることを可能にします。その仕組みは以下の通りです。
- bitsandbytesを使用してベースモデルを4ビット精度でロードする
- 再量子化の必要なく、その上にLoRAアダプターを適用する
- paged AdamWのようなメモリ効率の良いオプティマイザを使用する
QLoRAは、精度を犠牲にすることなく、LLaMA-65Bのようなモデルを消費者向けハードウェアでファインチューニングすることを可能にします。
マルチアダプター推論とルーティング
マルチタスクまたはマルチテナントの要件がある本番環境のシナリオでは、LoRAは複数のアダプターの作成を可能にし、それぞれが異なるユースケースや顧客向けに調整されます。これらは次のことが可能です。
- 実行時に動的にロードされる
- メタデータ(例:タスクID、ユーザータイプ、プロンプト構造)に基づいてルーティングされる
これにより、単一のベースモデルがメモリ使用量を低く抑え、レイテンシを管理可能なレベルに保ちながら、多くのドメインに対応できます。アダプター選択ロジックは、外部のオーケストレーション層やプロンプトパーサーと統合可能です。
モジュラーエージェントとRAGコンポーネント
Retrieval-Augmented Generation (RAG) やマルチエージェントアーキテクチャのような、より複雑なシステムでは、異なるサブモジュールが文書検索、ツール選択、要約、または対話を実行する場合があります。LoRAはコンポーネントレベルのファインチューニングを可能にし、各サブモデルがそれぞれのアダプターで独立してトレーニングできます。
これは次のようなシナリオで特に強力です。
- タスクが明確に分離されている場合(例:検索と生成)
- 異なるチームが異なるパイプラインコンポーネントを所有している場合
- サブモジュールが異なるペースで進化する必要がある場合
LoRAは、このようなモジュール型システムにおいて、分離性、保守性、適応性を確保します。
LoRAファインチューニングにおける課題
LoRAは効率性とモジュール性において大きな利点をもたらしますが、課題がないわけではありません。堅牢なファインチューニングワークフローを設計したり、複数のユースケースでLoRAをスケールさせたりする際には、これらの限界を理解することが不可欠です。
極端な適応に対する能力の限界
LoRAはパラメータのごく一部(低ランク行列を介して)しか更新しないため、タスクがモデルの挙動に大幅な変更を必要とする場合、苦戦する可能性があります。事前学習済み分布とは大きく異なるドメインでの推論を伴うタスクでは、完全なファインチューニングや追加のレイヤーが依然として必要になるかもしれません。
アダプター設定のトレードオフ
ランク (r)、アルファスケーリングファクター、ターゲットモジュールなど、適切なLoRA設定を選択するには実験が必要です。ランクが低すぎるとアンダーフィットする可能性があり、高すぎるとオーバーフィットにつながったり、パラメータ削減効果が薄れたりする可能性があります。さらに、誤ったモジュールをターゲットにすること(例:すべてのレイヤーに無差別にLoRAを使用すること)は、パフォーマンスの向上なしに不必要な複雑さとコストを招く可能性があります。
量子化とサービングとの互換性
QLoRAのようなツールは量子化されたファインチューニングをサポートしていますが、すべての推論プラットフォームがLoRAアダプターやマージされた重みを適切に処理できるわけではありません。一部のサービングフレームワーク(特にエッジや低レベルのC++ランタイム)では、アダプターのマージや互換性のある形式への再エクスポートが必要になる場合があり、デプロイメントパイプラインに手順が追加されます。
デバッグと評価
LoRAでファインチューニングされたモデルのデバッグは、予想以上に複雑になることがあります。ベースモデルが凍結されているため、失敗がLoRAモジュールの学習不足によるものなのか、凍結されたバックボーンの固有の限界によるものなのかを解釈するのが難しい場合があります。LoRAが適切なツールである時期を理解するためには、複数のタスクとデータセットにわたる適切な評価が重要です。
これらの課題にもかかわらず、LoRAは、特に効率性、規模、モジュール性が最優先される環境において、慎重に使用すれば非常に効果的で柔軟なアプローチであり続けます。
まとめ
LoRAは、大規模言語モデルのファインチューニング方法を再定義しました。これにより、膨大な計算資源や完全な再学習を必要とせずに、強力なモデルを効率的に適応させることが可能になりました。その低ランクアプローチは、現代のMLワークフローにモジュール性、スケーラビリティ、費用対効果をもたらします。このガイドでは、LoRAの基礎、実際のユースケース、高度なテクニック、そしてHugging FaceのPEFTを使用した実践的な実装について探求しました。LLMが規模と採用を拡大し続ける中、LoRAはパーソナライゼーションとパフォーマンスへの実用的な道筋を提供します。インテリジェントなスケーリングを目指すチームにとって、LoRAは単に効率的であるだけでなく、適応性の高いAIシステムを構築するための戦略的優位性をもたらします。
よくある質問
LoRAファインチューニングとは具体的に何ですか?
LoRAファインチューニングは、すべてのパラメータを更新することなく、大規模な事前学習済みモデルを適応させる効率的な手法です。ベースモデルの重みを凍結し、小型で軽量なアダプターモジュールのみを学習させます。この技術により、計算リソースとメモリが大幅に削減され、特定のタスクやデプロイメントにおいて、モデルの適応がより速く、安価に、そしてアクセスしやすくなります。
LoRAファインチューニングにはどのくらいのデータが必要ですか?
LoRAファインチューニングは、モデル全体のファインチューニングと比較して、必要なデータ量を大幅に削減します。決まった量はありませんが、LoRAは事前学習済みのベースモデルを活用するため、より小規模なタスク固有のデータセットでも優れた結果を達成できます。これにより、大規模モデルの適応が特殊なユースケースにおいてより効率的かつアクセスしやすくなり、リソースの使用が最適化されます。
LoRAベースのファインチューニングの主な利点は何ですか?
LoRAファインチューニングの最大の利点は、その驚くべき効率性にあります。訓練可能なパラメータを大幅に削減することで、プロセスを高速化し、コスト効率を高め、メモリ使用量を抑えることができます。これにより、最小限の計算リソースで大規模言語モデルを様々なタスクに適応させることが可能になり、米国企業にとってアクセスしやすく高性能なAIソリューションを提供します。
LoRAファインチューニングの仕組みは?
LoRAファインチューニングでは、元のモデルの大きな重みを固定し、特定の層に小さく訓練可能なアダプター行列を挿入します。訓練中に更新されるのは、モデル全体ではなく、これらの軽量なアダプターパラメータのみです。このプロセスにより、LoRAファインチューニングは大幅に効率的になり、計算リソースを削減し、米国チームのモデル適応を加速させます。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.


















.webp)
.webp)





.png)

.png)














