AIGC标识 软件工程第一次作业-102402126黄炜杰

这个作业属于哪个课程 2026级软件工程与软件工程实践(H202601)
这个作业要求在哪里 2026秋软件工程个人作业(第一次)
这个作业的目标 熟悉课程以博客园、GitHub 为主的实践体系,通过调用 HuggingFace API 实现 AI 生图交互页面初步体验大模型的实际应用能力,并完成个人技能评估与学习规划
学号 102402126

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


一、HuggingFace API 调用:AI 生图交互页面

1.1 实现思路

整体采用"前端页面 → Flask 后端 → Hugging Face Inference Providers"三层结构:

  1. 模型选择XLabs-AI/flux-RealismLora 是挂在 FLUX.1-dev 底模上的照片真实感 LoRA,调用它 = FLUX.1-dev + 真实感权重出图,目标是让结果接近真实摄影而非"AI 插画味"。
  2. API 调用:使用 huggingface_hub.InferenceClient(provider="auto", api_key=HF_TOKEN)text_to_image 接口。注意旧版 api-inference.huggingface.co 接口已停用,2024 年前的老教程代码会报 410/404,统一改走 Inference Providers。
  3. 令牌安全:HF 令牌只放在后端环境变量 HF_TOKEN 中,浏览器端不接触令牌——这是 Web 应用调用鉴权 API 的标准做法,避免令牌泄露。
  4. 交互流程:前端页面可填提示词、负向提示词、种子,点击"生成图像"后 fetch 调用后端 /api/generate,后端转发到 Hugging Face,把返回的 PNG 以 base64 显示在页面上,同时落盘到 outputs/ 并向 calls_log.jsonl 追加一条调用记录(时间、模型、提供方、耗时、提示词、输出路径)。
  5. 运行方式python -m pip install -r requirements.txt 装依赖 → $env:HF_TOKEN = "hf_你的令牌"python app.py → 浏览器打开 http://127.0.0.1:5000。另有 generate_image.py 脚本版可先单测跑通 API。

1.2 代码展示

项目结构:

hf-flux-realism-demo/
├── generate_image.py   # 方式 A:脚本直接调用 API
├── app.py              # 方式 B:Flask 后端(前端 + 后端一体)
├── static/index.html   # 前端交互页面
├── requirements.txt    # 依赖:huggingface_hub / flask / pillow
├── outputs/            # 生成的图片
└── calls_log.jsonl     # 每次调用的记录(成功日志素材)

① API 核心调用(generate_image.py)

# -*- coding: utf-8 -*-
"""通过 Hugging Face Inference Providers 调用 XLabs-AI/flux-RealismLora 生成照片级真实图像。"""
import os, sys, time, json, datetime
from pathlib import Path
from huggingface_hub import InferenceClient

MODEL_ID = "XLabs-AI/flux-RealismLora"            # FLUX.1-dev 的照片真实感 LoRA
PROVIDER = os.environ.get("HF_PROVIDER", "auto")  # auto 自动选择模型页可用的提供方

DEFAULT_PROMPT = (
    "natural candid photo of a young woman laughing in a rainy city street at night, "
    "neon reflections on wet ground, shot on 35mm film, realistic skin texture, "
    "cinematic lighting, shallow depth of field"
)
NEGATIVE_PROMPT = "cartoon, anime, illustration, painting, drawing, deformed, ugly, watermark"

def main():
    token = os.environ.get("HF_TOKEN")
    if not token:
        sys.exit("请先设置环境变量 HF_TOKEN(在 huggingface.co/settings/tokens 创建令牌)")
    prompt = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_PROMPT

    client = InferenceClient(provider=PROVIDER, api_key=token)
    t0 = time.time()
    image = client.text_to_image(
        prompt,
        model=MODEL_ID,
        negative_prompt=NEGATIVE_PROMPT,
        width=1024,
        height=1024,
        num_inference_steps=28,
        guidance_scale=3.5,
    )
    elapsed = time.time() - t0

    out_dir = Path(__file__).parent / "outputs"
    out_dir.mkdir(exist_ok=True)
    stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    out_file = out_dir / f"flux_realism_{stamp}.png"
    image.save(out_file)

    # 向 calls_log.jsonl 追加一条调用记录,作为"API 调用成功记录"的素材
    record = {"time": stamp, "model": MODEL_ID, "provider": PROVIDER,
              "status": "success", "elapsed_seconds": round(elapsed, 1),
              "prompt": prompt, "output": str(out_file)}
    with open(Path(__file__).parent / "calls_log.jsonl", "a", encoding="utf-8") as f:
        f.write(json.dumps(record, ensure_ascii=False) + "\n")
    print(f"[成功] 耗时 {elapsed:.1f} 秒,图片已保存:{out_file}")

if __name__ == "__main__":
    main()

② Flask 后端(app.py,关键部分)

# -*- coding: utf-8 -*-
"""前端 + 后端一体:Flask 提供交互页面,后端代调 Hugging Face 推理 API。
令牌只放在后端环境变量里,不暴露给浏览器。"""
import base64, io, json, os, time, datetime
from pathlib import Path
from flask import Flask, jsonify, request, send_from_directory
from huggingface_hub import InferenceClient

BASE = Path(__file__).parent
MODEL_ID = "XLabs-AI/flux-RealismLora"
PROVIDER = os.environ.get("HF_PROVIDER", "auto")

app = Flask(__name__)
_client = None

def get_client():
    global _client
    if _client is None:
        token = os.environ.get("HF_TOKEN")
        if not token:
            raise RuntimeError("缺少环境变量 HF_TOKEN,请先设置后再启动")
        _client = InferenceClient(provider=PROVIDER, api_key=token)
    return _client

@app.route("/")
def index():
    return send_from_directory(BASE / "static", "index.html")

@app.route("/api/generate", methods=["POST"])
def generate():
    data = request.get_json(force=True)
    prompt = (data.get("prompt") or "").strip()
    if not prompt:
        return jsonify(error="prompt 不能为空"), 400

    kwargs = dict(
        model=MODEL_ID,
        negative_prompt=data.get("negative_prompt")
        or "cartoon, anime, illustration, painting, deformed, watermark",
        width=int(data.get("width", 1024)),
        height=int(data.get("height", 1024)),
        num_inference_steps=int(data.get("steps", 28)),
        guidance_scale=float(data.get("guidance", 3.5)),
    )
    seed = data.get("seed")
    if seed not in (None, ""):
        kwargs["seed"] = int(seed)

    t0 = time.time()
    try:
        image = get_client().text_to_image(prompt, **kwargs)
    except Exception as exc:  # 把 API 报错原样返回给前端便于截图记录
        return jsonify(error=f"API 调用失败:{exc}"), 500
    elapsed = time.time() - t0

    out_dir = BASE / "outputs"
    out_dir.mkdir(exist_ok=True)
    stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    out_file = out_dir / f"flux_realism_{stamp}.png"
    image.save(out_file)

    buf = io.BytesIO()
    image.save(buf, format="PNG")
    # …(追加 calls_log.jsonl 记录,同脚本版)…

    return jsonify(
        image_base64=base64.b64encode(buf.getvalue()).decode(),
        file=str(out_file),
        elapsed=round(elapsed, 1),
    )

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000, debug=False)

③ 前端交互脚本(static/index.html 的 JS 部分)

const btn = document.getElementById('go');
btn.addEventListener('click', async () => {
  const prompt = document.getElementById('prompt').value.trim();
  if (!prompt) { statusEl.textContent = '请先输入提示词'; return; }
  btn.disabled = true;
  statusEl.textContent = '调用中……首次调用提供方冷启动可能需要数十秒,请耐心等待';
  try {
    const resp = await fetch('/api/generate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        prompt,
        negative_prompt: document.getElementById('neg').value.trim(),
        seed: document.getElementById('seed').value.trim()
      })
    });
    const data = await resp.json();
    if (!resp.ok) throw new Error(data.error || ('HTTP ' + resp.status));
    const img = document.getElementById('result');
    img.src = 'data:image/png;base64,' + data.image_base64;
    img.style.display = 'block';
    statusEl.textContent = '生成成功,耗时 ' + data.elapsed + ' 秒';
  } catch (e) {
    statusEl.textContent = '失败:' + e.message;
  } finally {
    btn.disabled = false;
  }
});

页面完整 HTML/CSS(暗色主题、提示词输入框、负向提示词与种子设置、结果展示卡片)见附件项目 static/index.html,博文中可按需粘贴。

1.3 API 调用成功记录

终端 (2)

1.4 前端页面生成图像效果

网页加图片

flux_realism_20260907-233844

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

总体思路:这个 LoRA 的目标是"照片感",所以提示词要用摄影语言写,而不是用插画语言写。对 FLUX + 真实感 LoRA 来说,"怎么拍"(胶片型号、镜头、光线、颗粒)比"拍什么"(主体描述)更能决定最终图像像不像真实照片——因为 LoRA 训练集的 caption 里大量包含这类摄影术语。修改过程遵循"基线 → 加摄影要素 → 加细节与瑕疵 → 负向提示词收口"四步:

版本 提示词(要点) 生成效果与问题
V1 基线 an elderly fisherman mending nets on a wooden dock 主体正确但构图随机、皮肤质感发"塑料",仍有明显的 AI 插画味
V2 加摄影要素 追加 shot on Kodak Portra 400 35mm filmnatural overcast lightLeica Summilux 35mm f/1.4, shallow depth of field 真实感明显提升,出现胶片色调和背景虚化;但人物过于"干净完美",像摆拍
V3 加细节与瑕疵 追加 wrinkled sun-damaged skin with visible pores and stubblefaded flannel shirt with frayed threadsmist over gray watersubtle film grainminor lens imperfections, no retouchingdocumentary photography 皮肤纹理、衣物磨损、环境雾气都到位,"抓拍纪实感"成立
最终版 V3 基础上再加负向提示词收口(见下) 压掉了偶尔滑向磨皮/影楼风的随机输出

负向提示词airbrushed, beauty filter, smooth plastic skin, makeup, glam, ...——思路不是排除"画错的东西",而是专门排除破坏照片真实感的美化倾向(磨皮、美颜滤镜、影楼妆感),把模型向"精修人像"滑动的情况压回"纪实摄影"。

对照实验方法:固定 seed=42,只替换 V3 中的单个短语(如删掉 subtle film grain),对比两次输出的差异截图——这样"修改过程"就有可复现的证据,而不是凭感觉说"改好了"。

1.6 操作经验总结

  1. 鉴权前置是基本安全习惯:HF 令牌必须放后端环境变量 HF_TOKEN,浏览器端不接触。如果前端直连 Hugging Face,任何访问者都能从页面源码里拿走令牌——这次把"前端 → Flask 后端 → API"的代理层搭起来后,才真正理解"密钥不出后端"不是一句空话。
  2. 接口在演进,教程会过期:旧版 api-inference.huggingface.co 接口已停用,网上 2024 年前的老教程代码直接报 410/404。现在统一走 Inference Providers(InferenceClient(provider="auto")),同一个模型可以在多个算力提供方之间切换,排错时要先看模型页确认当前可用的提供方(注意官方名称是 fal-ai 而不是 fal)。
  3. 冷启动与耗时:首次调用提供方冷启动明显偏慢(数十秒级),之后同一模型再调就快很多。我在后端给每次调用记了耗时并写入 calls_log.jsonl,最终一次生成 12.7 秒——没有度量就没有体感,日志同时还能直接当作业截图素材。
  4. 提示词工程的重心:照片感 LoRA 对摄影术语(胶片型号、镜头、光线、颗粒、"未修图")极其敏感,对主体本身的形容词反而没那么敏感。写提示词更像在给摄影师下拍摄需求单,而不是在描述一幅画。
  5. 随机性管理:不固定种子时,同一提示词两次输出差异很大,容易误判"改动有没有效"。固定 seed 做单变量对比后,评估才变得可靠——这大概就是软件工程里"可复现实验"的直觉版本。
  6. 许可证意识:flux-RealismLora 沿用 FLUX.1-dev 的非商业许可,作业使用没问题但不能商用。模型选型时许可证和效果同等重要,这是之前完全没考虑过的维度。

二、GitHub 个人主页搭建

采用方案:创建个人资料自述文件(Profile README)。新建一个与 GitHub ID 完全同名的公开仓库,在其根目录 README.md 中撰写个人介绍,GitHub 会自动将其作为个人主页展示。

搭建步骤:

  1. 登录 GitHub,点击右下角 +New repository
  2. Repository name 填入与自己的 GitHub 用户名一模一样的字符串(如用户名为 zhangsan,仓库名也必须写 zhangsan),可见性选 Public
  3. 勾选 Add a README file,点击 Create repository
  4. 进入仓库,点击 README.md → 右上角铅笔图标编辑,将撰写好的主页内容粘贴进去,Commit changes 保存
  5. 打开 https://github.com/X-runner354 验证主页效果,确认渲染正常

2.1 主页截图

【贴图:https://github.com/X-runner354 页面完整截图,建议包含头像、简介、技能树与规划部分,滚动截长图更佳】

7347fb51-5708-43ee-bbff-ef639154ea74

2.2 主页内容说明

  • 自我介绍:主页以"一个想把'能跑就行'变成'能稳定地跑'的初学者"开场,介绍专业班级、目前沉迷的方向(用大模型解决实际问题),爱好【填写 2~3 项,如跑步、摄影、看悬疑小说】,并附博客园主页与联系方式,方便同学交流。
  • 成果与技能:技能部分按编程语言星级表 + 工具环境两个维度列出(Python / C / 前端基础 / Git / Flask),并配了两个实际项目:一是"蒲公英计划"感恩主题网站(1 主页 + 3 人物故事详情页的纯前端项目,含签名墙、知识挑战等交互功能),二是本次作业的 HF Flux 生图应用(Flask 前后端一体、令牌保护、调用日志),每个项目都写明了技术要点与踩过的坑。
  • 自我评估:分"已掌握 / 感兴趣方向 / 最希望学习"三层,并单独成段写了"我清楚自己还不会什么"——大型项目架构设计、多人协作规范、测试与 CI/CD、算法竞赛能力,直接回应了作业要求中"了解你会什么以及你不会什么"这一关注点。
  • 三年规划:主线考研,方向倾向人工智能 / 软件工程。理由是想在 AI 方向走得更深,补上本科阶段零散工具学习之外的系统理论。规划按大三(打基础 + 数学英语推进 + 争取竞赛或科研经历)、大四上(全力备考)、大四下(做一个真正上线有人用的毕业设计)三段列出可验证目标,并给出备选路径:若升学不理想,先从工程侧进入 AI 应用团队工作,之后再判断是否返校深造。

三、技能树自我评估与学习规划

3.1 技能树与技术偏好

【按要点清晰列出,逻辑明确。形式不限,可用表格】

能力 掌握程度 说明
【Python】 【熟练】 【感恩小程序】
【前端】 【了解】 【静态网页】
【Git】 【基本了解】 【课程活动】
  • 感兴趣的技术方向:【软件工程】
  • 还欠缺的能力:【系统架构设计能力】

3.2 代码量

  • 截至目前代码量:约 6500 行(包含课程作业和练习)。
  • 本学期课程结束后希望达到:15000行,

3.3 对课程的期待

  • 最期待学习的知识:【软件生命周期与工程化开发方法(如需求分析、系统架构设计、敏捷开发与项目管理等),以及现代软件开发工具链与质量保证技术(如自动化测试、DevOps等)】
  • 希望获得的收获:【建立系统化的软件工程思维,能够独立或协作完成从需求获取、系统设计、编码实现到测试维护的完整软件项目,并具备解决复杂工程问题、跨团队协作及持续学习的能力,为未来的职业发展打下坚实的工程实践基础。】

3.4 AI 生成的软件工程课程学习指南

【使用DeepSeek生成,将指南原文粘贴如下】

AI 时代的软件工程课程学习指南:从传统开发到智能工程
在人工智能技术飞速发展的当下,软件工程的底层逻辑正在经历深刻变革。从“以人力为核心”的工业化生产模式,转向“知识密集型”的智能化生产模式。开发者不再仅仅是代码的编写者,更是AI工具的驾驭者和系统架构的设计师。本指南旨在为你提供一套系统化、面向未来的软件工程学习路径,帮助你在AI时代建立核心竞争优势。
一、 核心认知:AI 时代软件工程的新范式
在学习具体技术之前,首先需要完成认知上的升级。AI 软件工程并非简单的“产品+AI”叠加,而是软件生产逻辑的重构。
角色转变:开发模式正从“面向代码”转向“面向规约(Spec Coding)”。开发者的核心能力转变为精准定义需求、规则与约束,由AI生成可落地的代码。
人机协同:未来的开发团队将是“三元混合劳动力体系”,包括全人劳动力(负责高复杂度战略任务与价值判断)、人携智能体劳动力(人机协同完成需求/代码/测试)以及智能体自闭环劳动力(负责标准化低风险任务)。
基础依然重要:尽管 Coding Agent 的代码编写能力日益强大,但开发者仍需深刻理解系统工作原理。AI 负责“正确地做事”,而人负责判断“什么是正确的事”。
二、 核心技能图谱:AI 时代的软件工程基础
结合行业最新需求与专家共识,AI时代的软件工程基础可划分为以下五大核心模块:
全栈应用开发:借助 AI 辅助,开发者可以跨越不熟悉的技术领域。重点在于理解 UI 组件、API 设计、状态管理、数据持久化等组件如何解决实际问题并相互连接,从而判断 AI 生成的实现是否符合整体设计。
数据管理:数据是软件系统的核心资产。学习如何根据访问方式决定数据模型与存储方式(关系型、文档、键值等),并掌握事务并发控制、数据一致性保障,以及隐私合规等数据生命周期管理。对于 AI 应用,数据架构直接决定了模型能获取的上下文质量。
系统架构设计:架构取决于业务需求。学习如何根据用户规模、延迟敏感度、成本要求等条件,进行前后端边界划分、系统拆分及单体/微服务架构选择。理解架构需随项目阶段和业务复杂度动态演进。
安全与可靠性:建立完善的测试策略(单元测试、集成测试),并设计应对 API 限流、服务降级等故障场景的容错机制。同时,需掌握安全左移实践,理解供应链风险、代码漏洞扫描及云配置安全,确保 AI 生成代码的可靠性。
生产环境扩展与运行:掌握完整的软件生命周期,包括 CI/CD 自动化部署、可观测性(监控与告警)建设、负载均衡及数据基础设施调整。此外,版本控制、代码评审和技术债管理决定了项目的长期可维护性。
三、 进阶学习路径:从基础到智能工程化
建议遵循“基础 → 应用 → 工程化 → 进阶”的分阶段路径,坚持“70%实践 + 20%交流 + 10%理论”的原则。
基础准备阶段:掌握 Python 核心语法、异步编程、API 调用及 Git 版本控制。补充必要的数学基础(线性代数、概率统计),重点理解概念与适用场景,无需深究公式推导。
应用开发阶段:深入学习提示词工程(Prompt Engineering)、检索增强生成(RAG)技术以及 Agent(智能体)基础。通过构建公司内部文档问答系统、个人知识库助手等完整应用,验证学习成果。
工程化阶段:建立自动化评估体系,使用数据而非感觉指导迭代。掌握容器化部署(Docker)、API 服务封装、模型量化及并发处理。学习 LLMOps,包括 CI/CD 流水线、灰度发布及监控运维。
进阶与专精阶段:探索模型微调(LoRA/PEFT)、复杂多 Agent 协作及长周期任务规划。关注 AI 系统架构设计、多模态应用及边缘 AI 技术,并根据场景权衡 RAG 与微调、API 与自部署的成本与效果。
四、 实践与验证:打造你的核心竞争力
纸上得来终觉浅,绝知此事要躬行。在学习过程中,务必注重工程化思维的培养与实战能力的验证。
项目驱动学习:参与或主导完整的 AI 应用开发项目,从需求分析、架构设计到测试上线,体验全流程。尝试将传统业务进行智能化升级,例如构建基于大模型的违禁品识别系统或智能客服,积累可迁移的行业解决方案。
建立评估驱动思维:在开发中引入“AI 生成、AI 验证”的质量保障闭环。构建测试集,利用 LLM 作为评判进行离线与线上评估(关注正确率、幻觉率、延迟、成本等指标)。
能力验证与输出:在 GitHub 上维护 2-3 个包含完整 README 与在线演示的项目。通过撰写技术博客、参与开源社区贡献或对照面试题库自测,持续检验和提升自己的工程化水平。
五、 推荐学习资源
经典课程:吴恩达(Andrew Ng)的 Coursera 系列课程及 DeepLearning.ai 短课程、3Blue1Brown 的数学可视化教程。
核心工具:LangChain、LlamaIndex、Hugging Face Transformers、Vercel AI SDK。
必读书籍:《深度学习》(花书)、《AI Engineering》(Chip Huyen)、《AI Agents Guidebook》。
实战平台:Kaggle 竞赛、AgentInterview 开源项目。

我的分析:

✅哪些建议对你有帮助?
全栈应用开发基础:无论AI多强大,理解前后端交互、API设计、数据库模型依然是《软件工程》课程的核心。你可以借助AI来加速这部分的学习。
安全与可靠性(测试策略):指南中提到的“建立自动化评估体系”和“单元测试/集成测试”是软工课程的必考点和必做项。你可以尝试用AI帮你生成测试用例,这非常实用。
项目驱动与版本控制:强调在GitHub上维护项目、使用Git进行版本控制,这完美契合了软工课程的团队作业要求。
生产环境扩展(CI/CD):了解持续集成和持续部署的概念,对你完成软工课程的最终答辩和交付有极大的加分作用。
❌ 哪些建议不切实际?
数学基础与模型微调(LoRA/PEFT):这是“算法工程师”或“AI研究员”的技能。对于软工课程而言,你不需要去推导公式或微调大模型,你的任务是调用API构建应用和设计系统架构。
复杂多Agent协作与边缘AI:这些属于进阶研究方向,对于刚接触软工课程的学生来说门槛过高,且很难在短短一学期的课程作业中落地。
完全转向“面向规约(Spec Coding)”:虽然这是趋势,但在学校课程中,老师依然会考察你的底层编码能力和对系统原理的理解。你不能完全依赖AI生成代码而放弃自己思考架构。
💡 能否真正指导你的学习?(如何调整)
这份指南不能直接作为《软件工程》课程的学习大纲,但可以作为你的“课外拓展与进阶路线图”。
为了真正指导你的课程学习,建议你这样调整:
主线(占70%精力):严格按照学校软工课程的教学大纲走。扎实掌握需求分析(UML图)、系统设计、传统软件测试、项目管理(敏捷/瀑布)等传统软工核心知识。
副线(占30%精力):把这份指南作为“加分项”。在课程的大作业或毕业设计中,尝试引入指南中的AI工程化思维。例如:用AI辅助编写测试脚本、使用RAG技术为项目增加一个“智能问答模块”、或者用AI生成部分代码并自己进行Code Review。
总结来说: 这份指南是一份优秀的“AI应用工程师”转型指南,但对于你的软工课程,你需要“降维使用”——用传统的软工方法论去驾驭AI工具,而不是被AI工具带偏了软工基础。


四、博文编辑页面截图

markdown


参考资料


posted @ 2026-09-08 19:24  远航星的告别  阅读(21)  评论(0)    收藏  举报