0
.github/workflows/ci.yaml
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
.idea/.gitignore
generated
vendored
Normal file → Executable file
0
.idea/flux2.iml
generated
Normal file → Executable file
0
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file → Executable file
0
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file → Executable file
0
.idea/misc.xml
generated
Normal file → Executable file
0
.idea/modules.xml
generated
Normal file → Executable file
0
.idea/vcs.xml
generated
Normal file → Executable file
0
.pre-commit-config.yaml
Normal file → Executable file
0
.yamlfmt.yaml
Normal file → Executable file
37
Dockerfile
Executable file
@@ -0,0 +1,37 @@
|
||||
FROM ghcr.io/astral-sh/uv:latest AS uv_bin
|
||||
FROM nvidia/cuda:12.4.1-base-ubuntu22.04
|
||||
|
||||
# 1. 基础环境配置
|
||||
ENV UV_LINK_MODE=copy \
|
||||
UV_COMPILE_BYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
UV_PROJECT_ENVIRONMENT=/app/.venv
|
||||
|
||||
COPY --from=uv_bin /uv /uvx /bin/
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
wget \
|
||||
libcurl4-openssl-dev \
|
||||
build-essential \
|
||||
libgl1 \
|
||||
libglib2.0-0 \
|
||||
ca-certificates \
|
||||
git \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY pyproject.toml uv.lock ./
|
||||
|
||||
ENV UV_COMPILE_BYTECODE=0
|
||||
|
||||
RUN uv sync --frozen --no-dev --no-install-project --python 3.12
|
||||
|
||||
# 4. 拷贝项目文件并安装项目本身
|
||||
RUN uv sync --frozen --no-dev --python 3.12
|
||||
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["uv", "run","-m","app.litserve_serve"]
|
||||
0
LICENSE.md
Normal file → Executable file
0
litserve/app.py → app/litserve/app.py
Normal file → Executable file
0
litserve/cli.py → app/litserve/cli.py
Normal file → Executable file
0
litserve/client.py → app/litserve/client.py
Normal file → Executable file
0
litserve/model.py → app/litserve/model.py
Normal file → Executable file
8
litserve_serve.py → app/litserve_serve.py
Normal file → Executable file
@@ -6,10 +6,9 @@ from minio import Minio
|
||||
import litserve as ls
|
||||
from PIL import Image
|
||||
import io
|
||||
import base64
|
||||
from diffusers import Flux2KleinPipeline
|
||||
|
||||
from utils.new_oss_client import oss_get_image, oss_upload_image, MINIO_URL, MINIO_ACCESS, MINIO_SECRET, MINIO_SECURE
|
||||
from app.utils.new_oss_client import oss_get_image, oss_upload_image, MINIO_URL, MINIO_ACCESS, MINIO_SECRET, MINIO_SECURE
|
||||
|
||||
minio_client = Minio(MINIO_URL, access_key=MINIO_ACCESS, secret_key=MINIO_SECRET, secure=MINIO_SECURE)
|
||||
|
||||
@@ -117,9 +116,10 @@ class FluxKleinAPI(ls.LitAPI):
|
||||
images = payload.get("images", [])
|
||||
prompt = payload.get("prompt", "")
|
||||
gen = torch.Generator(device=self.device)
|
||||
output = {}
|
||||
seed = gen.seed()
|
||||
print(f"本次使用的随机种子是: {seed}")
|
||||
if images:
|
||||
output['im'] = self.pipe(
|
||||
output = self.pipe(
|
||||
image=images,
|
||||
prompt=prompt,
|
||||
height=payload.get("height", 512),
|
||||
2
utils/new_oss_client.py → app/utils/new_oss_client.py
Normal file → Executable file
@@ -61,7 +61,7 @@ def oss_upload_image(oss_client, bucket, object_name, image_bytes):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
url = "test/fida_generate_image/692932cfecd9499688899812737a369c.png"
|
||||
url = "test/fida_generate_image/9fea0a597d884c81a5a4c8381b7bae2c.png"
|
||||
img = oss_get_image(oss_client=minio_client, bucket=url.split('/')[0], object_name=url[url.find('/') + 1:])
|
||||
img.show()
|
||||
img.save("result.png")
|
||||
0
assets/i2i_klein.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.6 MiB |
0
assets/i2i_upsample_example.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
0
assets/i2i_upsample_input.png
Normal file → Executable file
|
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 290 KiB |
0
assets/klein_benchmark.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 408 KiB After Width: | Height: | Size: 408 KiB |
0
assets/t2i_klein_others.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB |
0
assets/t2i_klein_realism.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.6 MiB |
0
assets/t2i_upsample_example.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
0
assets/teaser_editing.png
Normal file → Executable file
|
Before Width: | Height: | Size: 11 MiB After Width: | Height: | Size: 11 MiB |
0
assets/teaser_generation.png
Normal file → Executable file
|
Before Width: | Height: | Size: 22 MiB After Width: | Height: | Size: 22 MiB |
19
docker-compose.yml
Executable file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
flux2_klein:
|
||||
restart: always
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./app:/app/app
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "14202:8451"
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
device_ids: [ '0' ]
|
||||
capabilities: [ gpu ]
|
||||
0
docs/flux2_dev_hf.md
Normal file → Executable file
0
docs/flux2_with_prompt_upsampling.md
Normal file → Executable file
0
model_cards/FLUX.2-dev.md
Normal file → Executable file
0
model_licenses/LICENSE-FLUX-DEV
Normal file → Executable file
0
model_licenses/LICENSE-FLUX-NON-COMMERICAL
Normal file → Executable file
4
pyproject.toml
Normal file → Executable file
@@ -21,6 +21,7 @@ dependencies = [
|
||||
"datetime>=6.0",
|
||||
"litserve>=0.2.17",
|
||||
"minio>=7.2.20",
|
||||
"diffusers",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
@@ -46,3 +47,6 @@ quote-style = "double"
|
||||
indent-style = "space"
|
||||
line-ending = "auto"
|
||||
docstring-code-format = true
|
||||
|
||||
[tool.uv.sources]
|
||||
diffusers = { git = "https://github.com/huggingface/diffusers.git" }
|
||||
|
||||
BIN
result1.png
|
Before Width: | Height: | Size: 963 KiB |
0
scripts/cli.py
Normal file → Executable file
0
src/flux2/autoencoder.py
Normal file → Executable file
0
src/flux2/model.py
Normal file → Executable file
0
src/flux2/openrouter_api_client.py
Normal file → Executable file
0
src/flux2/sampling.py
Normal file → Executable file
0
src/flux2/system_messages.py
Normal file → Executable file
0
src/flux2/text_encoder.py
Normal file → Executable file
0
src/flux2/util.py
Normal file → Executable file
0
src/flux2/watermark.py
Normal file → Executable file
31
test.py
@@ -1,31 +0,0 @@
|
||||
import datetime
|
||||
import time
|
||||
|
||||
import torch
|
||||
from PIL import Image
|
||||
from diffusers import Flux2KleinPipeline
|
||||
|
||||
device = "cuda"
|
||||
dtype = torch.bfloat16
|
||||
|
||||
pipe = Flux2KleinPipeline.from_pretrained("black-forest-labs/FLUX.2-klein-4B", torch_dtype=dtype, is_distilled=False)
|
||||
pipe.to(device) # save some VRAM by offloading the model to CPUsave some VRAM by offloading the model to CPU
|
||||
|
||||
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
prompt = ""
|
||||
num_inference_steps = 4
|
||||
input_image = Image.open("result1.png")
|
||||
|
||||
start_time = time.time()
|
||||
image = pipe(
|
||||
image=input_image,
|
||||
prompt=prompt,
|
||||
height=768,
|
||||
width=512,
|
||||
guidance_scale=1.0,
|
||||
num_inference_steps=num_inference_steps,
|
||||
# generator=torch.Generator(device=device).manual_seed(3)
|
||||
).images[0]
|
||||
|
||||
image.save(f"{timestamp}_{num_inference_steps}steps.png")
|
||||
print(f"infer time : {time.time() - start_time}")
|
||||
40
uv.lock
generated
Normal file → Executable file
@@ -244,6 +244,23 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/7a/ea0f3e3ea74be36fc7cf54f966cde732a3de72697983cdb5646b0a4dacde/datetime-6.0-py3-none-any.whl", hash = "sha256:d19988f0657a4e72c9438344157254a8dcad6aea8cd5ae70a5d1b5a75e5dc930", size = 52637, upload-time = "2025-11-25T08:00:33.077Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diffusers"
|
||||
version = "0.38.0.dev0"
|
||||
source = { git = "https://github.com/huggingface/diffusers.git#11a3284cee024bfff017408b303d18e88981d2ea" }
|
||||
dependencies = [
|
||||
{ name = "filelock" },
|
||||
{ name = "httpx" },
|
||||
{ name = "huggingface-hub" },
|
||||
{ name = "importlib-metadata" },
|
||||
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||
{ name = "numpy", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||
{ name = "pillow" },
|
||||
{ name = "regex" },
|
||||
{ name = "requests" },
|
||||
{ name = "safetensors" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distro"
|
||||
version = "1.9.0"
|
||||
@@ -317,6 +334,7 @@ source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "accelerate" },
|
||||
{ name = "datetime" },
|
||||
{ name = "diffusers" },
|
||||
{ name = "einops" },
|
||||
{ name = "fire" },
|
||||
{ name = "litserve" },
|
||||
@@ -337,6 +355,7 @@ dev = [
|
||||
requires-dist = [
|
||||
{ name = "accelerate", specifier = "==1.12.0" },
|
||||
{ name = "datetime", specifier = ">=6.0" },
|
||||
{ name = "diffusers", git = "https://github.com/huggingface/diffusers.git" },
|
||||
{ name = "einops", specifier = "==0.8.1" },
|
||||
{ name = "fire", specifier = "==0.7.1" },
|
||||
{ name = "litserve", specifier = ">=0.2.17" },
|
||||
@@ -468,6 +487,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "zipp" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
@@ -1697,6 +1728,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.23.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zope-interface"
|
||||
version = "8.2"
|
||||
|
||||