2026秋 软件工程第一次个人作业

2026 秋软件工程第一次个人作业

这个作业属于哪个课程 202601 软件工程
这个作业要求在哪里 第一次个人作业
这个作业的目标 完成课程平台准备,调用 Hugging Face API,并结合前端页面实现可交互的图像生成
学号 102400412

一、准备工作

  1. 我的 GitHub 主页为 illnessemc,目前已经完善头像、昵称和个人资料。
  2. 我的博客园主页为 Gwbin,目前已经开通个人博客并完成主题美化。
  3. 我已经关注吴越钟老师张明圣同学王奇蕊同学,并实名加入 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. 实验体验与心得

  1. 调用过程中遇到的问题。 最开始调用接口时无法返回正确图片,排查后发现是前后端调用端口配置错误。修正端口后又遇到了额度不足的问题,我当时没有提前注意 Hugging Face 的调用额度,因此注册并切换了好几个账号。根据这些问题,我在后端增加了错误分类,根据调用端返回的状态分别提示 Token、权限、额度、模型和请求频率等错误,使排查方向更加明确。
  2. 提示词和扩散步数会直接影响生成效果。 第一次只有基本场景,控制力较弱;第二次补充人物、雨具和环境光线后,画面内容更准确;第三次加入皮肤、雨滴、镜头语言和负面限制后,真实感进一步提高。测试中我还发现,扩散步数过少时画面容易模糊或不完整,适当增加步数能改善细节,但也会增加生成时间和额度消耗。
  3. 前后端联调让我对 API 应用有了更完整的认识。 除了模型调用本身,还需要处理参数校验、加载状态、图片响应、错误信息和 Token 保护。只有这些环节都正常工作,模型能力才能真正变成可用的网页功能。

三、GitHub 个人主页

作业提供了两种 GitHub 个人主页建设方案:

  1. 创建一个与 GitHub ID 同名的仓库,在仓库根目录的 README.md 中编写个人介绍,GitHub 会将其展示在个人主页上。
  2. 使用 GitHub Pages 搭建独立的个人展示网站,通过网页介绍个人信息、专业技能、实践经历和未来规划。

我选择了第一种方案,即创建 GitHub Profile README。相比独立搭建 GitHub Pages,Profile README 可以在进入 GitHub 主页后直接看到个人介绍、技能和项目,展示更加直观,编辑与更新的效率也更高。此外,我目前的前端能力还不够扎实,暂时难以制作内容丰富、完成度较高的 GitHub Pages,因此现阶段选择 Profile README 更符合我的实际情况。后续提升前端能力后,我也会尝试搭建更完整的个人网站。

我的 GitHub 主页:https://github.com/illnessemc

GitHub 个人主页

四、随笔部分

个人随笔记录了我的技能树、自我评估、代码量目标、课程期待,以及对 AI 生成的软件工程学习指南的分析。

此处是随笔

五、总结

通过本次作业,我完成了 Hugging Face API 的调用,并结合 Flask、HTML、CSS 和 JavaScript 实现了可以交互生成图片的网页。在逐步调整提示词和扩散步数的过程中,我对扩散模型的生成特点有了更直观的认识,也了解到调用第三方模型时需要关注端口配置、错误处理等实际问题。

准备作业的过程中,我还完善了 GitHub 和博客园的个人主页,对个人资料和页面样式进行了编辑。同时,通过整理代码、图片、链接和文字说明,我更加熟悉了 Markdown 的表格、代码块、链接和图片等常用语法。

附截图

此作业编辑均采用markdown编辑,并在博文中附加后台博文编辑页面的截图。
markdown编辑

posted @ 2026-09-09 23:01  Gwbinn  阅读(8)  评论(0)    收藏  举报