☰
本地大模型+Stable Diffusion+FastAPI:搭建AI绘画提示词增强服务
2026/9/26 16:51:42 网站建设 项目流程

把本地大模型和Stable Diffusion真正串起来做成一套服务,前前后后花了我小半个月。起因其实很简单:我一直在用Diffusers本地跑文生图,但提示词这件事始终是个麻烦。直接说中文,模型理解得七零八落;自己硬写英文提示词,又常常词不达意。SDXL这类模型对提示词的讲究远比你想象中严格——主体、环境、光线、风格、画质词,缺一样,出图就"偏"。于是我就想,既然本地已经能跑大模型了,为什么不让它来当这个"翻译官"?这才有了这篇实战总结:用Ollama部署一个7B量级的本地大模型,负责把用户随口说出的想法整理成Stable Diffusion能听懂的提示词,用Diffusers调用SDXL生成图片,再用FastAPI把整条链路包成一个干净的REST接口。这套东西适合谁?想在内网或本地搭建文生图服务的人、做AI绘画工具但不想依赖云端接口的开发者、以及所有被提示词折磨过的朋友。它解决的核心问题就一句话:让AI绘画更听话。

1. 先想清楚:为什么这三样东西要凑在一起

1.1 裸用Stable Diffusion的痛,其实全在提示词上

很多人第一次用Diffusers本地出图,第一反应是"模型好难控制"。这事真不怪模型,怪提示词。Stable Diffusion系列模型是在海量英文图文对上训练的,它理解的"漂亮女孩在花园里"和你脑子里的画面根本不是一回事。你需要给出足够具体的主体描述、场景定义、光线方向、镜头语言、风格流派,还要顺手加上"masterpiece, best quality"这类画质词,否则出图就是灰蒙蒙一片。更要命的是中文输入——模型训练语料里中文占比很低,直接丢一句"月光下的古镇"进去,经常出来一张构图混乱、语义断裂的废图。

我最早的做法是写死一套英文模板,让用户往里面填词。但填词这个事对普通用户来说门槛太高了,而且每个人描述习惯不一样,模板一限死,画面就千篇一律。后来我才意识到,与其逼用户去学提示词语法,不如让另一个模型去理解用户的话、再翻译成模型听得懂的"行话"。这就是Ollama在这个项目里的位置。

1.2 Ollama在这里不是画画的,是当"翻译官"的

项目标题里把Ollama放在前面,很多人误以为图片是它生成的,其实不是。Ollama负责的是自然语言理解这一层:接收用户一句大白话,输出一段结构化的英文提示词,甚至顺带给出英文负面提示词。选它的理由很朴素——本地部署、免费、数据不出机器、一条命令启动,而且它对显卡的利用率比裸跑Python大模型脚本高不少,模型管理也省心。

模型我选的是qwen2.5:7b。7B这个体量在普通消费级显卡上能跑得动,理解中文和改写英文提示词的活儿它完全够用。如果你显卡更大,换14B或者32B版本效果会更好,但说实话提示词改写这个任务,7B和32B的差距很小,远不如在图像模型本身上下功夫。这里有一个新玩家容易踩的坑:如果你选的是带思维链或"思考模式"的模型,响应里会夹带一长串推理过程,直接污染提示词。新版Ollama对这类模型提供了关闭思考的选项,或者在system prompt里明确要求"不要输出任何分析过程,只输出提示词本身",实测后者更稳。

1.3 FastAPI为什么是合适的"胶水层"

链路里最后一个环节是FastAPI。选它不是因为流行,而是因为它实在太贴合这个场景了。第一,Pydantic的请求校验能帮我把接口参数限制得明明白白,分辨率、步数、引导系数这些数值该在什么范围,直接在模型定义里写死,非法请求根本进不了业务逻辑。第二,FastAPI自动生成交互式文档,接口调完还能在浏览器里直接试参数,调试效率高出一截。第三,Python生态和torch无缝衔接,不需要像Java、Go那样再包一层。最重要的一点是,FastAPI对同步阻塞任务的态度很务实——你定义普通函数,它自动丢进线程池执行,不会卡死事件循环。这个细节在文生图场景里非常关键,后面会专门说。

2. 整体架构与目录设计

2.1 一次完整的请求是怎么流转的

先把全链路讲清楚,你才知道代码该怎么组织。用户向FastAPI发一个POST请求,JSON里带着一句口语化的创作想法,比如"月光下的江南古镇,河面有倒影"。FastAPI先做参数校验,然后调用Ollama客户端,把这句话加上系统提示词模板一起发给Ollama的/api/generate接口。Ollama返回的是一段英文结构化提示词,可能还附一句负面提示词。拿到它之后,封装好的Diffusers管线开始工作:加载的Stable Diffusion模型根据提示词做去噪生成,出一张PIL图片。最后FastAPI把图片编码成PNG字节流,通过HTTP响应返回给调用方。整条链路里,Ollama是"翻译官",Diffusers是"画师",FastAPI是"调度台"。

2.2 项目目录结构参考

我实际用的是这样一个结构,麻雀虽小五脏俱全,后续加功能也不至于推倒重来:

text2image-api/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI入口,路由注册 │ ├── config.py # 全局配置:模型名、路径、Ollama地址 │ ├── schemas.py # Pydantic请求/响应模型 │ ├── ollama_client.py # Ollama提示词增强模块 │ ├── sd_pipeline.py # Diffusers文生图封装 │ └── utils.py # 图片处理、种子处理等小工具 ├── models/ # 本地模型缓存目录,按需设置 ├── output/ # 生成图片落盘目录 ├── requirements.txt └── README.md

config.py里我额外做了两件事:一是所有路径用环境变量兜底,比如MODEL_CACHE_DIR、OLLAMA_BASE_URL,方便以后迁移到Docker;二是模型名和默认参数集中管理,免得散落在代码里改一处漏一处。

2.3 开工前必须想清楚的三个设计决策

这个项目有几个决策点,想清楚了后面能省大量返工时间。

一是模型加载时机。Stable Diffusion模型加载一次要几十秒甚至几分钟,绝不能每次请求都重新加载。正确做法是在FastAPI的启动生命周期里把模型加载到内存,进程退出时再卸载。新版FastAPI建议用lifespan上下文管理器代替早年的@app.on_event,写法更干净,也避免弃用警告。

二是请求同步还是异步。Diffusers的生成任务是典型的重CPU/GPU阻塞任务。如果你把接口函数定义成async def,一旦生成开始,整个事件循环就被占死了,其他所有请求都排队等它,这绝对是灾难。反过来用普通的def定义接口函数,FastAPI会让它在线程池里执行,多个请求可以并行跑。当然线程池也不适合承载几十个并发的重度任务,真正的高并发场景要上任务队列,这个我放到最后说。

三是Ollama请求的超时控制。大模型改写提示词一般几秒内完成,但偶尔也会因为模型加载、显存抖动拖到几十秒。我给Ollama客户端设了60秒超时,调用失败时直接降级返回原始提示词,而不是让整个接口报错。这个降级逻辑很实用——用户等一张图已经够久了,不能再因为翻译官掉链子而白等。

3. 环境准备:硬件、依赖与模型下载

3.1 硬件底线和CUDA环境

先说硬件,这是劝退最多人的地方。跑SDXL全精度推理,最低建议12GB显存起步,16GB能比较从容地同时跑Ollama和Diffusers——注意这两个模型是同时驻留显存的,显存分配上要留余量。如果你的卡只有6到8GB,也不是不能玩,两个办法:一是换用SD 1.5系列的模型,出图尺寸512x512,显存占用能压到4GB左右;二是给Diffusers管线开enable_model_cpu_offload(),让模型层在显存和内存之间自动换入换出,速度慢一些但跑得动。纯CPU推理我不是很推荐,一张512的图要几分钟甚至十几分钟,体验很折磨。

CUDA的坑主要是torch版本和显卡驱动不匹配。装torch之前先确认自己的CUDA版本,然后去PyTorch官网选对应的安装命令。一个典型错误是装成CPU版的torch还在那折腾显存报错,先用torch.cuda.is_available()验一下,真金白银的检查比直觉靠谱。

3.2 Ollama安装与模型拉取,以及下载慢的解法

Ollama的安装本身很简单,官网下个安装包一路下一步就行。真正卡人的是两件事:一是模型下载慢,二是模型默认存到C盘。

先解决C盘问题。Windows下设置环境变量OLLAMA_MODELS=D:\ollama\models,设置完重启Ollama服务,新拉取的模型就会进D盘。很多人是拉了两三个模型之后才发现C盘爆了,再迁移就麻烦得多,建议第一步就设好。

再解决下载慢。Ollama官方源的模型文件动辄几个GB,网络状况不好时ollama pull qwen2.5:7b能挂一晚上。实际操作中我试过三种靠谱的路子:第一,安装包和模型都从GitHub releases或国内第三方转存地址拿,速度比官网稳;第二,直接去HuggingFace把对应模型的GGUF文件下载下来,放到本地后,写一个简单的Modelfile,用ollama create mymodel -f Modelfile从本地文件导入,这招在离线环境里几乎是唯一解;第三,给Python侧的依赖下载配置镜像加速,比如给transformers和diffusers设置HF_ENDPOINT=https://hf-mirror.com环境变量,模型缓存路径统一指到本地目录。这些都属于常规的下载加速手段,不是黑魔法,但确实能把几小时的等待压缩到几分钟。

3.3 Python依赖清单

依赖文件长这样,版本以你安装时最新的稳定版为准,但diffusers和transformers建议锁大版本,免得API变动:

fastapi uvicorn[standard] diffusers transformers accelerate safetensors torch Pillow requests python-multipart

python-multipart是FastAPI处理表单数据用的,如果你的接口只用JSON,其实可以不要。我加上它是因为后期给接口加了个"上传参考图"的功能,不想再改依赖。Pillow用来做图片编码和尺寸转换,requests用来调Ollama的HTTP接口。这里没引入官方ollama的Python SDK,因为我只用一个API接口,直接requests足够,少一层依赖少一份坑。真要用SDK,装ollama包然后ollama.generate(model='qwen2.5:7b', prompt=...)也能达到同样效果,看你习惯。

4. 核心代码实现:三块拼图逐一拆解

4.1 Ollama客户端封装:让大模型好好当翻译官

先看代码。这里我调的是Ollama的/api/generate接口,忽略输出流,直接拿完整结果:

import requests OLLAMA_URL = "http://localhost:11434/api/generate" MODEL_NAME = "qwen2.5:7b" SYSTEM_PROMPT = """你是一名AI绘画提示词专家。用户会给你一个简单的创作想法,你需要把它改写为Stable Diffusion能理解的结构化提示词。 要求: 1. 输出必须全部是英文,包含主体、环境、光线、风格、画质词 2. 主体和风格用具体、可视觉化的词汇,避免抽象概念 3. 额外输出一行英文负面提示词,以NEGATIVE:开头 4. 不要输出任何解释,不要输出分析过程,只输出提示词本身 5. 整体控制在80个单词以内""" def enhance_prompt(user_input: str) -> str: payload = { "model": MODEL_NAME, "prompt": f"{SYSTEM_PROMPT}\n\n用户的想法:{user_input}", "stream": False, "options": { "temperature": 0.7, "num_predict": 250 } } resp = requests.post(OLLAMA_URL, json=payload, timeout=60) resp.raise_for_status() data = resp.json() raw = data["response"].strip() negative = "" if "NEGATIVE:" in raw: prompt_part, neg_part = raw.split("NEGATIVE:", 1) return prompt_part.strip(), neg_part.strip() return raw, ""

为什么temperature设0.7?这个值在改写任务里是经验和权衡的结果。设太低,比如0.2,模型输出会过于保守,每次都套同一套模板,画面雷同;设太高,比如1.2,改写结果会跑偏,甚至编出和用户原意无关的词汇。0.7左右既能保证一定的多样性,又不至于失控。另外我明确要求输出"NEGATIVE:"前缀,就是为了让模型把负面词和正面词分开,方便后续直接喂给Diffusers做negative prompt。你可能会问,直接固定写一份负面提示词不行吗?也行,但让LLM根据画面内容动态生成更精准——画人像时的负面词和画风景时的负面词,侧重点完全不同。

4.2 Diffusers封装:把SDXL包装成稳定的函数

Diffusers这边我封装的是一个纯函数,输入提示词和参数,输出PIL图片:

import torch from diffusers import StableDiffusionXLPipeline pipe = None def init_pipeline(model_path="stabilityai/stable-diffusion-xl-base-1.0", local_only=False): global pipe pipe = StableDiffusionXLPipeline.from_pretrained( model_path, torch_dtype=torch.float16, variant="fp16", use_safetensors=True, local_files_only=local_only, ) pipe.enable_model_cpu_offload() def generate_image(prompt, negative_prompt, width=768, height=768, steps=30, guidance_scale=7.5, seed=-1): if pipe is None: init_pipeline() if seed < 0: seed = torch.randint(0, 2 ** 32 - 1, (1,)).item() generator = torch.Generator(device="cuda").manual_seed(seed) result = pipe( prompt=prompt, negative_prompt=negative_prompt, width=width, height=height, num_inference_steps=steps, guidance_scale=guidance_scale, generator=generator, ) return result.images[0], seed

有几点解释一下。variant="fp16"表示使用半精度版本权重,显存占用能降低差不多一半;use_safetensors=True用更安全的safetensors格式,加载也更快。enable_model_cpu_offload()对中低端显卡非常友好,它会把部分模块放在内存,用到哪层再换入显存。代价是每张图可能慢个两三秒,但换来的是6GB显存也能碰SDXL,这笔交易划算。

种子处理是个容易被忽略的细节。这里约定seed=-1表示随机,实际生成时取一个随机种子,并且把用掉的种子返回给调用方。这个设计对调试太重要了——用户说"这张图不错但我想微调一下",你只要把上次的种子和参数原样传回来复现,而不是让他重新碰运气。接口返回的参数里带上seed,用户不满意又能基于同一张图微调,体验完全不一样。

另外一个常见的疑问是:为什么用SDXL base而不是SD 1.5或SDXL Turbo?Turbo出图快但画质细节少,适合实时预览;base画质上限高,配合30步采样质量稳定,适合做正式出图。如果你想要速度和质量兼顾,可以管线里同时准备两个模型,接口加个speed_mode参数切换,这是后续很容易扩展的优化项。

4.3 FastAPI接口层:参数校验和图片返回

接口定义用Pydantic模型把参数约束写清楚,这是最容易被新手忽略但价值极高的部分:

from fastapi import FastAPI, HTTPException from fastapi.responses import Response from pydantic import BaseModel, Field from contextlib import asynccontextmanager import io, time, logging logger = logging.getLogger("t2i") class GenerateRequest(BaseModel): prompt: str = Field(..., min_length=2, max_length=200, description="用户的创作想法") width: int = Field(768, ge=512, le=1024, multiple_of=64) height: int = Field(768, ge=512, le=1024, multiple_of=64) steps: int = Field(30, ge=10, le=80) guidance_scale: float = Field(7.5, ge=1.0, le=15.0) seed: int = Field(-1, ge=-1) use_enhance: bool = Field(True, description="是否启用LLM提示词增强") NEGATIVE_BASE = "lowres, bad anatomy, bad hands, watermark, text, cropped, worst quality, low quality, jpeg artifacts" @asynccontextmanager async def lifespan(app: FastAPI): init_pipeline(local_only=False) logger.info("SDXL pipeline loaded") yield logger.info("shutting down") app = FastAPI(title="Local Text-to-Image API", lifespan=lifespan) @app.post("/v1/generate") def generate(req: GenerateRequest): start = time.time() try: final_prompt = req.prompt negative_prompt = NEGATIVE_BASE if req.use_enhance: enhanced, dynamic_neg = enhance_prompt(req.prompt) if enhanced: final_prompt = enhanced if dynamic_neg: negative_prompt = f"{NEGATIVE_BASE}, {dynamic_neg}" img, used_seed = generate_image( prompt=final_prompt, negative_prompt=negative_prompt, width=req.width, height=req.height, steps=req.steps, guidance_scale=req.guidance_scale, seed=req.seed, ) buf = io.BytesIO() img.save(buf, format="PNG") logger.info("generate ok, prompt=%s, seed=%d, cost=%.2fs", req.prompt, used_seed, time.time() - start) return Response(content=buf.getvalue(), media_type="image/png") except Exception as e: logger.exception("generate failed") raise HTTPException(status_code=500, detail=str(e))

分辨率限制在512到1024之间且必须是64的倍数,这是SD模型的硬约束,不符合会出各种奇怪的图像问题。steps限制在10到80,一方面防止有人把步数拉满白耗显存,另一方面也给快速预览留了空间。multiple_of=64这个约束很多人不知道——Stable Diffusion下采样8倍,latent空间对尺寸有对齐要求,不是64的倍数容易出黑边或构图异常。

图片直接以PNG字节流返回,media_type="image/png",调用方拿到之后想存文件想转Base64都行。如果你需要同时返回种子和参数信息,可以把图片存到output/目录,然后在响应的Header里带上X-Seed: 12345这种自定义字段,或者干脆改成交互式任务模型,这取决于你的实际需求。

这里我用的是同步def定义接口函数。按照前面说的,FastAPI会把它扔到线程池里跑,主事件循环不会被Diffusers的长时间推理堵住。如果你误写成async def,后续所有请求都会排队卡死——这是我在一个早期版本里真实踩过的坑,排查了半天才发现是事件循环被图形生成占住了。

4.4 并发与性能的真实边界

简单线程池方案能撑多少并发?我用12GB显存的卡实测,两个请求同时跑就已经开始明显变慢,三个请求很可能直接OOM。原因很简单:Diffusers每次生成都要把模型权重和中间激活值放进显存,两个并发就接近翻倍占用。所以这个项目的现实定位是"轻量内网服务",接口响应时间本身就要好几秒,并发意义有限。

真要做成多人使用的正式服务,我建议往任务队列方向演进:FastAPI收到请求后把任务丢进Redis/RQ或Celery队列,立刻返回一个task_id,后台Worker负责实际生成,前端轮询任务状态拿结果。步骤拆开之后,接口层只管接收和查询,生成任务全部排队执行,显存占用天然受控。这是从"能跑"到"好用"的关键一步,等基础版跑通后再上也不迟。

5. 让AI绘画"听话"的提示词策略

5.1 给LLM写好"岗位说明书"

很多人用了Ollama做提示词增强但效果不佳,问题几乎都出在system prompt上。大模型是极强的"角色扮演者",你给它清晰的角色定义和输出格式约束,它的表现会完全不一样。我给Ollama的system prompt里反复强调了几件事:输出全英文、包含结构化元素、禁止输出分析过程、给出负面词。这四条规定分别解决四个痛点——英文对齐训练分布、结构提升画面完整度、防止思维链污染、负面词提升构图干净度。

这里有个实用技巧:允许在改写结果里保留少量中文关键词,比如"江南古镇"这种带有强文化属性的词汇,直接音译或半中半英反而让Stable Diffusion难以理解。实测下来,"江南古镇"保留中文比翻译成"ancient town in Jiangnan"效果更好。当然这个取决于你用的图像模型底模,如果是偏写实的大模型,这种文化词保留原样更稳妥。可以让LLM在拿不准时保留中文,反正后续Diffusers的CLIP Text Encoder对中文也有一定理解能力。

5.2 参数组合对照表:别复制别人的默认值

下面这张表是我跑了几百张图之后沉淀下来的参数建议,不同出图目的用不同组合:

参数快速预览标准出图精细出图
steps153045
guidance_scale6.07.58.5
分辨率512x512768x7681024x1024
适合场景灵感试错常规生成成品交付

steps和guidance_scale是相互关联的。steps太少(低于10)时模型还没收敛,画面糊;太高超过80纯属浪费算力,后期收益几乎为零。guidance_scale控制的是"提示词对画面的影响强度"——太低,画面自由发挥,可能偏离提示词;太高,画面过度迎合提示词,色彩会发灰发硬。7.5是SD系列比较经典的平衡点,但具体模型和底模不同,建议在6到9之间自己试几轮,找到你手上这个底模的甜点区。

5.3 实测对比:同一个想法,两种效果

我给团队演示过一次最直观的对比。同一句输入:"一个女孩在雨夜的便利店门口,霓虹灯,赛博朋克风格"。未加增强链路时,把这句话原样喂给SDXL,出来的是构图混乱、风格不明的图,人物和环境搅在一起。走Ollama增强链路后,改写出来的提示词长这样:a girl standing outside a convenience store in the rainy night, neon lights reflecting on wet pavement, cyberpunk style, cinematic lighting, detailed face, masterpiece, best quality,负面词补充了motion blur, messy composition。最终出图,霓虹氛围、雨夜质感、人物主体都清晰可见。这就是"听话"的具体含义——模型不是理解你的中文,而是理解了被翻译成它母语后的精确指令。

这套链路还有一个隐性收益:用户端的体验统一了。不管用户用词多口语化、多零碎,LLM都会自动补全要素、纠偏方向,输出的图片质量方差变小。换句话说,你是在用一个聪明的模型去"驯服"另一个不那么聪明的模型,最终用户只感受到一个稳定的服务。

6. 常见问题与排查实录

6.1 Ollama下载慢、装完还老失效怎么办

这是被问得最多的问题。ollama pull qwen2.5:7b半天不动,第一件事别反复重试,先看是不是存储路径问题。Ollama默认把模型放在用户目录的.ollama/models下,如果你C盘快满了,下载会先卡住。按前面说的设置OLLAMA_MODELS环境变量后重启服务,再重新pull。

如果网络确实慢,最稳的办法是绕过pull:去HuggingFace找对应模型的GGUF文件,用工具下载到本地,再写一个Modelfile,内容就是一行FROM /path/to/model.gguf,然后ollama create mymodel -f Modelfile。这个方案在离线环境里几乎是唯一解,也方便你统一管理模型文件。另外,Ollama对GPU的使用是自动的,想确认模型真的用了显卡,执行ollama ps看模型对应的显存占用,如果显示CPU跑,检查驱动和CUDA版本。

6.2 显存爆了:CUDA out of memory

Diffusers最常见的报错就是显存不足。三步排查:第一步,确认torch.cuda.is_available()为True,很多人用的是CPU版torch;第二步,把StableDiffusionXLPipeline的torch_dtype设为torch.float16,这一步能省接近一半显存;第三步,开启enable_model_cpu_offload(),代价是速度慢一点。如果还不够,降分辨率、换SD 1.5模型、减少steps,这三个是降显存的铁三角。

Ollama和Diffusers同时跑显存打架的问题也需要留意。两个模型的常驻显存是叠加的,建议给Ollama设置OLLAMA_MAX_LOADED_MODELS=1,并且用OLLAMA_NUM_PARALLEL=1限制同时处理的请求数,给Diffusers留足空间。

6.3 Diffusers模型下载和缓存的老大难

第一次运行from_pretrained会从HuggingFace拉权重,国内网络慢是常态,而且模型动不动几个GB。解决办法是设置环境变量HF_ENDPOINT=https://hf-mirror.com,再指定HF_HOME把缓存放到一个有足够空间的目录。模型下载一次后会缓存在本地,以后走local_files_only=True就能离线加载。如果你已经有一套下载好的模型目录,也可以通过from_pretrained("/本地路径")直接加载,不一定要走HuggingFace的缓存逻辑。

版本兼容问题也常碰到:diffusers版本太旧,SDXL的variant="fp16"参数不识别;transformers版本太新,和某个底模的tokenizer不兼容。我的建议是不要盲目追新,锁定一个大版本内的最新小版本,跑通之后不要随意升级。我把requirements里的关键包用>=和<锁了范围,避免某天队友pip install把环境搞坏。

6.4 接口层面的三个隐蔽坑

第一个坑是请求超时。默认的requests超时很短,图片生成动辄几十秒,客户端早断开了。要在调用侧设置合理的超时参数,至少给足两分钟,或者改用异步任务轮询。

第二个坑是FastAPI里误用async def。前面反复强调,重计算任务用同步def让FastAPI走线程池,这个顺序千万别搞反。判断标准很简单:函数里有没有真实的异步IO?有才用async def,纯计算一律用普通def。

第三个坑是返回图片时的响应头。如果你直接return bytes,FastAPI会当成JSON处理导致报错,必须用Response(content=buf.getvalue(), media_type="image/png")。要额外传种子信息,记得加自定义Header,但注意Header值必须是字符串。

6.5 一些零散但救过命的小技巧

最后分享几个散装经验,不按逻辑排序,都是踩过坑之后才记住的:

  • 启动时先做一次模型自检,比如初始化管线后跑一张8x8的小图,有问题立刻报错退出,别等用户第一个请求才炸。
  • 记录生成日志时把输入提示词、最终提示词、种子、耗时都打出来,排查用户问题全靠它。
  • 接口加一个/v1/health健康检查接口,返回模型加载状态和显存余量,部署到Docker后探活就靠它。
  • 用Docker部署的话,给Ollama和FastAPI各起一个容器,通过docker-compose管理,GPU透传记得加gpus=all配置。
  • 想接一个Web前端时,FastAPI直接托管静态文件,把HTML丢进去,出一个简易版绘画页面,整个服务就完整了。

这套链路跑通之后我又陆续往里加了LoRA切换、ControlNet边缘控制,甚至把Ollama换成了更强的大模型做更复杂的提示词规划。底子打好了,后面每一步都是锦上添花。关于"听话"这件事,我最后的体会是:模型不会真正理解你的意图,它只理解你给的指令。你的工作就是搭好一条把意图翻译成指令的流水线,而Ollama加Diffusers加FastAPI这三件套,恰好能把这件事做得足够稳、足够顺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询