装闭 RenoPit 源码解析(05):FastAPI与Celery如何执行AI装修分析

AI 装修闭坑分析可能包含多张图片、多份合同以及多次大模型调用,不适合让 FastAPI 请求一直阻塞。装闭 RenoPit 在 fthux/RenoPit 中使用 Celery 和 Redis 编排这条长任务链,本篇分析任务从入队到结束的全过程。

一、FastAPI 只负责启动任务

用户点击"开始分析"后,ProjectPagePOST /api/projects/{id}/analyze 发送请求。trigger_analysis() 首先查询项目、图片和文件,并判断三类输入是否至少存在一种:

  • 可分析图片;
  • 已上传文档;
  • 非空的用户补充说明。

输入为空时返回 400;项目已经处于 analyzing 时返回 409。校验通过后,接口先把项目状态提交为 analyzing,再投递任务:

python 复制代码
from ..tasks.analysis import run_analysis_task
run_analysis_task.delay(project_id)

如果入队失败,接口会把状态恢复为 pending。因此浏览器收到成功响应时,数据库已经记录了分析中的状态,任务也已经进入 Redis。

二、Celery 如何连接 Redis

tasks/celery_app.py 创建 Celery 实例,Broker 使用 Redis 0 号库,结果后端使用 1 号库:

python 复制代码
celery_app = Celery(
    "renovation_analyzer",
    broker=settings.CELERY_BROKER_URL,
    backend=settings.CELERY_RESULT_BACKEND,
    include=["app.tasks.analysis"],
)

任务消息和结果采用 JSON 序列化。task_acks_late=True 表示任务执行完成后才确认消息,worker_prefetch_multiplier=1 让 Worker 每次只预取一个长任务。软、硬时间限制都设置为 1200 秒,以容纳串行的图片和文档分析。

Docker Compose 中的 backendcelery_worker 使用同一份代码和环境变量,但启动命令不同。Worker 不接收 HTTP 请求,只监听 Redis 队列。

三、run_analysis_task 是总编排器

Celery 实际执行的是 run_analysis_task(project_id)。它不是直接调用一次 LLM 就结束,而是按六个阶段组织任务:
flowchart TD A验证项目 --> B状态改为 analyzing B --> C设计图综合分析 C --> D逐份文档分析 D --> E{成功文档是否不少于两份} E -->|是| F跨文档核查 E -->|否| G汇总状态 F --> G G --> Hcompleted 或 failed

第三步调用 run_analysis_sync() 处理图片、已提取文本和用户说明。设计图分析失败不会立刻终止整个任务,因为合同与报价单分析可以独立完成。

四、文档分析按文件串行执行

任务会查询当前项目中 extracted_text 非空,且类型为 PDF、DOCX、TXT 或 Markdown 的文件。每份文件调用一次 run_document_analysis_sync(),结果追加到 doc_results

单份文档异常会被捕获并记录为失败,不会阻断下一份文件。这样一份无法解析的合同不会让其他报价单全部失去分析机会。

当文档结果数量不少于两份时,任务继续调用 run_cross_check_sync()。该阶段会比较合同和报价单中的金额、项目、责任条款等信息,并把差异写回综合分析结果。

五、项目完成状态如何判定

任务结束时分别计算:

python 复制代码
design_ok = result.get("status") == "completed"
doc_ok_count = sum(
    1 for item in doc_results if item.get("status") == "completed"
)

只要设计分析成功,或者至少一份文档分析成功,项目就被标记为 completed。完成消息会汇总设计问题数、文档成功数和跨文档差异数。

只有设计分析与全部文档分析都失败时,项目状态才写为 failed。最外层异常同样会落入失败分支,并把错误信息提供给后续 SSE 接口读取。

六、停止分析如何改变状态

POST /projects/{id}/stop 只接受当前状态为 analyzing 的项目。接口把项目恢复为 pending,再找到最近一条 processingpendingAnalysis,将其标为 failed,错误信息写成"用户手动停止"。

状态提交后,SSE 轮询会观察到 pending 并发送 stopped 事件。项目页据此关闭进度条并恢复开始分析按钮。

七、异步任务调用链小结

RenoPit 把 HTTP 请求和 AI 计算分成两个进程:FastAPI 完成输入校验、状态更新和任务投递;Celery Worker 完成设计分析、文档分析、交叉核查和最终状态汇总。Redis 负责传递任务,PostgreSQL 则是两个进程共同认可的业务状态来源。

这条任务链的完整代码可以在 fthux/RenoPit 中查看。下一篇将继续分析浏览器如何通过 SSE 观察数据库状态,并把后台任务转换为实时进度条和完成跳转。

相关推荐
格数致用1 小时前
数据库设计与表结构详解|信息化项目全流程管理系统源码逐行精讲(五)
人工智能·政务·数据库设计·外键约束
罗西的思考2 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
DevUI团队2 小时前
从“即兴创作”到“规格先行”,华为云码道(CodeArts)代码智能体持续深耕企业级规范驱动开发能力
前端·人工智能·后端
论文避坑指南2 小时前
论文写作全流程AI合规边界:从选题到投稿的“红绿灯“清单
大数据·人工智能·深度学习
Dawson Zhu2 小时前
工业世界模型——基于AI Agent+数学仿真架构
人工智能·架构·agi
冬奇Lab2 小时前
开源项目第183期:Ontology Playground — 微软出品的本体论可视化学习工具,零后端、浏览器直接运行
人工智能·microsoft·开源
Wang's Blog2 小时前
AI Agent白手起家52: 从零搭建钉钉智能助手——资源准备与核心架构实现
人工智能·架构·钉钉
冬奇Lab2 小时前
代码库知识库系列(13):评测——怎么知道知识库够不够好
人工智能
字节跳动视频云技术团队2 小时前
把 AI 视频的钱花在刀刃上,不是每一刀上
人工智能·音视频开发