软工第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/homework/16716
这个作业的目标 熟悉 GitHub/博客园协作环境;通过调用 HuggingFace 文生图 API 并自建前端完成一次真实的 API 工程实践;建立个人技术主页;梳理自身技能树与学习规划
学号 102401510

任务 1:HuggingFace API 调用 Flux 模型生成真实感图像 —— 博客素材

使用说明:本文按博客顺序组织,含代码、真实日志、截图占位与心得文字。
凡标注【截图:xxx】处,请插入你本地截图后发布。
完整工程代码位于 flux-generator/ 目录(app.py 后端 + templates/index.html 前端)。


一、任务目标

在 HuggingFace 注册账号并获取 API,调用 XLabs-AI/flux-RealismLora(FLUX.1-dev 的真实感 LoRA)生成"最贴近真实世界"的图像;在模型调用代码基础上结合前端接口,实现交互式生成;并以代码、截图与文字记录操作步骤,总结 API 调用体验。

二、操作步骤记录

步骤 1:注册 HuggingFace 账号并获取 Token

  1. 打开 https://huggingface.co/join 用邮箱注册(需邮箱验证)。
  2. 登录后进入 https://huggingface.co/settings/tokens,点击 Create new token
  3. Type 选择 Read(如需调用付费/受限资源可勾选 "Inference Providers" 权限),Name 随意,点击 Create。
  4. 复制生成的 hf_xxx... 字符串 —— Token 相当于密码,绝不能提交到 GitHub 或发给他人

说明:本次实践中,Read 权限 Token 即可完成 Inference Providers 的图像生成调用。

步骤 2:准备 Python 运行环境

本机没有系统级 Python,使用 uv 管理的 Python 3.14.7 创建项目虚拟环境:

cd flux-generator
"C:\Users\...\python.exe" -m venv venv
venv\Scripts\python -m pip install -r requirements.txt

requirements.txt 内容:

flask>=3.0
huggingface_hub>=1.30
pillow>=10.0

步骤 3:项目结构

flux-generator/
├── app.py               # Flask 后端:/api/generate 调用模型 + 日志(控制台与页面同步)
├── templates/
│   └── index.html       # 前端交互页面:预设提示词 / 输入框 / 生成按钮 / 结果与历史 / 日志面板
├── requirements.txt     # 依赖
├── run.bat              # 一键启动(含 HF_TOKEN 与代理配置)
├── outputs/             # 成功生成的图片自动保存于此
└── README.md

步骤 4:运行

双击 run.bat(首次自动装依赖),或手动:

set HF_TOKEN=hf_你的Token
set HTTPS_PROXY=http://127.0.0.1:7897   :: 本机需经代理访问外网(***)
venv\Scripts\python app.py

浏览器打开 http://127.0.0.1:5000 ,页面标题栏显示"HF Token:已配置"即就绪。

三、核心代码说明

3.1 后端:调用模型的核心函数(app.py)

2026 年 HuggingFace 已将推理统一迁移到 Inference Providers 体系,旧的 Serverless 推理域名
(api-inference.huggingface.co)已退役。因此代码使用官方 Python SDK
huggingface_hub.InferenceClient.text_to_image,由 SDK 自动路由到可用的提供商:

from huggingface_hub import InferenceClient

def call_sdk(prompt, model, logs):
    """通过官方 SDK 调用模型,自动路由到 Inference Providers 可用提供商"""
    client = InferenceClient(api_key=API_TOKEN, timeout=300)
    for attempt in range(1, MAX_RETRY + 1):          # 冷启动时自动重试
        log_line("第 %d/%d 次调用:text_to_image(model=%s)" % (attempt, MAX_RETRY, model), logs)
        t0 = time.time()
        try:
            img = client.text_to_image(prompt, model=model)
            buf = io.BytesIO(); img.save(buf, format="PNG"); data = buf.getvalue()
            log_line("调用成功:HTTP 200,耗时 %.1f 秒,返回图像 %dx%d(%d 字节)"
                     % (time.time() - t0, img.width, img.height, len(data)), logs)
            return True, data, None
        except Exception as exc:
            ...  # 503/加载中 -> 等待后重试;其余错误 -> 记录并返回

后端 /api/generate 路由:接收前端 POST 的 {prompt, model},调用上述函数;
主模型 XLabs-AI/flux-RealismLora 失败时自动切换备选模型 FLUX.1-schnell
保证交互流程不中断;成功后图片以 Base64 返回前端,同时自动保存到 outputs/ 目录。
每次调用都写入日志(控制台 + 随响应返回页面)。

3.2 前端:交互式生成(index.html 关键片段)

// 点击“生成图像”按钮:把提示词 POST 到后端,等待返回并展示
$("genBtn").onclick = async function () {
  const prompt = $("prompt").value.trim();
  const model  = $("modelSelect").value;
  // ...显示“生成中”遮罩...
  const resp = await fetch("/api/generate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ prompt, model }),
  });
  const data = await resp.json();
  if (data.ok) {
    showImage(data.image);           // 大图展示
    addHistory(data.image);          // 加入历史缩略图
  }
  data.logs.forEach(l => addLog(l)); // 页面日志面板 = 后端控制台日志
};

屏幕截图 2026-09-09 202212

页面还内置 6 组"真实世界"风格预设(人像/街头/田园/宠物/美食/人物与环境),一键填入提示词,
支持自由修改、生成历史回看、一键下载与复制图片、日志面板一键复制。

四、API 调用成功的记录(真实日志)

4.1 后端控制台日志(一次完整的成功调用)

[19:08:44] 收到生成请求:模型=XLabs-AI/flux-RealismLora 提示词='Close-up portrait of a young
           Chinese college student with natural skin texture, slight tired eyes after study,
           warm golden-hour sunlight through a window, 85mm f/1.8 lens, shallow depth of field,
           soft bokeh background, candid natural expression, photorealistic, fine film grain,
           no heavy makeup'
[19:08:45] 第 1/4 次调用:text_to_image(model=XLabs-AI/flux-RealismLora) —— InferenceClient 自动路由到可用提供商
[19:09:02] 调用成功:HTTP 200,耗时 16.8 秒,返回图像 1024x768(PNG,729050 字节)
[19:09:02] 图片已保存:C:\Users\...\flux-generator\outputs\flux_20260909_190902.png
  • 首次调用即成功(模型在云端已完成加载),HTTP 200,耗时 16.8 秒
  • 返回 1024×768 PNG 图像(729 KB),自动保存到本地 outputs/ 目录

4.2 页面日志面板

页面底部日志面板与后端控制台输出一致,便于复查与截图。

4.3 生成的图像

flux_20260909_192439

五、提示词设计思路与修改过程

5.1 设计框架:真实感提示词"四要素"

要素 作用 示例
① 主体 画面内容的特征、动作、状态 a young Chinese college student, natural skin texture, tired eyes after study
② 环境与光线 时间、光源、氛围 warm golden-hour sunlight through a window
③ 镜头语言 焦段、光圈、景深 85mm f/1.8 lens, shallow depth of field, bokeh
④ 画质关键词 真实感收尾 photorealistic, film grain, natural color

原则:提示词越具体越接近真实照片;避免抽象词(beautiful)、风格化词(anime/cartoon);
FLUX 类模型不需要负面提示词,把"不要什么"直接写成正面描述(no heavy makeup)。

5.2 修改过程(真实迭代记录)

第 1 版(连通性探针)——用最简提示词验证 API 链路:

屏幕截图 2026-09-09 192219

第 2 版(四要素完整版)——针对"人像最贴近真实世界"目标补全要素:

屏幕截图 2026-09-09 192455屏幕截图 2026-09-09 192559

六、踩坑记录与 API 调用体验(心得素材)

6.1 踩坑记录(均可作为博客"排错过程"素材)

坑 1:作业指定的旧 API 域名已随 HF 迁移而退役。
按作业要求最初直接请求 https://api-inference.huggingface.co/models/...
连续遇到 SSL 连接中断。经多源 DNS(Google/Cloudflare DoH)交叉验证发现:
该域名全球 DNS 已无 A 记录;而国内 ISP DNS 对已消失的域名返回了投毒假 IP
(TCP 可连通、TLS 握手即被掐断的黑洞),导致报错极具迷惑性。

坑 2:网络直连被墙,必须走代理。
直连 huggingface.co 全部超时;系统代理(***,127.0.0.1:7897)可通。
注意 Python 默认不读系统代理,需要显式设置环境变量:

set HTTPS_PROXY=http://127.0.0.1:7897

坑 3:代理"规则模式"下该域名走直连规则被重置。
对照实验:同一代理下 GitHub 通、Google/YouTube/HF 全挂,且 CONNECT 隧道建立成功后
TLS 握手被杀 —— 这是 GFW SNI 阻断特征。切换到全局模式并选择存活节点后解决。
(排查思路:用 curl -v 观察 TLS 死在哪个阶段,用 DoH 对比 DNS 是否被投毒。)

坑 4:旧接口不可用后,正确姿势是读官方文档 + 用官方 SDK。
HF 已将推理迁移到 "Inference Providers"(router.huggingface.co 路由 + 各提供商),
文档示例即为官方 SDK:

from huggingface_hub import InferenceClient
client = InferenceClient(api_key=os.environ["HF_TOKEN"])   # 不指定 provider,自动路由
image  = client.text_to_image("...", model="XLabs-AI/flux-RealismLora")

SDK 内部自动处理端点选择与错误语义,比手写 HTTP 省心得多 —— 作业指定的
flux-RealismLora 与备选 FLUX.1-schnell 均一次打通。

6.2 体验与心得总结

  1. API 生态是流动的:作业示例中的旧 Serverless 推理域名在 2025-2026 年间被 HF
    迁移退役(hf.co 短域名仍 301 指回旧域名,属于遗留配置)。遇到"报错诡异"时,
    先查官方文档确认当前推荐调用方式,而不是死磕旧接口 —— 本次改走官方 SDK 后一次成功。
  2. 网络问题的排查要分层:本次经历"应用层报错 → TLS 握手失败 → 直连超时 →
    DNS 投毒 → 代理规则"五层排查。有效手段包括:curl -v 观察 TLS 阶段、
    用 DoH(1.1.1.1 / dns.google)与本地 DNS 结果做对照、用不同站点做代理连通性对照实验。
  3. 日志先行:后端把每次调用的时间戳、HTTP 状态、耗时、字节数都记录下来,
    既方便排错,也是作业要求的"调用成功记录"素材 —— 好的日志设计本身就是工程能力。
  4. 成本与配额意识:免费账号的图像生成额度有限,调试时应先用最小请求验证链路,
    确认无误后再做正式生成;我在本次调试中因反复验证消耗了少量额度,教训是
    "先确认配额与最小成本路径,再批量调用"。
  5. 工程化体验:交互式前端(预设/历史/日志面板/一键下载)让"调 API"从一次性脚本
    变成了可演示的小产品,也让我体会到 API 调用与产品集成之间的差距。

Github个人主页搭建

屏幕截图 2026-09-09 201713
屏幕截图 2026-09-09 205353

作业要求

使用Markdown编写作业,并在博文中附加后台博文编辑页面的截图。(注:要把博客园的编辑器改成:Markdown编辑器)
屏幕截图 2026-09-09 195045

posted @ 2026-09-09 20:56  林富强  阅读(9)  评论(0)    收藏  举报