Un port de flux MLX basé sur l'implémentation des diffuseurs HuggingFace.
Exécutez les modèles de flux puissants de Black Forest Labs localement sur votre Mac!
MFLUX est un port ligne par ligne de l'implémentation de flux dans la bibliothèque des diffuseurs HuggingFace à Apple MLX. MFLUX est délibérément maintenu minimal et explicite - les architectures de réseau sont codées en dur et aucun fichier de configuration n'est utilisé à l'exception des tokenzers. L'objectif est d'avoir une minuscule base de code dans le but d'exprimer ces modèles (évitant ainsi trop d'abstractions). Bien que les priorités MFLUX lisiblement sur la généralité et les performances, elles peuvent toujours être assez rapides et encore plus rapides.
Tous les modèles sont implémentés à partir de zéro dans MLX et seuls les tokenzers sont utilisés via la bibliothèque HuggingFace Transformers. En dehors de cela, il n'y a que des dépendances minimales comme Numpy et un oreiller pour le post-traitement d'image simple.
Pour les utilisateurs, le moyen le plus simple d'installer MFLUX est d'utiliser uv tool
: si vous avez installé uv
, simplement:
uv tool install --upgrade mflux
Pour obtenir les exécutables mflux-generate
et la ligne de commande associée. Vous pouvez passer aux guides d'utilisation ci-dessous.
L'encodeur T5 dépend de la phrase, qui n'a pas d'artefact de roue installable pour Python 3.13 à partir de novembre 2024. Jusqu'à ce que Google publie une roue 3.13, vous devez construire votre propre roue avec des instructions de construction officielles ou pour votre commodité utilisez un .whl
Pré-construit par le contributeur @anthonywu. Les étapes ci-dessous devraient fonctionner pour la plupart des développeurs, bien que votre système puisse varier.
uv venv --python 3.13
python -V # e.g. Python 3.13.0rc2
source .venv/bin/activate
# for your convenience, you can use the contributor wheel
uv pip install https://github.com/anthonywu/sentencepiece/releases/download/0.2.1-py13dev/sentencepiece-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
# enable the pytorch nightly
uv pip install --pre --extra-index-url https://download.pytorch.org/whl/nightly -e .
mkdir -p mflux && cd mflux && python3 -m venv .venv && source .venv/bin/activate
Cela crée et active un environnement virtuel dans le dossier mflux
. Après cela, installez MFLUX via PIP:
pip install -U mflux
git clone [email protected]:filipstrand/mflux.git
make install
make test
make lint
et make format
et utilise ruff
. Vous pouvez configurer automatiquement votre éditeur / IDE au flèche / format, ou utiliser nos aides fournies make
:make format
- formats votre codemake lint
- montre vos erreurs et avertissements de peluche, mais ne corrige pas automatiquementmake check
- via des crochets pre-commit
, formats votre code et tente de corriger automatiquement les erreurs de pelucheruff
sur les usages avancés Exécutez la commande mflux-generate
en spécifiant une invite et le modèle et certains arguments facultatifs. Par exemple, nous utilisons ici une version quantifiée du modèle schnell
pour 2 étapes:
mflux-generate --model schnell --prompt " Luxury food photograph " --steps 2 --seed 2 -q 8
Cet exemple utilise le modèle dev
plus puissant avec 25 étapes de temps:
mflux-generate --model dev --prompt " Luxury food photograph " --steps 25 --seed 2 -q 8
Par défaut, les fichiers du modèle sont téléchargés dans le dossier .cache
dans votre répertoire domestique. Par exemple, dans ma configuration, le chemin ressemble à ceci:
/Users/filipstrand/.cache/huggingface/hub/models--black-forest-labs--FLUX.1-dev
Pour modifier ce comportement par défaut, vous pouvez le faire en modifiant la variable d'environnement HF_HOME
. Pour plus de détails sur la façon d'ajuster ce paramètre, veuillez vous référer à la documentation des étreintes .
FLUX.1-DEV exige actuellement l'accès à son repo HuggingFace. Pour le dépannage, consultez le tracker du problème
--prompt
(requis, str
): Description du texte de l'image à générer.
--model
ou -m
(requis, str
): modèle à utiliser pour la génération ( "schnell"
ou "dev"
).
--output
(Facultatif, str
, par défaut: "image.png"
): sortie de fichier d'image de sortie.
--seed
(facultatif, int
, par défaut: None
): graine pour la génération de nombres aléatoires. La valeur par défaut est basée sur le temps.
--height
(facultatif, int
, par défaut: 1024
): hauteur de l'image de sortie en pixels.
--width
(facultatif, int
, par défaut: 1024
): Largeur de l'image de sortie en pixels.
--steps
(facultatif, int
, par défaut: 4
): nombre d'étapes d'inférence.
--guidance
(Facultatif, float
, par défaut: 3.5
): Échelle de guidage (uniquement utilisée pour le modèle "dev"
).
--path
(Facultatif, str
, par défaut: None
): Chemin vers un modèle local sur le disque.
--quantize
ou -q
(facultatif, int
, par défaut: None
): quantification (choisissez entre 4
ou 8
).
--lora-paths
(Facultatif, [str]
, par défaut: None
): les chemins vers les poids LORA.
--lora-scales
(Facultatif, [float]
, par défaut: None
): L'échelle pour chaque LORA respective (sera par défaut à 1.0
si elle n'est pas spécifiée et un seul poids LORA est chargé.)
--metadata
(facultatif): exporte un fichier .json
contenant les métadonnées de l'image avec le même nom. (Même sans ce drapeau, les métadonnées de l'image sont enregistrées et peuvent être visualisées à l'aide exiftool image.png
)
--controlnet-image-path
(Obligatoire, str
): chemin vers l'image locale utilisée par ControlNet pour guider la génération de sortie.
--controlnet-strength
(facultatif, float
, par défaut: 0.4
): degré d'influence que l'image de contrôle a sur la sortie. Varie de 0.0
(aucune influence) à 1.0
(pleine influence).
--controlnet-save-canny
(Facultatif, bool, par défaut: false): si défini, enregistre l'image de référence de détection de bord de pointe utilisée par ControlNet.
--init-image-path
(Facultatif, str
, par défaut: None
): Chemin local vers l'image initiale pour la génération d'image à image.
--init-image-strength
(Facultatif, float
, par défaut: 0.4
): Contrôle la force de l'image initiale influence l'image de sortie. Une valeur de 0.0
signifie aucune influence. (La valeur par défaut est 0.4
)
--config-from-metadata
ou -C
(Facultatif, str
): chemin [expérimental] vers un fichier antérieur enregistré via --metadata
, ou un fichier de configuration fabriqué à la main compatible adhérant au schéma Args attendu.
{
"$schema" : " http://json-schema.org/draft-07/schema# " ,
"type" : " object " ,
"properties" : {
"seed" : {
"type" : [ " integer " , " null " ]
},
"steps" : {
"type" : [ " integer " , " null " ]
},
"guidance" : {
"type" : [ " number " , " null " ]
},
"quantize" : {
"type" : [ " null " , " string " ]
},
"lora_paths" : {
"type" : [ " array " , " null " ],
"items" : {
"type" : " string "
}
},
"lora_scales" : {
"type" : [ " array " , " null " ],
"items" : {
"type" : " number "
}
},
"prompt" : {
"type" : [ " string " , " null " ]
}
}
}
{
"model" : " dev " ,
"seed" : 42 ,
"steps" : 8 ,
"guidance" : 3.0 ,
"quantize" : 4 ,
"lora_paths" : [
" /some/path1/to/subject.safetensors " ,
" /some/path2/to/style.safetensors "
],
"lora_scales" : [
0.8 ,
0.4
],
"prompt" : " award winning modern art, MOMA "
}
Ou, avec l'environnement python correct actif, créez et exécutez un script séparé comme les suivants:
from mflux import Flux1 , Config
# Load the model
flux = Flux1 . from_alias (
alias = "schnell" , # "schnell" or "dev"
quantize = 8 , # 4 or 8
)
# Generate an image
image = flux . generate_image (
seed = 2 ,
prompt = "Luxury food photograph" ,
config = Config (
num_inference_steps = 2 , # "schnell" works well with 2-4 steps, "dev" works well with 20-25 steps
height = 1024 ,
width = 1024 ,
)
)
image . save ( path = "image.png" )
Pour plus d'options sur la façon de configurer MFLUX, veuillez consulter generate.py.
Ces nombres sont basés sur le modèle schnell
non quantifié , avec la configuration fournie dans l'extrait de code ci-dessous. Pour chronométrer votre machine, exécutez ce qui suit:
time mflux-generate
--prompt " Luxury food photograph "
--model schnell
--steps 2
--seed 2
--height 1024
--width 1024
Pour découvrir la spécification de votre machine (y compris le nombre de cœurs de processeur, les cœurs GPU et la mémoire, exécutez la commande suivante:
system_profiler SPHardwareDataType SPDisplaysDataType
Appareil | Série M | Utilisateur | Temps signalé | Notes |
---|---|---|---|---|
Mac Studio | 2023 M2 Ultra | @awni | <15S | |
MacBook Pro | 2024 M4 Max (128 Go) | @ivanfioravanti | ~ 19S | |
MacBook Pro | 2023 m3 max | @Karpathy | ~ 20s | |
- | 2023 m2 max (96 Go) | @Explorigin | ~ 25S | |
Mac Mini | 2024 M4 Pro (64 Go) | @Stoobs | ~ 34S | |
Mac Mini | 2023 M2 Pro (32 Go) | @leekichko | ~ 54S | |
- | 2022 M1 Max (64 Go) | @Bosseparra | ~ 55S | |
MacBook Pro | 2023 m2 max (32 Go) | @filipstrand | ~ 70S | |
- | 2023 M3 Pro (36 Go) | @ kush-gupt | ~ 80s | |
MacBook Pro | 2021 M1 Pro (32 Go) | @filipstrand | ~ 160 | |
- | 2021 M1 Pro (16 Go) | @ qw-in | ~ 175S | Pourrait geler votre mac |
MacBook Air | 2020 M1 (8 Go) | @mbvillaverde | ~ 335S | Avec résolution 512 x 512 |
Notez que ces nombres incluent le démarrage de l'application à partir de zéro, ce qui signifie faire du modèle d'E / S, régler / quantification des poids, etc. Si nous supposons que le modèle est déjà chargé, vous pouvez inspecter les métadonnées de l'image à l'aide exiftool image.png
et voir le total Durée de la boucle de débrassement (à l'exclusion de l'intégration du texte).
Ces repères ne sont pas très scientifiques et ne sont destinés qu'à donner des numéros de base. Ils ont été réalisés à différents moments avec différents versions MFLUX et MLX, etc. Des informations matérielles supplémentaires telles que le nombre de cœurs GPU, le périphérique MAC, etc. ne sont pas toujours connus.
Il n'y a qu'une seule source d'aléatoire lors de la génération d'une image: le tableau latent initial. Dans cette implémentation, ce latent initial est complètement contrôlé de manière déterministe par le paramètre seed
d'entrée. Cependant, si nous devions importer une instance fixe de ce tableau latent enregistré à partir de l'implémentation des diffuseurs, MFLUX produira une image identique à l'implémentation des diffuseurs (en supposant une invite fixe et en utilisant les paramètres de paramètre par défaut dans la configuration des diffuseurs).
Les images ci-dessous illustrent cette équivalence. Dans tous les cas, le modèle Schnell a été exécuté pendant 2 pas de temps. L'implémentation des diffuseurs s'est déroulée en mode CPU. La précision pour MFLUX peut être définie dans la classe de configuration. Il y a généralement une différence notable mais très petite dans l'image finale lors de la passage entre 16 bits et précision 32 bits.
Luxury food photograph
detailed cinematic dof render of an old dusty detailed CRT monitor on a wooden desk in a dim room with items around, messy dirty room. On the screen are the letters "FLUX" glowing softly. High detail hard surface render
photorealistic, lotr, A tiny red dragon curled up asleep inside a nest, (Soft Focus) , (f_stop 2.8) , (focal_length 50mm) macro lens f/2. 8, medieval wizard table, (pastel) colors, (cozy) morning light filtering through a nearby window, (whimsical) steam shapes, captured with a (Canon EOS R5) , highlighting (serene) comfort, medieval, dnd, rpg, 3d, 16K, 8K
A weathered fisherman in his early 60s stands on the deck of his boat, gazing out at a stormy sea. He has a thick, salt-and-pepper beard, deep-set blue eyes, and skin tanned and creased from years of sun exposure. He's wearing a yellow raincoat and hat, with water droplets clinging to the fabric. Behind him, dark clouds loom ominously, and waves crash against the side of the boat. The overall atmosphere is one of tension and respect for the power of nature.
Luxury food photograph of an italian Linguine pasta alle vongole dish with lots of clams. It has perfect lighting and a cozy background with big bokeh and shallow depth of field. The mood is a sunset balcony in tuscany. The photo is taken from the side of the plate. The pasta is shiny with sprinkled parmesan cheese and basil leaves on top. The scene is complemented by a warm, inviting light that highlights the textures and colors of the ingredients, giving it an appetizing and elegant look.
MFLUX prend en charge le flux d'exécution en mode quantifié 4 bits ou 8 bits. L'exécution d'une version quantifiée peut considérablement accélérer le processus de génération et réduire la consommation de mémoire par plusieurs gigaoctets. Les modèles quantifiés occupent également moins d'espace disque.
mflux-generate
--model schnell
--steps 2
--seed 2
--quantize 8
--height 1920
--width 1024
--prompt " Tranquil pond in a bamboo forest at dawn, the sun is barely starting to peak over the horizon, panda practices Tai Chi near the edge of the pond, atmospheric perspective through the mist of morning dew, sunbeams, its movements are graceful and fluid — creating a sense of harmony and balance, the pond’s calm waters reflecting the scene, inviting a sense of meditation and connection with nature, style of Howard Terpning and Jessica Rossier "
Dans cet exemple, les poids sont quantifiés au moment de l'exécution - cela est pratique si vous ne voulez pas économiser une copie quantifiée des poids sur le disque, mais que vous souhaitez toujours bénéficier de l'accélération potentielle et de la quantification de réduction de la RAM pourrait apporter.
En sélectionnant l'indicateur --quantize
ou -q
pour être 4
, 8
ou le supprimant entièrement, nous obtenons les 3 images ci-dessus. Comme on peut le voir, il y a très peu de différence entre les images (en particulier entre le 8 bits et le résultat non quantifié). Les temps de génération d'images dans cet exemple sont basés sur une machine 2021 M1 Pro (32 Go). Même si les images sont presque identiques, il y a une accélération de ~ 2x en exécutant la version quantifiée 8 bits sur cette machine particulière. Contrairement à la version non quantifiée, pour la version 8 bits, l'utilisation de la mémoire d'échange est considérablement réduite et l'utilisation du GPU est proche de 100% pendant toute la génération. Les résultats ici peuvent varier d'une machine à l'autre.
Les tailles de modèle pour schnell
et dev
à différents niveaux de quantification sont les suivantes:
4 bits | 8 bits | Original (16 bits) |
---|---|---|
9.85 Go | 18.16 Go | 33,73 Go |
La raison pour laquelle les tailles de poids ne sont pas entièrement coupées en deux est dû au fait qu'un petit nombre de poids ne sont pas quantifiés et maintenus à pleine précision.
Pour économiser une copie locale des poids quantifiés, exécutez la commande mflux-save
comme ainsi:
mflux-save
--path " /Users/filipstrand/Desktop/schnell_8bit "
--model schnell
--quantize 8
Notez que lors de la sauvegarde d'une version quantifiée, vous aurez besoin des poids d'origine Hugging Face.
Il est également possible de spécifier les adaptateurs LORA lors de l'enregistrement du modèle, par exemple
mflux-save
--path " /Users/filipstrand/Desktop/schnell_8bit "
--model schnell
--quantize 8
--lora-paths " /path/to/lora.safetensors "
--lora-scales 0.7
Lors de la génération d'images avec un modèle comme celui-ci, aucun adaptateur LORA n'est nécessaire pour être spécifié car il est déjà cuit dans les poids quantifiés enregistrés.
Pour générer une nouvelle image à partir du modèle quantifié, fournissez simplement un --path
à l'endroit où il a été enregistré:
mflux-generate
--path " /Users/filipstrand/Desktop/schnell_8bit "
--model schnell
--steps 2
--seed 2
--height 1920
--width 1024
--prompt " Tranquil pond in a bamboo forest at dawn, the sun is barely starting to peak over the horizon, panda practices Tai Chi near the edge of the pond, atmospheric perspective through the mist of morning dew, sunbeams, its movements are graceful and fluid — creating a sense of harmony and balance, the pond’s calm waters reflecting the scene, inviting a sense of meditation and connection with nature, style of Howard Terpning and Jessica Rossier "
Remarque: Lors du chargement d'un modèle quantifié à partir du disque, il n'est pas nécessaire de passer dans un drapeau -q
, car nous pouvons déduire cela à partir des métadonnées de poids.
Remarque également: une fois que nous avons un modèle local (quantifié ou non) spécifié via l'argument --path
, les modèles de cache HuggingFace ne sont pas nécessaires pour lancer le modèle. En d'autres termes, vous pouvez récupérer l'espace de disque de 34 Go (par modèle) en supprimant le modèle complet 16 bits du cache HuggingFace si vous choisissez.
Si vous ne souhaitez pas télécharger les modèles complets et les quantifier vous-même, les poids 4 bits sont disponibles ici pour un téléchargement direct:
MFLUX prend également en charge l'exécution d'un modèle non quantifié directement à partir d'un emplacement personnalisé. Dans l'exemple ci-dessous, le modèle est placé dans /Users/filipstrand/Desktop/schnell
:
mflux-generate
--path " /Users/filipstrand/Desktop/schnell "
--model schnell
--steps 2
--seed 2
--prompt " Luxury food photograph "
Notez que l'indicateur --model
doit être défini lors du chargement d'un modèle à partir du disque.
Notez également que contrairement à l'utilisation de la manière alias
typique d'initialiser le modèle (qui gère en interne que les ressources requises sont téléchargées), lors du chargement d'un modèle directement à partir du disque, nous avons besoin que les modèles téléchargés ressemblent à ce qui suit:
.
├── text_encoder
│ └── model.safetensors
├── text_encoder_2
│ ├── model-00001-of-00002.safetensors
│ └── model-00002-of-00002.safetensors
├── tokenizer
│ ├── merges.txt
│ ├── special_tokens_map.json
│ ├── tokenizer_config.json
│ └── vocab.json
├── tokenizer_2
│ ├── special_tokens_map.json
│ ├── spiece.model
│ ├── tokenizer.json
│ └── tokenizer_config.json
├── transformer
│ ├── diffusion_pytorch_model-00001-of-00003.safetensors
│ ├── diffusion_pytorch_model-00002-of-00003.safetensors
│ └── diffusion_pytorch_model-00003-of-00003.safetensors
└── vae
└── diffusion_pytorch_model.safetensors
Cela reflète la façon dont les ressources sont placées dans le repo HuggingFace pour le flux.1. Les poids des étreintes, contrairement à ceux quantifiés exportés directement à partir de ce projet, doivent être traités un peu différemment, c'est pourquoi nous avons besoin de cette structure ci-dessus.
Une façon de conditionner la génération d'images consiste à partir à partir d'une image existante et à laisser MFLUX produire de nouvelles variations. Utilisez l'indicateur --init-image-path
pour spécifier l'image de référence, et la --init-image-strength
pour contrôler la quantité de référence que l'image doit guider la génération. Par exemple, compte tenu de l'image de référence ci-dessous, la commande suivante a produit la première image à l'aide de la croquis LORA:
mflux-generate
--prompt " sketching of an Eiffel architecture, masterpiece, best quality. The site is lit by lighting professionals, creating a subtle illumination effect. Ink on paper with very fine touches with colored markers, (shadings:1.1), loose lines, Schematic, Conceptual, Abstract, Gestural. Quick sketches to explore ideas and concepts. "
--init-image-path " reference.png "
--init-image-strength 0.3
--lora-paths Architectural_Sketching.safetensors
--lora-scales 1.0
--model dev
--steps 20
--seed 43
--guidance 4.0
--quantize 8
--height 1024
--width 1024
Comme avec ControlNet, cette technique se combine bien avec les adaptateurs LORA:
Dans les exemples ci-dessus, les loras suivants sont des croquis utilisés, la prise de vue d'animation et le flux-film-caméra sont utilisés.
Adaptateurs LORA de chargement MFLUX Loading (le support de formation réel arrive).
L'exemple suivant The_hound Lora de @thelastben:
mflux-generate --prompt " sandor clegane " --model dev --steps 20 --seed 43 -q 8 --lora-paths " sandor_clegane_single_layer.safetensors "
L'exemple suivant est FLUX_1_DEV_LORA_LANT LORA de style Cutout de @ Norod78:
mflux-generate --prompt " pikachu, Paper Cutout Style " --model schnell --steps 4 --seed 43 -q 8 --lora-paths " Flux_1_Dev_LoRA_Paper-Cutout-Style.safetensors "
Notez que les poids formés de Lora sont généralement formés avec un mot ou une phrase déclencheur . Par exemple, dans ce dernier cas, la phrase doit inclure la phrase "style de découpe de papier" .
Notez également que les mêmes poids LORA peuvent bien fonctionner avec les modèles schnell
et dev
. Reportez-vous au référentiel LORA d'origine pour voir à quel mode il a été formé.
Plusieurs loras peuvent être envoyés pour combiner les effets des adaptateurs individuels. L'exemple suivant combine les deux loras ci-dessus:
mflux-generate
--prompt " sandor clegane in a forest, Paper Cutout Style "
--model dev
--steps 20
--seed 43
--lora-paths sandor_clegane_single_layer.safetensors Flux_1_Dev_LoRA_Paper-Cutout-Style.safetensors
--lora-scales 1.0 1.0
-q 8
Juste pour voir la différence, cette image affiche les quatre cas: l'un d'avoir les deux adaptateurs entièrement actifs, partiellement actifs et pas du tout LORA. L'exemple ci-dessus montre également l'utilisation du drapeau --lora-scales
.
Étant donné que différents services de réglage fin peuvent utiliser différentes implémentations de flux, les poids LORA correspondants formés sur ces services peuvent être différents les uns des autres. L'objectif de MFLUX est de soutenir les plus courants. Le tableau suivant montre les formats pris en charge actuels:
Soutenu | Nom | Exemple | Notes |
---|---|---|---|
✅ | Bfl | civitai - impressionnisme | Beaucoup de choses sur la civitai semblent fonctionner |
✅ | Diffuseurs | Flux_1_dev_lora_paper-cutout-style | |
Xlabs-ai | Flux-Remismlora |
Pour signaler des formats supplémentaires, des exemples ou d'autres suggestions liées à la prise en charge du format LORA, veuillez consulter le numéro 47.
MFLUX a la prise en charge de ControlNet pour un contrôle encore plus grainé de la génération d'images. En fournissant une image de référence via --controlnet-image-path
et un paramètre de résistance via --controlnet-strength
, vous pouvez guider la génération vers l'image de référence.
mflux-generate-controlnet
--prompt " A comic strip with a joker in a purple suit "
--model dev
--steps 20
--seed 1727047657
--height 1066
--width 692
-q 8
--lora-paths " Dark Comic - s0_8 g4.safetensors "
--controlnet-image-path " reference.png "
--controlnet-strength 0.5
--controlnet-save-canny
Cet exemple combine l'image de référence ControlNet avec le flux de bande dessinée Lora Dark .
generate-controlnet
. À l'heure actuelle, le ControlNet utilisé est Instantx / Flux.1-Dev-Controlnet-Canny, qui a été formé pour le modèle dev
. Cela peut bien fonctionner avec schnell
, mais les performances ne sont pas garanties.
ControlNet peut également bien fonctionner avec les adaptateurs LORA. Dans l'exemple ci-dessous, la même image de référence est utilisée comme entrée ControlNet avec différentes invites et les adaptateurs LORA actifs.
export HF_HUB_DISABLE_PROGRESS_BARS=1
--args
alias mflux-dev='mflux-generate --model dev'
alias mflux-schnell='mflux-generate --model schnell --metadata'
Ce projet est autorisé sous la licence du MIT.