跳转至

视觉隐患识别

本页面供调用方参考。三种模式的说明、图片传输格式及错误码均在本页。上游配置方式见 配置 和 CG 字段手册。

CG_RAG 内置施工现场图片安全隐患识别功能。调用方提交 base64 编码图片,即可获取结构化隐患报告,无需自行对接 VLM。

三种模式:

模式 接口 是否检索法规 回答是否带引用 典型耗时
自由生成 /cg-rag/vision/answer 否 否 单次模型调用
智能生成 /cg-rag/vision/agentic 是,模型自行决定检索问题 是,[cite^n] 多轮观察 + 检索
垂域+RAG /cg-rag/vision/hybrid 是,DeepSeek 按千问描述检索 是,正文为 〔n〕 一次看图 + 文本检索
观察 /cg-rag/vision/observe 否 否 单次模型调用

自由生成适用于快速筛查与高并发场景;智能生成适用于需要条文依据、可审计结论的场景;观察返回经校验的隐患标签与展示文本,供调用方将图片转换为检索问题后自行编排检索流程。

与 Question App 的关系

仓库内所有 VLM 调用均发生在 CG_RAG。 Question App 不再自行组装多模态请求,而是通过本页的 HTTP 接口调用 CG_RAG,再将结果渲染为对话轮次:

Question App ──HTTP──> CG_RAG vision ──进程内──> 检索

该设计带来两项直接效果:

  • 智能生成每轮检索无网络往返。agent 与检索同进程,共享同一份 retrieve cache、profile fingerprint 与容量限制器。
  • 判定标准、prompt、引用校验仅有一份实现。Question App 与外部调用方获取到的是同一套行为,不会因两处实现漂移而产生不同结论。

调用方只需访问 CG_RAG,无需额外部署编排层。

前置配置

视觉功能需单独配置一个多模态上游,与文本生成使用不同的配置。YAML 写在 cg_rag.vision(endpoint / model,密钥 cg_rag.vision.api_key)。未配置时,检索与文本生成不受影响,仅 /cg-rag/vision/* 返回 vision_not_configured。

通过 /cg-rag/health 的 vision.configured 字段判断是否就绪。字段说明见 CG 字段手册。

图片输入

两个接口的 images 字段结构相同:

字段 类型 必填 默认 说明
data string 是 无 base64 数据,或 data:<mime>;base64,<...> 形式的 data URL
mime_type string 否 image/jpeg image/jpeg、image/png、image/webp 之一
source_turn_index integer/null 否 null 图片来源轮次,从 0 开始;用于多轮上下文标记

约定:

  • 单次请求最多 max_images 张(默认 4),单张解码后最多 max_image_bytes 字节(默认 16 MiB)。
  • data 为 data URL 时,以 data URL 自带的媒体类型为准,mime_type 字段被忽略。调用方可直接使用浏览器产生的 data URL,不会造成类型错标。
  • 不接受 HEIC 格式。iPhone 原图需由调用方预先转换为 JPEG/PNG/WebP —— CG_RAG 接收的是已解码的字节,且上游 VLM 均不支持 HEIC。
  • 图片仅在内存中流转,不落盘。

多图时,服务会在每张图前注入 图N: 标记,模型按图分块输出(## 图1、## 图2 …)。单图时不注入该标记。

多轮图片与文字

answer、observe 和 agentic 接受可选 history 数组,最多六轮,每项包含 query(用户文字)、answer(助手文字)、turn_index(从 0 开始的轮次)。历史文字按 user/assistant 顺序传给视觉模型;本次 images 必须同时提供需要继续观察的历史图片字节。CG_RAG 不为调用方保存会话或图片, 仅在文字中注明"见上图"不能替代图片内容。

history 非空时,成功响应返回 history_turn_count,调用方可据此确认对端是否接受了多轮协议。 Question API 仅在请求携带 vision_multi_turn=true 时合并当前会话的历史图片与本次上传、按图片 ID 去重,并校验此回执;默认关闭,本轮仅发送当前附件。

POST /cg-rag/vision/answer

自由生成。请求字段:

字段 类型 必填 默认 说明
images array 是 无 至少一张,见上文
question string 否 请检测图中的安全隐患 观察重点;非隐患类问题会被直接回答,不套用固定格式
enable_thinking boolean/null 否 null 单次覆盖服务级 CG_RAG_VISION_ENABLE_THINKING
history array 否 [] 最近六轮以内的用户问题和助手回答,见上文

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/vision/answer \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-doc-vision' \
  -d "{\"images\":[{\"data\":\"$(base64 -w0 site.jpg)\",\"mime_type\":\"image/jpeg\"}]}"

示例输出,已删减:

{
  "ok": true,
  "request_id": "req-doc-vision",
  "mode": "free_form",
  "question": "请检测图中的安全隐患",
  "answer": "隐患等级:一般隐患\n\n隐患分类:扣件式钢管脚手架\n\n隐患描述:\n1. 脚手架基础区域存在明显积水,未采取有效排水措施。\n\n整改措施和建议:\n1. 立即排除积水并设置排水设施。",
  "reasoning": "",
  "image_count": 1,
  "model": "<vlm-model>",
  "thinking_enabled": false,
  "citations": [],
  "retrieval_docs": [],
  "hazard_categories": ["扣件式钢管脚手架"],
  "hazard_taxonomy_version": "construction-hazard-19-v1",
  "usage": {"prompt_tokens": 1180, "completion_tokens": 96, "total_tokens": 1276},
  "runtime_stats": {"total_time_ms": 6421.3}
}

citations 与 retrieval_docs 恒为空数组:该模式不执行检索,回答中不会出现 [cite^n]。需要条文依据时,请使用智能生成模式。服务会校验回答中的分类;首次格式不合法时自动纠正一次,仍不合法则返回 vision_response_invalid,不会返回或保存格式异常的报告。

POST /cg-rag/vision/agentic

智能生成。在自由生成字段的基础上追加:

字段 类型 必填 默认 说明
scope string 否 full 检索范围,full / usual / usual_plus_law
max_search_rounds integer/null 否 null 最多检索轮数,范围 1..3;null 用服务配置
topk integer/null 否 null 每轮检索候选数,范围 1..200;null 用服务配置

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/vision/agentic \
  -H 'Content-Type: application/json' \
  -d "{\"images\":[{\"data\":\"$(base64 -w0 site.jpg)\"}],\"scope\":\"full\",\"topk\":12}"

示例输出,已删减:

{
  "ok": true,
  "request_id": "req_xxx",
  "mode": "agentic",
  "question": "请检测图中的安全隐患",
  "answer": "## 隐患等级\n重大事故隐患\n\n## 隐患分类\n扣件式钢管脚手架\n\n## 隐患描述\n1. 脚手架立杆底部浸泡在积水中。\n\n## 隐患判定依据\n1. 《房屋市政工程生产安全重大事故隐患判定标准(2024版)》第七条第一款:脚手架工程基础承载力和变形不满足设计要求。\n2. 《施工脚手架通用规范》(GB 55023-2022)地基应坚实、平整,不应有积水 [cite^2]。\n\n## 整改措施及建议\n1. 立即排水并复核地基承载力。",
  "reasoning_stages": [
    {"label": "OBSERVATION", "content": "图中脚手架立杆底部处于积水中。"},
    {"label": "SEARCH_PLAN", "content": "检索脚手架地基基础排水与承载力要求。"},
    {"label": "EVIDENCE_REVIEW", "content": "检索到的条文支持地基不应积水。"},
    {"label": "FINAL_REASONING", "content": "按 2024 版判定标准第七条第一款定级。"}
  ],
  "citations": [2],
  "retrieval_docs": [
    {
      "law_name": "GB55023-2022施工脚手架通用规范",
      "article_number": "2.0.1",
      "contents": "脚手架性能应符合下列规定……"
    }
  ],
  "pipeline_trace": [
    {"name": "图片接收", "status": "done", "summary": "已接收并校验 1 张图片。"},
    {"name": "第 1 轮法规检索", "status": "done", "summary": "执行 1 条检索问题,累计保留 12 条证据。"},
    {"name": "证据化结论生成", "status": "done", "summary": "已生成最终回答,使用 1 条服务器引用。"}
  ],
  "scene_status": "assessable",
  "image_count": 1,
  "model": "<vlm-model>",
  "scope": "full",
  "thinking_enabled": false,
  "warnings": [],
  "hazard_categories": ["扣件式钢管脚手架"],
  "hazard_taxonomy_version": "construction-hazard-19-v1",
  "usage": {"total_tokens": 8241},
  "runtime_stats": {"total_time_ms": 41250.8}
}

字段说明:

  • citations 为回答中实际使用的服务器证据序号,与 retrieval_docs 的下标一一对应(从 1 开始)。
  • reasoning_stages 为可公开的审计依据,非模型的原始 thinking。
  • scene_status 取值为 assessable、unsupported_scene、insufficient_visual_evidence 或 not_assessed;后两者表示图片本身不足以判定,此时应按 warnings 提示补拍。
  • pipeline_trace 用于向用户展示进度,亦便于排查某一轮检索是否为空。

隐患等级取值为 无隐患 / 一般隐患 / 疑似重大事故隐患 / 重大事故隐患。每张图同时只有一个主隐患分类;hazard_categories 按图片顺序给出"19 类 + 无"的校验结果,hazard_taxonomy_version 标明分类版本。存在多项隐患时,优先选取等级最高者;同等级则优先画面证据最明确、最具体的设备或工程类别。非施工场景或证据不足时,不会以 无 代替实际情况。定级规则、分类清单和 2024 版判定标准条款清单均由服务端注入 system prompt,调用方无需自行实现。

POST /cg-rag/vision/hybrid

垂域+RAG。与上一节的智能生成不属于同一条处理链路。

智能生成由看图的模型自行决定检索内容,再输出带 [cite^n] 的报告。本接口的处理流程为:千问先按自由生成方式输出隐患描述,描述、等级和分类保持原样;DeepSeek 仅读取该段文字,调用检索工具查询法规,再撰写判定依据和整改措施。文本模型不接收图片。

存在可见隐患且检索到证据时,判定依据固定为 3 条,每条仅引用一条证据。整改措施根据描述和这 3 条依据撰写,条数不要求与依据条数一致。格式校验未通过时,模型先修正一次;仍未通过,服务端保留已输出的可见事实,不整篇重写。visual_qa 直接回答问题,不使用报告格式,亦不执行检索。

请求字段与 /cg-rag/vision/agentic 相同。topk 不生效,服务端固定为 12。未传入 max_search_rounds 时最多检索 2 轮;传入时限制在 1 到 3 轮,每轮最多 3 次工具调用。scope 按请求执行。正文中的引用已写成 〔n〕,citations 为对应的证据序号。agentic 返回的是原始 [cite^n],由调用方自行渲染,两种格式不可混用。

文本模型需单独配置,三项均为必填:

环境变量 含义
CG_RAG_HYBRID_GENERATION_ENDPOINT 文本模型地址
CG_RAG_HYBRID_GENERATION_MODEL 现网为 deepseek-flash
CG_RAG_HYBRID_GENERATION_API_KEY 文本模型密钥,不回退到 CG_RAG_API_KEY

任一项缺失均返回 hybrid_generation_not_configured。不会改用受约束生成的 CG_RAG_GENERATION_MODEL(现网为另一个 deepseek-chat)。

Question App 中 qwen-deepseek-flash 的带图智能生成仅转发至本接口。页面上的模型名、反馈卡和文字复核不变。文字复核不经过本接口,仍由 Question App 使用修改后的描述执行文本检索。返回元数据中的 match_type 仍为 hybrid_vision_agentic,该字段为历史遗留字段名,与 /vision/agentic 无关。

流式路径为 POST /cg-rag/vision/hybrid/stream,事件类型与智能生成相同,并额外增加 retrieval 事件,用于更新检索预览。

POST /cg-rag/vision/observe

单次结构化观察。请求字段与自由生成相同(images、question),但返回的是经校验的观察结果,而非隐患报告:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/vision/observe \
  -H 'Content-Type: application/json' \
  -d "{\"images\":[{\"data\":\"$(base64 -w0 site.jpg)\"}]}"

示例输出:

{
  "ok": true,
  "mode": "observe",
  "text": "图片描述:图中可见施工区域地面存在积水。\n\n确定隐患描述:场地积水问题\n\n整改建议:\n1. 及时排除积水。",
  "hazard_label": "场地积水问题",
  "is_non_scene": false,
  "parse_status": "succeeded",
  "parse_error": "",
  "profile_id": "construction-hazard-inspection-v1",
  "system_prompt_sha256": "<PROFILE_PROMPT_SHA256>",
  "image_count": 1,
  "model": "<vlm-model>",
  "usage": {"total_tokens": 812},
  "elapsed_ms": 5120.4
}

hazard_label 取自服务端的 62 项标签词表,模型无法自行生成词表外的标签。parse_status 为 failed 时,hazard_label 为空,parse_error 说明原因,而 text 仍为可安全展示的原始观察内容——这是正常返回,而非错误:调用方应据此决定降级展示或中止,不应将其视为调用失败。观察接口无流式变体。

流式接口

/cg-rag/vision/answer/stream 与 /cg-rag/vision/agentic/stream 的请求字段与各自的非流式版本完全相同,响应类型为 text/event-stream:

curl --noproxy '*' -N \
  -X POST http://127.0.0.1:8864/cg-rag/vision/agentic/stream \
  -H 'Content-Type: application/json' \
  -d "{\"images\":[{\"data\":\"$(base64 -w0 site.jpg)\"}]}"

事件序列示例,已删减:

event: progress
data: {"stage":"vision","label":"正在结合法规识别图片隐患","status":"running"}

event: trace
data: {"name":"第 1 轮法规检索","status":"done","summary":"执行 1 条检索问题,累计保留 12 条证据。"}

event: agent
data: {"event_id":"vision.final","kind":"final","status":"running","label":"正在生成最终回答"}

event: token
data: {"channel":"answer","text":"## 隐患等级\n重大事故隐患\n"}

event: final
data: {"ok":true,"mode":"agentic","answer":"...","citations":[2]}

事件说明:

事件 出现于 含义
progress 两种模式 阶段进度
token 两种模式 可追加到 UI 的片段,channel 为 answer 或 reasoning
trace 智能生成 流水线节点:图片接收、各轮检索、结论生成
agent 智能生成 agent 事件(观察、检索、重试、最终回答)的状态流转
answer_reset 两种模式 作废此前已发送的全部 answer 文本,随后重发
error 两种模式 业务或流式中断错误
final 两种模式 与非流式响应结构一致的完整结果

answer_reset 必须处理。智能生成会校验公开协议、引用与分类契约;自由生成会校验分类契约并最多纠正一次。校验不通过时服务重试,重试成功后重发正确答案;客户端需先清空已渲染的 answer 缓冲,再追加后续 token。忽略该事件将导致页面出现两份拼接在一起的回答。

其余语义与 /cg-rag/rag/stream 一致,详见 HTTP 参考 · SSE。以 final 作为最终状态来源;final 的 payload 与非流式响应结构相同。

MCP 工具

两种模式同样以 MCP 工具形式暴露,见 MCP 工具:

  • cg_vision_answer(images, question, enable_thinking)
  • cg_vision_agentic(images, question, scope, max_search_rounds, topk, enable_thinking)

MCP 返回完整 JSON envelope,不提供 token 流;如需逐字输出,请使用上述 HTTP 流式接口。

错误

错误码 HTTP 状态 含义
vision_not_configured 503 未设置 CG_RAG_VISION_ENDPOINT / CG_RAG_VISION_MODEL
invalid_image 400 图片数量超限、体积超限、base64 非法或媒体类型不受支持
invalid_request 400 请求体字段类型或范围不合法
vision_upstream_error 502 调用 VLM 失败
vision_response_invalid 502 VLM 未返回可用内容
capacity.exceeded 429 生成容量等待超时

示例:

{
  "request_id": "req_xxx",
  "error": {
    "code": "invalid_image",
    "message": "第 1 张图片为 20971520 字节,超过上限 16777216 字节。",
    "details": {}
  }
}

流式接口的响应头在生成开始前已发出,因此上述失败在流中表现为 event: error,HTTP 状态仍为 200。

集成建议

  • 先通过 /cg-rag/health 的 vision.configured 判断能力是否可用,再决定是否向用户开放入口。
  • 批量筛查使用自由生成,需要出具依据时再对命中项调用智能生成,以避免对每张图均付出多轮检索的开销。
  • 智能生成请显式传入 scope 和 topk,不应依赖默认值。
  • 视觉与文本生成共用同一个 generation 容量限制器,批量调用前请确认 capacity.generation 余量。
  • 图片体积直接影响上传耗时和 token 成本,建议调用方预先将长边压缩至 2048 以内再提交。

视觉版本(profile)

配置键 cg_rag.vision.profile(环境变量 CG_RAG_VISION_PROFILE)。未设置时,兼容旧键 CG_RAG_VISION_AGENTIC_WORKFLOW:continuous 解析为 e10,controller 解析为 controller。

profile 含义 适用 已知自动评测(是/(是+否),未识别不进分母)
e10(默认,当 workflow=continuous) continuous + 六分区观察清单 + publish/salvage + VLM 上游重试×4 生产;与线上 overlay 20260920T2235Z-e10-observe-inventory-cg 对齐 ≈48.5%(9-19~9-21)
continuous_base continuous 无观察清单;可关 strict_retrieval_failure 回退对照(9/16 原版思路) ≈43.5%(今日重跑)
controller main controller 工作流(含引用对齐与检索失败加固) 对照 / 非生产默认 ≈41.7%(9/17)
controller_wip 实验:垫板词表、二次观察、覆盖检索等 实验,不建议生产 d04 ≈45.4%

切换方式:修改 YAML cg_rag.vision.profile 或环境变量后重启 CG-RAG。回滚生产版本:将其设回 e10(或仅保留 CG_RAG_VISION_AGENTIC_WORKFLOW=continuous 且不设 profile)后重启。

与线上 overlay 的有意差异

  • strict_retrieval_failure 默认开启:检索传输全部失败时,在成文前拒绝请求(线上 e10 会先成文)。continuous_base 可关闭该选项。
  • 观察清单 phase 名为 inventory(线上曾用 observe,但当时 observe 无 JSON schema;现网 main 的 observe 会套 controller schema,故改名)。
  • 流式 VLM 仅在首个 token 前重试(避免半途重放重复字)。

健康检查会报告当前 profile 名与提示词 SHA。启动时预检 SHA 钉子(CG_RAG_STRICT_PROMPT_PINS=1 时不一致则拒绝启动)。

整单预算与心跳(P5)

  • cg_rag.vision.total_budget_seconds / CG_RAG_VISION_TOTAL_BUDGET_SECONDS:整单墙钟预算。e10 默认 150 秒(现网均时约 67s;外层 CG/问答超时 180s)。各阶段(观察、六分区清单、检索、成文纠正、上游重试)启动前均检查预算;预算耗尽时优先发布已通过校验的报告,否则返回 vision_budget_exceeded。
  • cg_rag.vision.sse_heartbeat_seconds / CG_RAG_VISION_SSE_HEARTBEAT_SECONDS:默认 15;设为 0 时关闭。长等待期间发送 SSE : keepalive(前端忽略注释行)及携带 heartbeat: true 的 progress 事件。

检索全失败(G6)

  • cg_rag.vision.strict_retrieval_failure / CG_RAG_VISION_STRICT_RETRIEVAL_FAILURE:为真时,传输全部失败在成文之前拒绝请求(retrieval.failed),不会先流出半篇报告。e10 默认开启;continuous_base 默认关闭,以回退至线上旧有的"先成文"行为。检索成功但返回 0 篇时继续成文,提示不得写条号,结果 evidence_status=none,模型若仍写条号将被清洗。