2026秋 软件工程第一次个人作业
2026 秋软件工程第一次个人作业
| 这个作业属于哪个课程 | 202601 软件工程 |
|---|---|
| 这个作业要求在哪里 | 第一次个人作业 |
| 这个作业的目标 | 完成课程平台准备,调用 Hugging Face API,并结合前端页面实现可交互的图像生成 |
| 学号 | 102400412 |
一、准备工作
- 我的 GitHub 主页为 illnessemc,目前已经完善头像、昵称和个人资料。
- 我的博客园主页为 Gwbin,目前已经开通个人博客并完成主题美化。
- 我已经关注吴越钟老师、张明圣同学和王奇蕊同学,并实名加入 202601 福州大学软件工程班级博客。
二、Hugging Face API 调用与前端交互
1. 实验目标与技术选型
本次实验的目标是调用 Hugging Face 上的 XLabs-AI/flux-RealismLora 模型,生成一张尽可能贴近真实世界的图片,并通过网页完成提示词输入、参数设置、生成状态反馈和图片展示。
项目采用以下技术:
- 后端:Python、Flask、
huggingface_hub - 前端:HTML、CSS、JavaScript
- 模型:
XLabs-AI/flux-RealismLora - 推理服务商:
fal-ai - 配置管理:
python-dotenv
整体调用过程如下:
用户填写提示词和参数
↓
浏览器 JavaScript 向 /api/generate 发送 POST 请求
↓
Flask 校验参数,并从 .env 中读取 HF_TOKEN
↓
后端通过 InferenceClient 调用 Hugging Face 模型
↓
模型返回 PNG 图片,Flask 将图片二进制返回浏览器
↓
前端展示图片、Seed、耗时、尺寸等信息
把 Token 保存在后端的 .env 中,而不是写入 HTML 或 JavaScript,可以避免浏览器端直接暴露密钥;同时使用 .gitignore 排除 .env,防止把 Token 提交到 GitHub。
2. 获取并配置 API Token
我先在 Hugging Face 官网注册并登录个人账号,然后在个人设置中创建 Access Token,供后端调用模型时使用。
3. 项目结构与运行步骤
项目主要文件如下:
flux_web/
├── app.py # Flask 后端与模型调用
├── templates/index.html # 网页结构
├── static/style.css # 页面样式
├── static/app.js # 前端交互与请求
├── requirements.txt # Python 依赖
├── .env # 本地 Token 配置,不上传 GitHub
└── logs/api.log # 不含 Token 的 API 调用记录
在 PowerShell 中进入项目目录并执行:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python app.py
服务启动后访问 http://127.0.0.1:5000,填写提示词,选择尺寸和生成步数,点击“生成图像”。
4. 后端 API 核心实现
后端先从环境变量读取模型、供应商和 Token。只有 Token 配置成功时才建立推理客户端:
MODEL_ID = os.getenv("HF_MODEL_ID", "XLabs-AI/flux-RealismLora")
PROVIDER = os.getenv("HF_PROVIDER", "fal-ai")
def create_client() -> InferenceClient:
token = os.getenv("HF_TOKEN")
if not token:
raise RuntimeError(
"未检测到 HF_TOKEN。请在 .env 中配置 Hugging Face API Token。"
)
return InferenceClient(
provider=PROVIDER,
api_key=token,
timeout=90,
)
生成接口接收前端输入,检查提示词、尺寸、步数和 Seed,再调用模型并返回 PNG:
@app.post("/api/generate")
def generate():
data = request.get_json(silent=True) or {}
prompt = str(data.get("prompt", "")).strip()
negative_prompt = str(data.get("negativePrompt", "")).strip()
size_name = str(data.get("size", "square"))
if not prompt:
return jsonify(error="请输入图片描述后再生成。"), 400
if size_name not in IMAGE_SIZES:
return jsonify(error="不支持的图片尺寸。"), 400
width, height = IMAGE_SIZES[size_name]
image = create_client().text_to_image(
prompt,
model=MODEL_ID,
negative_prompt=negative_prompt or None,
width=width,
height=height,
num_inference_steps=steps,
seed=seed,
)
buffer = io.BytesIO()
image.save(buffer, format="PNG")
return Response(buffer.getvalue(), mimetype="image/png")
实际项目中还加入了输入长度限制、步数范围校验、Seed 范围校验、上游错误提示和不记录 Token 的日志,避免无效请求或敏感信息泄露。
5. 前端交互核心实现
前端拦截表单提交,将提示词和参数组织为 JSON 后发送给 Flask:
form.addEventListener("submit", async (event) => {
event.preventDefault();
const response = await fetch("/api/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
prompt: promptInput.value.trim(),
size: sizeInput.value,
steps: stepsInput.value,
seed: seedInput.value.trim(),
negativePrompt: negativePromptInput.value.trim(),
}),
});
if (!response.ok) {
const data = await response.json().catch(() => ({}));
throw new Error(data.error || "请求失败,请稍后重试。");
}
const imageUrl = URL.createObjectURL(await response.blob());
resultImage.src = imageUrl;
imageResult.hidden = false;
});
页面还提供了方形、横向和竖向尺寸,10、20、30 步生成选项,随机种子以及负面提示词。请求期间按钮会切换为“生成中”,成功后显示模型、服务商、尺寸、Seed、步数和耗时;失败时显示易理解的错误信息。
6. 提示词设计与三轮修改过程
为了便于比较提示词修改带来的效果,三次生成均使用竖向尺寸 (768 × 1024)、20 步和相同的 Seed (2411486867)。
第一次:确定基本场景
第一次只描述人物、地点、天气和时间,让模型生成一名年轻女性在雨夜公交站等车的画面。生成结果已经具备基本场景,但人物动作、服装、雨具和环境细节主要由模型自由发挥。


第二次:补充人物与环境细节
第二次增加透明雨伞、深色外套、湿润路面、路灯和车灯倒影,并要求自然姿态和写实摄影效果。生成结果中的主体与环境关系更加明确,画面的构图和氛围也更完整。


第三次:增强真实感并加入负面限制
第三次进一步补充湿发、面部受光、雨滴、水洼、皮肤纹理、纪实摄影和浅景深等细节,同时使用负面提示词减少卡通感、模糊、肢体错误和塑料皮肤等问题。最终画面的材质、光影和人物状态更加自然,是三次结果中最接近真实照片的一张。


7. 实验体验与心得
- 调用过程中遇到的问题。 最开始调用接口时无法返回正确图片,排查后发现是前后端调用端口配置错误。修正端口后又遇到了额度不足的问题,我当时没有提前注意 Hugging Face 的调用额度,因此注册并切换了好几个账号。根据这些问题,我在后端增加了错误分类,根据调用端返回的状态分别提示 Token、权限、额度、模型和请求频率等错误,使排查方向更加明确。
- 提示词和扩散步数会直接影响生成效果。 第一次只有基本场景,控制力较弱;第二次补充人物、雨具和环境光线后,画面内容更准确;第三次加入皮肤、雨滴、镜头语言和负面限制后,真实感进一步提高。测试中我还发现,扩散步数过少时画面容易模糊或不完整,适当增加步数能改善细节,但也会增加生成时间和额度消耗。
- 前后端联调让我对 API 应用有了更完整的认识。 除了模型调用本身,还需要处理参数校验、加载状态、图片响应、错误信息和 Token 保护。只有这些环节都正常工作,模型能力才能真正变成可用的网页功能。
三、GitHub 个人主页
作业提供了两种 GitHub 个人主页建设方案:
- 创建一个与 GitHub ID 同名的仓库,在仓库根目录的
README.md中编写个人介绍,GitHub 会将其展示在个人主页上。 - 使用 GitHub Pages 搭建独立的个人展示网站,通过网页介绍个人信息、专业技能、实践经历和未来规划。
我选择了第一种方案,即创建 GitHub Profile README。相比独立搭建 GitHub Pages,Profile README 可以在进入 GitHub 主页后直接看到个人介绍、技能和项目,展示更加直观,编辑与更新的效率也更高。此外,我目前的前端能力还不够扎实,暂时难以制作内容丰富、完成度较高的 GitHub Pages,因此现阶段选择 Profile README 更符合我的实际情况。后续提升前端能力后,我也会尝试搭建更完整的个人网站。
我的 GitHub 主页:https://github.com/illnessemc

四、随笔部分
个人随笔记录了我的技能树、自我评估、代码量目标、课程期待,以及对 AI 生成的软件工程学习指南的分析。
此处是随笔
五、总结
通过本次作业,我完成了 Hugging Face API 的调用,并结合 Flask、HTML、CSS 和 JavaScript 实现了可以交互生成图片的网页。在逐步调整提示词和扩散步数的过程中,我对扩散模型的生成特点有了更直观的认识,也了解到调用第三方模型时需要关注端口配置、错误处理等实际问题。
准备作业的过程中,我还完善了 GitHub 和博客园的个人主页,对个人资料和页面样式进行了编辑。同时,通过整理代码、图片、链接和文字说明,我更加熟悉了 Markdown 的表格、代码块、链接和图片等常用语法。
附截图
此作业编辑均采用markdown编辑,并在博文中附加后台博文编辑页面的截图。


浙公网安备 33010602011771号