基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-10-24 14:52

用FastAPI搭建图像诊断AI接口

dev.to · AI#多模态#接口开发#结构化输出
Editor brief · 编辑速览

教程以玉米叶片诊断为例,通过FastAPI接收图片、调用Gemma 4并返回结构化JSON。流程涵盖上下文文件、提示词管理、输入校验和测试,可迁移到其他图像分析任务。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

45 分钟,把一张玉米叶片照片变成 JSON 诊断结果:这篇 AgriScan 工作坊用 Python、FastAPI 和 Gemma 4,演示了一条从模型调用到 API、测试和演示交付的完整路径。它真正值得借鉴的,是如何给 AI 应用安排清楚的代码边界。

但「接口能返回结果」离「诊断可信」还有距离。原文提供的是 Hack Day 原型教程,没有农业诊断准确率,也没有生产环境验证。读它时,可以带走工程组织方式,同时把模型效果和接口可靠性分开判断。

先把项目规则写清楚,AI 才知道往哪里改

AgriScan 的请求链路很短:用户上传照片,FastAPI 检查输入,app/gemma.py 带着 app/prompts.py 中的提示词调用模型,再解析 JSON 并返回。

作者要求在写代码之前,先创建 AGENTS.md。里面明确 Python 3.11、FastAPI、google-genai,指定模型为 gemma-4-26b-a4b-it,启动命令是 fastapi dev app/main.py,测试命令是 pytest。

更有用的是四条约束:密钥来自 GEMINI_API_KEY;模型调用集中在 app/gemma.py;提示词集中在 app/prompts.py;每条路由都要有不调用真实模型的测试。它们把容易散落在项目各处的东西,提前收到了固定位置。

上下文文件的价值,是让后续修改有明确边界。

作者据此建议,在 Copilot Chat 的 agent 模式中直接提出小任务,例如添加无框架的 HTML 上传页,调用 POST /diagnostic 并显示结果。需求可以短,前提是项目规则已经写清。至于 Copilot 是否按预期读取并遵守这些规则,仍要检查实际改动,原文没有提供遵循率之类的验证。

环境准备也很朴素:依赖只有 fastapi[standard]、google-genai 和 pytest,通过 python -m venv .venv 创建虚拟环境,再运行 pip install -r requirements.txt。密钥不能进仓库;如果使用 .env,就要确认它在 .gitignore 中。

从图片到 JSON,真正需要约定哪些东西

按原文说明,Gemma 4 是 Google 的开放权重模型,支持文本和图片;教程通过 Gemini API 调用,免去本地运行模型的准备。文中列出两个模型标识:gemma-4-26b-a4b-it 和 gemma-4-31b-it,实际使用前者。免费密钥和模型可用性是原文的描述,本文没有额外核验。

提示词定义了三件事:服务对象是多哥的小农户,输入是玉米叶片照片,输出必须是法语 JSON。字段固定为 maladie、confiance、conseil,分别表示疾病、置信程度和一句行动建议。置信程度只能取 faible、moyenne、forte,非玉米照片则返回 photo non valide。

这让业务需求变得具体:模型不只要「看图回答」,还要遵守字段、语言和异常输入约定。

下面这段代码把模型调用集中起来,图片作为内容的一部分发送,业务提示词放进 system_instruction:

import json

from google import genai
from google.genai import types

from app.prompts import DIAGNOSTIC_PROMPT

MODEL = "gemma-4-26b-a4b-it"

def analyser_image(image_bytes: bytes, mime_type: str) -> dict:
    """Envoie la photo à Gemma 4 et renvoie le diagnostic sous forme de dict."""
    client = genai.Client()  # créé ici pour que les tests n'aient pas besoin de clé
    response = client.models.generate_content(
        model=MODEL,
        config=types.GenerateContentConfig(system_instruction=DIAGNOSTIC_PROMPT),
        contents=[
            types.Part.from_bytes(data=image_bytes, mime_type=mime_type),
            "Analyse cette photo.",
        ],
    )
    return extraire_json(response.text)

要关注最后一行:拿到 response.text 之后,程序还要负责解析,模型回复并没有直接成为可靠的数据结构。

作者的 extraire_json 从第一个 { 截到最后一个 },再交给 json.loads。这能处理部分解释文字或 Markdown 围栏,却不保证只有一个 JSON 对象,也不校验字段是否齐全、枚举是否正确。

要求模型输出 JSON,与程序验证输出契约,是两件事。

FastAPI 路由只接收 image/jpeg 和 image/png,其他类型返回 415;文件上限是 5 * 1024 * 1024 字节,超出返回 413;解析触发 ValueError 时返回 502。作者还建议把 photo non valide 映射为 422,但这是后续练习,初版路由没有实现。

测试通过,究竟证明了哪一层正确

原文最适合日常 AI 编程借鉴的,是用 monkeypatch 替换模型调用。它让路由测试不用消耗配额,也不依赖网络或密钥。

下面两项测试分别验证正常返回和拒绝 PDF,代码保留原样:

from fastapi.testclient import TestClient

from app import gemma
from app.main import app

client = TestClient(app)

def test_diagnostic(monkeypatch):
    faux = {"maladie": "rouille", "confiance": "moyenne", "conseil": "..."}
    monkeypatch.setattr(gemma, "analyser_image", lambda data, mime: faux)
    r = client.post("/diagnostic", files={"photo": ("feuille.jpg", b"fake", "image/jpeg")})
    assert r.status_code == 200
    assert r.json()["maladie"] == "rouille"

def test_refuse_un_pdf():
    r = client.post("/diagnostic", files={"photo": ("doc.pdf", b"%PDF", "application/pdf")})
    assert r.status_code == 415

要注意 monkeypatch.setattr(gemma, "analyser_image", ...)。路由采用 gemma.analyser_image(...) 调用,测试替换的是同一个模块属性,因此能拦住真实请求;如果换了导入方式,也要重新确认替换目标。

测试里的图片内容只是 b"fake"。它证明上传请求能进入路由、假结果能返回,无法证明接口识别了真实 JPEG,更无法证明玉米疾病判断正确。

原文另有一项 JSON 提取测试,并以「三个测试通过、不需要 API 密钥」描述预期结果。但提供的正文中,部分代码围栏和换行已经损坏,不能直接把整篇复制运行,也没有附测试日志。

作者安排的人工检查是:先用 python essai.py 验证连通性,再上传真实叶片和无关照片,最后在 http://127.0.0.1:8000/docs 操作 POST /diagnostic。每次修改后读 diff、跑 pytest、试接口、提交代码。自动测试与真实调用各负责一部分,这个安排是合理的。

我的判断

我赞同它对项目边界的处理。单独管理提示词、集中封装模型调用、用假响应测试路由,能让一个小原型保持可理解,也方便后续换模型或改提示词。

但「45 分钟」是教程目标,原文没有给出不同参与者的完成时间;「JSON 可靠」也说得偏满,当前实现缺少字段校验。提示词中出现 confiance,不代表这个置信程度经过校准,尤其非玉米照片还被要求固定返回 forte,前端不能把它直接展示成准确率。

接口还有明确的工程缺口:async def 路由中执行同步模型调用;整份文件读入后才检查大小;上传类型只检查声明的 MIME;网络失败、配额耗尽和超时没有完整处理。这些不妨碍工作坊演示,却限制了它直接上线的适用范围。

与当前的提示词约束加字符串截取相比,用 Pydantic 等工具校验解析后的字段,更方便约束 API 返回值;模型侧是否支持所需的结构化输出机制,则需要另行确认。原文没有做方案对比,也没有诊断数据集或专家复核,因此疾病识别效果只能保留判断。

另外,作者建议 AI 改错方向时运行 git restore .。这会丢弃工作区中尚未暂存的修改,使用前应确认改动范围,避免连自己的有效修改一起撤销。

能拿来做什么

  • 做图片识别原型时,可以沿用「上传路由、模型适配层、提示词文件」的结构,先通过 FastAPI 的 /docs 验证请求链路,再添加 HTML 页面。
  • 给前端对接 AI 接口时,应明确三个字段的取值与错误状态,把 413、415、422、502 分别转成可理解的提示,并对模型输出补充字段校验。
  • 编写测试时,可以先替换真实模型,覆盖路由和异常分支;再用少量真实照片检查模型表现,分别记录程序错误与识别错误。
  • 使用 Copilot 扩展项目时,可以先写好 AGENTS.md,再按小任务推进,每次检查 diff 并运行测试,确认理解改动后再提交。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Kimi 3.1 Pro 宣称开放权重并提升接口速度
下一篇
评论监控用定时任务就能落地

资讯速览

dev.to · AI · 2026-10-24 14:52

AI 评分 8.0 / 10

相关标签

#多模态#接口开发#结构化输出

继续阅读

  • 评估 Agent 记忆:先测它如何处理未知
  • Kimi 3.1 Pro 宣称开放权重并提升接口速度
  • 评论监控用定时任务就能落地
  • 让编程Agent交付可核验的完成证据
  • VoxCPM2 开源多语种语音生成模型