
LLM 服务返回的只是文本,真正把项目素材、Prompt、模型调用、JSON 校验和数据库记录串起来的是 analysis_engine.py。本篇基于开源仓库 fthux/RenoPit,分析 run_analysis_sync() 的完整执行过程。
一、AnalysisEngine 是业务编排层
Celery 负责决定"先分析设计,再分析文档",而 run_analysis_sync(project_id) 只负责一次综合设计分析。它的主流程可以概括为:
flowchart TD A加载 Project --> B读取图片和文件 B --> C图片压缩并转 Base64 B --> D文档提取纯文本 C --> E输入校验 D --> E E --> F创建 Analysis: processing F --> G构建 Prompt G --> H调用 analyze_design H --> IJSON 解析与修复 I --> Jcompleted 或 failed J --> K提交数据库
二、加载项目与预处理输入
函数首先通过 SessionLocal 创建独立数据库会话,查询 Project,再读取该项目的全部 ProjectImage 和 ProjectFile。
每张图片都会检查磁盘文件是否存在,然后执行 compress_image() 和 image_to_base64()。单张图片失败会被跳过,不会中断其他图片。
每份文档则根据原始文件名取得扩展名,通过 parse_file_text() 提取文本。成功文本写入两个列表:一个保存内容,一个保存真实文件名;同时更新 ProjectFile.extracted_text。
这里会先执行一次 db.commit() 持久化提取文本。即使后面的 LLM 调用失败并触发回滚,Celery 下一阶段仍能查询到这些文本并继续执行独立文档分析。
三、输入校验和 Analysis 记录
_validate_input() 检查图片、文档文本和用户说明是否至少存在一项。没有任何有效内容时,函数返回失败结果,不会调用 LLM。
校验通过后创建一条 Analysis:
python
analysis = Analysis(
project_id=project_id,
status="processing",
)
db.add(analysis)
db.flush()
flush() 让代码在事务提交前拿到分析 UUID,便于记录日志和后续更新。重新分析会创建新记录,而不是覆盖旧记录。
四、构建 Prompt 并调用模型
分析引擎调用 build_system_prompt() 注入本地装修知识库,然后把图片 Base64、文档文本、用户说明和文件名交给 analyze_design()。
由于当前函数是同步入口,异步 LLM 调用通常通过 asyncio.run() 执行。如果遇到已经运行的事件循环,代码会根据错误类型切换到线程池或现有循环;普通 LLM 异常则继续向外传播,进入统一失败处理。
模型返回后,分析引擎记录响应长度,并把完整文本交给 validate_and_repair()。数据库不会直接保存未经解析的字符串。
五、JSON 如何解析和修复
parse_json() 先从 Markdown 代码围栏或混合文本中提取 JSON 区块,再按两步处理:
- 直接调用
json.loads(); - 失败后使用
json_repair修复,再次解析。
解析出的顶层对象需要包含 summary 和 problems。每个问题至少要有 title;bbox 如果存在,必须是四个数字组成的数组。
validate_and_repair() 对"存在 summary、但 problems 为空"的结果作特殊处理:它把这种情况视为模型没有发现装修陷阱,允许空数组通过。非关键字段缺失则由 apply_fallback() 补齐,例如默认位置、批判说明、套路解释和替代方案。
六、结果如何写回数据库
校验成功时,完整字典写入 Analysis.raw_result_json,状态改为 completed,同时记录 completed_at。问题数量来自 result_data["problems"]。
解析失败或关键字段缺失时,状态写为 failed,error_message 保存校验原因。其他异常先执行 rollback(),再尝试把已创建的分析记录更新为失败状态并重新提交。
函数最终只返回一个轻量结果:状态、分析 ID、项目 ID、问题数量和错误信息。大体积 JSON 留在数据库中,由 /result 接口在报告页加载。
七、分析引擎调用链小结
AnalysisEngine 是素材与 LLM 之间的适配层:它把磁盘文件转成模型输入,把异步 LLM 包装成同步调用,再把不稳定的文本输出转换成可持久化 JSON。Celery 只需要根据返回状态继续调度文档分析和交叉核查。
主流程、事务处理和 JSON 校验代码都可以在 fthux/RenoPit 中查看。下一篇将从综合设计分析切换到单份合同与报价单,分析文档分类、风险审查和增项预测链路。