澳五机器人 analysis_engine.py 是连接原始项目素材(图片、文档)与大语言模型(LLM)的核心业务编排层
在 RenoPit 项目中,analysis_engine.py 是连接原始项目素材(图片、文档)与大语言模型(LLM)的核心业务编排层。它负责将非结构化的磁盘文件转化为模型可理解的输入,处理异步调用,并将不稳定的文本输出清洗为可持久化的结构化 JSON 数据。
以下是 run_analysis_sync(project_id) 函数的完整执行流程解析:
1. 加载项目与预处理输入
函数首先通过 sessionlocal 创建独立的数据库会话,查询指定 project_id 的项目信息,并读取该项目关联的所有 project_image(图片)和 project_file(文档)。
图片处理:遍历每张图片,检查磁盘文件是否存在。若存在,执行 compress_image() 进行压缩,随后通过 image_to_base64() 转换为 Base64 编码字符串。单张图片处理失败会被跳过,不会中断整体流程。
文档处理:根据原始文件名获取扩展名,调用 parse_file_text() 提取文本内容。成功提取的文本会被存入两个列表(一个保存内容,一个保存真实文件名),同时更新数据库中 project_file 表的 extracted_text 字段。此处会立即执行一次 db.commit(),确保即使后续 LLM 调用失败触发回滚,下一阶段的 Celery 任务仍能查询到已提取的文本继续执行独立文档分析。
2. 输入校验与分析记录初始化
调用 _validate_input() 检查图片、文档文本和用户说明中是否至少存在一项有效内容。若没有任何有效输入,函数直接返回失败结果,避免无效调用 LLM。
校验通过后,创建一条新的 Analysis 记录:
python
analysis = Analysis(
project_id=project_id,
status="processing",
)
db.add(analysis)
db.flush()
使用 flush() 而非 commit(),旨在事务提交前获取分析记录的 UUID,便于后续日志记录和状态更新。值得注意的是,重新分析会创建新的记录而非覆盖旧记录,以保留历史追溯能力。
3. 构建 Prompt 并调用模型
分析引擎调用 build_system_prompt() 注入本地装修知识库,然后将图片 Base64 数据、文档提取文本、用户说明及文件名组合,交给 analyze_design() 函数。
由于 run_analysis_sync 是同步入口,而 LLM 调用通常是异步的,代码通过 asyncio.run() 执行。若检测到已有运行的事件循环,会根据错误类型自动切换到线程池或复用现有循环;普通 LLM 异常则向外传播,进入统一失败处理逻辑。
4. JSON 解析与修复
模型返回的是纯文本,需经过严格的清洗才能入库。validate_and_repair() 函数负责此过程:
提取 JSON:parse_json() 先从 Markdown 代码围栏或混合文本中提取 JSON 区块。
尝试解析:首先调用标准 json.loads()。
自动修复:若解析失败,使用 json_repair 库进行修复后再次解析。
结构校验:
顶层对象必须包含 summary 和 problems 字段。
problems 中的每个问题至少要有 `title字段。
若存在 bbox(边界框),必须是包含四个数字的数组。
特殊处理与兜底:
若存在 summary 但 problems 为空数组,视为模型未发现装修陷阱,允许通过。
非关键字段缺失时,由 apply_fallback() 补齐默认值(如默认位置、批判说明、套路解释和替代方案)。
5. 结果写回数据库
成功场景:校验成功后,完整的字典数据写入 analysis.raw_result_json 字段,状态更新为 completed,并记录 completed_at 时间戳。问题数量从 result_data["problems"] 中统计。
失败场景:若解析失败或关键字段缺失,状态标记为 failed,error_message 记录具体校验原因。
异常处理:其他异常发生时,先执行 rollback() 回滚事务,再尝试将已创建的分析记录更新为失败状态并重新提交,确保数据库状态的一致性。
6. 返回轻量结果
函数最终仅返回一个轻量级结果对象,包含状态、分析 ID、项目 ID、问题数量和错误信息。大体积的 JSON 数据保留在数据库中,由前端 /result 接口在报告页加载时按需读取,以减少内存占用和网络传输开销。
总结
AnalysisEngine 充当了素材与 LLM 之间的适配层:它将磁盘文件转换为模型输入,将异步 LLM 调用包装为同步接口,并将不稳定的文本输出转换为可持久化的结构化 JSON。Celery 任务队列只需根据返回的状态决定后续调度(如继续执行文档分析或交叉核查),实现了业务逻辑与底层 AI 调用的解耦。