文档备案控制台
免费开始使用

FLUX + LoRA 实测,AI 绘画开启新纪元,5分钟带你部署体验

猴哥的第 69 期分享,欢迎追看

FLUX 作为 AI 绘画界的新秀,最近火的不行。且看:

开源版 Midjourney 来了,无需本地显卡,5 分钟带你玩转 AI 绘画模型

拳打MJ脚踢SD,爆火FLux任性玩!免费API,速速领取

社区给它的标签是:一个比 SD 更强的 AI 绘画模型。

不过根据猴哥的实测来看,FLUX 尽管在细节处理方面的功力了得,但在写实摄影还比不过 SD 的专业选手,而专业的背后是各种 LoRA 模型的加持。

仅过去一周,FLUX 版 LoRA 也出来了,比如 XLabs AI Realism 这款 LoRA,可以让你生成的图片更加写实。

今天就带大家实操一番,给你的 FLUX,装上 LoRA,让生图不再抽卡!

  1. 环境准备

首先,git 下载 camenduru/ComfyUI 项目的 totoro4 分支:

  
git clone -b totoro4 https://github.com/camenduru/ComfyUI  
cd ComfyUI  

为了方便环境管理,我们新建一个虚拟环境:

  
conda create -p envs/flux python=3.10  
conda activate envs/flux/  

然后,新建 requirements.txt,填入如下环境依赖:

  
torchsde  
einops  
diffusers  
accelerate  
xformers==0.0.27  
gradio==4.40.0  
transformers  
fastapi  

一键安装:pip install -r requirements.txt,上述 xformers 依赖 2.3.1版本的torch。如果遇到如下报错:

  
libtorch_cuda.so: undefined symbol: ncclCommRegister  

这是 PyTorch 和 NCCL 版本与 CUDA 版本不兼容的问题,建议重新使用 conda 重新安装对应 CUDA 版本的 Pytorch,比如我这里用的是 CUDA 12.1 的镜像:

  
# 安装指定版本:https://pytorch.org/get-started/previous-versions/  
conda install pytorch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 pytorch-cuda=12.1 -c pytorch -c nvidia  

  1. 模型下载

❝ HF地址:https://huggingface.co/camenduru/FLUX.1-dev

国内镜像:https://hf-mirror.com/camenduru/FLUX.1-dev/

Huggingface 这个仓库中,集成了 FLUX 底模和各种 LoRA 模型,我们可以按需下载。

下载好的模型存放在根目录 models 文件夹下:

  
# 存放底模  
mkdir -p models/checkpoints  
# 存放 LoRA  
mkdir -p models/loras  

picture.image

  1. WebUI 部署

环境和模型准备好之后,我们可以编写代码,首先本地测试下加载 LoRA 模型的生成效果:

❝ 为方便展示,这里只贴出了核心实现,完整代码较长,感兴趣的小伙伴可以拉到文末自取。

  
lora_models = os.listdir('models/loras')  
lora_models = [lora for lora in lora_models if not lora.startswith('flux1-dev')]  
  
with torch.inference_mode():  
    unet, clip, vae = CheckpointLoaderSimple.load_checkpoint("flux1-dev-fp8-all-in-one.safetensors")  
    print('load model successfully')  
  
@torch.inference_mode()  
def generate(positive_prompt='a cat',   
             width=1024,   
             height=1024,   
             seed=0,   
             steps=20,   
             sampler_name="euler",   
             scheduler="simple",  
             guidance=3.5,  
             lora_strength_model=1.0,  
             lora_strength_clip=1.0,  
             lora_model="flux\_realism\_lora.safetensors"):  
    global unet, clip  
    if seed == 0:  
        seed = random.randint(0, 18446744073709551615)  
    unet_lora, clip_lora = LoraLoader.load_lora(unet, clip, lora_model, lora_strength_model, lora_strength_clip)  
    cond, pooled = clip_lora.encode_from_tokens(clip_lora.tokenize(positive_prompt), return_pooled=True)  
    cond = [[cond, {"pooled\_output": pooled}]]  
    cond = FluxGuidance.append(cond, guidance)[0]  
    noise = RandomNoise.get_noise(seed)[0]  
    guider = BasicGuider.get_guider(unet_lora, cond)[0]  
    sampler = KSamplerSelect.get_sampler(sampler_name)[0]  
    sigmas = BasicScheduler.get_sigmas(unet_lora, scheduler, steps, 1.0)[0]  
    latent_image = EmptyLatentImage.generate(closestNumber(width, 16), closestNumber(height, 16))[0]  
    sample, sample_denoised = SamplerCustomAdvanced.sample(noise, guider, sampler, sigmas, latent_image)  
    decoded = VAEDecode.decode(vae, sample)[0].detach()  
    Image.fromarray(np.array(decoded*255, dtype=np.uint8)[0]).save("flux.png")  
    return "flux.png"  

生成结果保存在本地图片:

picture.image

然后,我们采用 Gradio 编写一个简单的 UI 界面:

  
with gr.Blocks(analytics_enabled=False) as demo:  
        with gr.Row():  
            with gr.Column():  
                positive_prompt = gr.Textbox(lines=3, interactive=True, value="a cat", label="Prompt")  
                loras = gr.Dropdown(lora_models, label="LORA Model", value="flux\_realism\_lora.safetensors")  
                with gr.Row():  
                    width = gr.Slider(minimum=256, maximum=2048, value=1024, step=16, label="width")  
                    height = gr.Slider(minimum=256, maximum=2048, value=1024, step=16, label="height")  
                with gr.Row():  
                    seed = gr.Slider(minimum=0, maximum=18446744073709551615, value=0, step=1, label="seed (0=random)")  
                    steps = gr.Slider(minimum=4, maximum=50, value=20, step=1, label="steps")  
                with gr.Row():  
                    guidance = gr.Slider(minimum=0, maximum=20, value=3.5, step=0.5, label="guidance")  
                    lora_strength_model = gr.Slider(minimum=0, maximum=1, value=1.0, step=0.1, label="lora\_strength\_model")  
                    lora_strength_clip = gr.Slider(minimum=0, maximum=1, value=1.0, step=0.1, label="lora\_strength\_clip")  
                with gr.Row():  
                    sampler_name = gr.Dropdown(["euler", "heun", "heunpp2", "dpm\_2", "lms", "dpmpp\_2m", "ipndm", "deis", "ddim", "uni\_pc", "uni\_pc\_bh2"], label="sampler\_name", value="euler")  
                    scheduler = gr.Dropdown(["normal", "sgm\_uniform", "simple", "ddim\_uniform"], label="scheduler", value="simple")  
                generate_button = gr.Button("Generate")  
            with gr.Column():  
                output_image = gr.Image(label="Generated", interactive=False)  
        generate_button.click(fn=generate, inputs=[positive_prompt, width, height, seed, steps, sampler_name, scheduler, guidance, lora_strength_model, lora_strength_clip, loras], outputs=output_image)  
    demo.queue().launch(inline=False, share=False, debug=True, server_name='0.0.0.0')  

启动成功后,浏览器直达:localhost:7860~

左上角输入提示词,先选一个 漫画 风格的 LoRA 看看:

picture.image

再来看看 xlab 提供的 midjourney v6 的 LoRA 怎么样?picture.image

Disney 风格的 LoRA ?

picture.image

最后来看下显存占用情况,供大家参考:

picture.image

  1. 服务部署

对于爱折腾的开发者而言,自然要把服务部署好,方便任性调用~

4.1 服务端

我们采用 FastAPI 把模型部署成一个服务,首先准备好服务端代码 server.py

  
# 定义数据模型,用于接收POST请求中的数据,默认值后面不能加逗号,否则会是一个 tuple  
class Item(BaseModel):  
    positive_prompt: str = "a cat"  
    width: int = 512  
    height: int = 512  
    seed: int = 0  
    steps: int = 20  
    sampler_name: str = "euler"  
    scheduler: str = "simple"  
    guidance: float = 3.5  
    lora_strength_model: float = 1.0  
    lora_strength_clip: float = 1.0  
    lora_model: str = "flux\_realism\_lora.safetensors"  
  
app = FastAPI()  
@app.post("/txt2img")  
async def txt2img(item: Item):  
    try:  
        image_array = generate(positive_prompt=item.positive_prompt)  
        image = Image.fromarray(image_array.astype('uint8')).convert('RGB')  
        # 将PIL图像对象转换为二进制数据  
        with io.BytesIO() as output:  
            image.save(output, format="PNG")  
            image_binary = output.getvalue()  
        response = JSONResponse(content={"image": base64.b64encode(image_binary).decode()})  
    except Exception as e:  
        response = JSONResponse(content={"error": str(e)})  
    return response  
  
if __name__ == '\_\_main\_\_':  
    uvicorn.run(app, host='0.0.0.0', port=2002)  

python server.py 一键启动,成功后会看到如下提示:

  
load model successfully  
INFO:     Started server process [735]  
INFO:     Waiting for application startup.  
INFO:     Application startup complete.  
INFO:     Uvicorn running on http://0.0.0.0:2002 (Press CTRL+C to quit)  

4.2 客户端

服务启动后,我们来编写客户端代码:

  
# 发送GET请求获取图像数据  
headers = {'Content-Type': 'application/json'}  
data = {'positive\_prompt': 'a cat'}  
response = requests.post('http://localhost:2002/txt2img/', headers=headers, json=data)  
  
# 检查请求是否成功  
if response.status_code == 200:  
    data = response.json()  
    img_base64 = data['image']  
    image_binary = base64.b64decode(img_base64)  
    # 将二进制数据保存为本地文件  
    with open('image.png', 'wb') as file:  
        file.write(image_binary)  
else:  
    print("请求失败,状态码:", response.status_code)  

我们用同一套提示词生成三张图片,只有中间一张正确添加了 Logo CVLab

picture.image

这么看,抽卡还是难免啊~

写在最后

本文是 FLUX AI绘画系列的续篇,介绍了如何为FLUX添加LoRA模型来增强其生成效果,更多内容正在不断填坑中……

希望能激发你的更多创作灵感,让 FLUX 插上 LoRA 的翅膀带你飞向艺术新天地!

如果本文有帮助,不妨点个免费的赞收藏 备用。

本文所有源码+模型已打包,有需要的小伙伴,可以在公众号后台回复 “flux” 自取。

👇 关注猴哥,快速入门AI工具

picture.image

# AI 工具:

本地部署大模型?看这篇就够了,Ollama 部署和实战

【玩转云服务】Oracle Cloud甲骨文永久免费云服务器,来薅资本主义羊毛了!白嫖党请进!

# AI应用** :**

手把手搭建微信机器人,帮你雇一个24小时在线的个人 AI 助理(上)

视频生成 EasyAnimate-v3 实测,阿里开源,5 分钟带你部署体验,支持高分辨率超长视频

# 效率工具:

电脑微信双开/多开?两种方法任你挑,1分钟搞定

简单3步,搞定 Windows11 系统安装/重装

0
0
0
0
评论
未登录
暂无评论