跳转至

HTTP API

本文描述 CG_RAG 当前对外暴露的 HTTP API。示例默认服务地址为:

http://127.0.0.1:8864

如通过代理或网关访问,请把示例中的主机和端口替换为实际入口。

核心约定

  • CG_RAG 编排不包含 domain gate。
  • retrieve-rerank 只返回候选文档,不调用 LLM。
  • constrained-generate 只基于调用方传入的候选文档做受约束生成。
  • raganswer 会串联 retrieve、rerank、constrained generation;answer 是当前 HTTP 兼容别名。
  • rag/stream 会以 SSE 返回完整 RAG 流程事件,适合前端动态吐字。
  • vision/* 接收 base64 图片并返回隐患报告;自由生成不检索、不带引用,智能生成自行检索并带 [cite^n] 引用。字段与示例见视觉隐患识别
  • 视觉接口需要单独配置多模态上游(CG_RAG_VISION_*);未配置时只影响 vision/*,检索与文本生成不受影响。
  • 可用 scopefullusualusual_plus_law。自动化调用建议显式传入目标 scope
  • topk 会被限制在 1..200max_items 会被限制在 1..20
  • include_debuggeneration_enable_thinking 必须是 JSON boolean;"true"10 等字符串或数字会被判为无效请求。
  • constrained generation 默认返回 compact 输出;只有 include_debug: true 时才返回调试字段。
  • generation thinking 可由服务级配置控制,也可在单次 constrained-generate / rag 请求中用 generation_enable_thinking 覆盖。
  • DeepSeek provider 使用 thinking: {"type": "enabled"|"disabled"};Poly / OpenAI-compatible provider 仅在启用 thinking 时注入 chat_template_kwargs: {"enable_thinking": true}
  • retrieve-rerank 缓存只覆盖检索和重排结果,不缓存 LLM generation。
  • retrieve-rerank 缓存 key 包含 normalized scope、query、topkprofile_fingerprint;索引、语料、embedding/rerank 配置变化后不会误命中旧缓存。
  • retriever manager 同时只保留一个 active profile。warmup 会顺序加载 scopes,但最终只保留最后一个 active scope。
  • retrieval 与 generation 使用独立容量限制器。非流式请求等待超时返回 HTTP 429capacity.exceeded/rag/stream 响应开始后的容量错误通过 SSE error + final 表达,HTTP 状态仍为 200

接口总览

方法 路径 用途 业务状态字段
GET /cg-rag/health 服务健康、profile、rerank 和 LLM 配置摘要 ok
GET /cg-rag/profiles 列出可用检索范围 裸 profile map
POST /cg-rag/retrieve-rerank 只执行 retrieve + rerank num_docscache.hit
POST /cg-rag/constrained-generate 对调用方传入的候选文档做受约束生成 ok
POST /cg-rag/rag 完整 retrieve + rerank + constrained generation generation.ok
POST /cg-rag/rag/stream 完整 RAG 的 SSE 流式版本 final.generation.ok
POST /cg-rag/answer /cg-rag/rag 的兼容别名 generation.ok
POST /cg-rag/warmup 加载一个或多个检索 scope okfinal_active_scope
POST /cg-rag/vision/answer 图片隐患识别(自由生成,不检索) ok
POST /cg-rag/vision/answer/stream 自由生成的 SSE 版本 final.ok
POST /cg-rag/vision/observe 结构化视觉观察,返回校验过的隐患标签 okparse_status
POST /cg-rag/vision/agentic 图片隐患识别(智能生成,自行检索并引用) ok
POST /cg-rag/vision/agentic/stream 智能生成的 SSE 版本 final.ok
GET /healthz 进程存活探针(兼容路由) ok
POST /retrieve FlashRAG 风格检索(兼容路由) num_docs

HTTP 响应会带 X-Request-ID header。调用方传入合法 X-Request-ID 时服务会回传该值;未传入时服务会生成 req_*。多数 JSON body 也会包含 request_id,但 /cg-rag/profiles 成功响应保持裸 profile map。

GET /cg-rag/health

请求:

curl --noproxy '*' -sS \
  -H 'X-Request-ID: req-doc-health' \
  http://127.0.0.1:8864/cg-rag/health

示例输出,已删减:

{
  "ok": true,
  "request_id": "req-doc-health",
  "service": "CG_RAG",
  "http_prefix": "/cg-rag",
  "mcp_path": "/cg-rag/mcp",
  "available_scopes": ["full", "usual", "usual_plus_law"],
  "default_scope": "full",
  "active_scope": "full",
  "config_issues": [],
  "generation": {
    "configured": true,
    "provider": "deepseek",
    "endpoint_configured": true,
    "endpoint_host": "<GENERATION_ENDPOINT_HOST>",
    "model": "deepseek-v4-flash",
    "response_format_json": true,
    "enable_thinking": false,
    "streaming": true,
    "stream_answer_token_delay_seconds": 0.025,
    "timeout_seconds": 180.0,
    "max_context_docs": 78,
    "default_max_items": 10
  },
  "vision": {
    "configured": true,
    "endpoint_configured": true,
    "endpoint_host": "<VISION_ENDPOINT_HOST>",
    "model": "<vlm-model>",
    "enable_thinking": false,
    "streaming": true,
    "max_images": 4,
    "max_image_bytes": 8388608,
    "max_tokens": 4096,
    "agentic_max_search_rounds": 3,
    "agentic_retrieval_topk": 12
  },
  "rerank": {
    "api_enabled": true,
    "model": "qwen-rerank"
  },
  "retriever": {
    "active_scope": "full",
    "resident_scopes": ["full"],
    "load_count": 1,
    "last_load_time_ms": 54759.2,
    "last_loaded_scope": "full"
  },
  "profile_fingerprint": {
    "id": "3f4c6b7a8d9e0123",
    "summary": {
      "scope": "full",
      "retrieval_method": "qwen3-0.6b",
      "index_file_name": "full.index",
      "embedding_api": {
        "configured": true,
        "model": "qwen3-embedding",
        "dimension": 2560
      },
      "rerank": {
        "backend": "api",
        "api_configured": true,
        "model": "qwen-rerank"
      }
    }
  },
  "retrieve_cache": {
    "entries": 2,
    "hits": 1,
    "misses": 2,
    "max_entries": 128,
    "ttl_seconds": 300.0
  },
  "hydration": {
    "path": ".../cg_rag_hydration.sqlite3",
    "indexed_corpora": 7,
    "lookup_hits": 57,
    "lookup_misses": 0,
    "lookup_failures": 0,
    "last_error": "",
    "build_count": 7
  },
  "capacity": {
    "retrieval": {"resource":"retrieval","max":16,"active":0,"queued":0,"rejected":0,"peak":2,"wait_timeout_seconds":5.0},
    "generation": {"resource":"generation","max":16,"active":0,"queued":0,"rejected":0,"peak":1,"wait_timeout_seconds":5.0}
  }
}

config_issues 非空时表示服务可启动,但部分能力可能不可用。例如 generation endpoint 或 model 未配置时,retrieve-rerank 仍可用,constrained generation 会返回业务错误。

vision.configured 用于能力发现:为 false/cg-rag/vision/* 会返回 vision_not_configured,调用方应据此决定是否开放相关入口。endpoint_host 只暴露主机名,不暴露完整地址和密钥。

健康检查中的 retrieverprofile_fingerprintretrieve_cachehydration 用于排查远端性能问题:先看 active scope 是否符合预期,再看当前 fingerprint 是否随索引/模型配置变化,再看缓存命中和 hydration lookup 是否异常。

GET /cg-rag/profiles

请求:

curl --noproxy '*' -sS http://127.0.0.1:8864/cg-rag/profiles

示例输出,已删减:

{
  "full": {
    "label": "全库",
    "retrieval_method": "qwen3-0.6b"
  },
  "usual": {
    "label": "常用规范",
    "retrieval_method": "qwen3-0.6b"
  },
  "usual_plus_law": {
    "label": "常用规范+常用法律",
    "retrieval_method": "qwen3-0.6b"
  }
}

POST /cg-rag/retrieve-rerank

请求字段:

字段 类型 必填 默认 说明
query string 用户问题;会去除首尾空白,不能为空
scope string usual 检索范围;建议显式传入
topk integer 78 返回候选数,范围 1..200

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/retrieve-rerank \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-doc-retrieve' \
  -d '{"query":"脚手架验收需要检查哪些条文?","scope":"full","topk":2}'

示例输出,已删减:

{
  "query": "脚手架验收需要检查哪些条文?",
  "request_id": "req-doc-retrieve",
  "num_docs": 2,
  "topk": 2,
  "profile_fingerprint": "3f4c6b7a8d9e0123",
  "profile_fingerprint_summary": {
    "scope": "full",
    "retrieval_method": "qwen3-0.6b",
    "embedding_api": {
      "configured": true,
      "model": "qwen3-embedding",
      "dimension": 2560
    },
    "rerank": {
      "backend": "api",
      "api_configured": true,
      "model": "qwen-rerank"
    }
  },
  "cache": {
    "hit": false,
    "entries": 1,
    "hits": 0,
    "misses": 1,
    "max_entries": 128,
    "ttl_seconds": 300.0
  },
  "pipeline": {
    "requested_scope": "full",
    "active_scope": "full",
    "scope_switched": false,
    "profile_fingerprint": "3f4c6b7a8d9e0123",
    "rerank_enabled": true,
    "api_rerank_enabled": false,
    "rerank_backend": "transformers",
    "retrieval_time_ms": 126.4,
    "rerank_time_ms": 44.8,
    "search_total_time_ms": 178.2
  },
  "retrieval_docs": [
    {
      "law_name": "JGJ166-2016建筑施工碗扣式钢管脚手架安全技术规范",
      "article_number": "9.0.8(4)",
      "contents": "脚手架验收合格投入使用后,在使用过程中应定期检查,检查项目应符合下列规定:4 架体应无超载使用情况。"
    },
    {
      "law_name": "GB55023-2022施工脚手架通用规范",
      "article_number": "6.0.5(1)",
      "contents": "脚手架搭设达到设计高度或安装就位后,应进行验收,验收不合格的,不得使用。"
    }
  ]
}

缓存命中时 cache.hittrue,响应会保留当前 pipeline,并额外带 cached_pipeline 记录缓存写入时的原始 pipeline 摘要。缓存 key 包含 normalized scope、去首尾空白后的 query、topkprofile_fingerprintprofile_fingerprint_summary 只暴露脱敏后的路径文件名、存在性、mtime/size、embedding/rerank 配置摘要,不暴露完整本地路径。

POST /cg-rag/constrained-generate

请求字段:

字段 类型 必填 默认 说明
query string 用户问题
retrieval_docs array 候选文档,通常来自 /cg-rag/retrieve-rerank
max_items integer 10 最多返回条文数,范围 1..20
include_debug boolean false 是否返回调试字段
generation_enable_thinking boolean/null null 单次请求是否开启 thinking;null 表示使用服务配置

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/constrained-generate \
  -H 'Content-Type: application/json' \
  -d '{
    "query":"脚手架验收需要检查哪些条文?",
    "max_items":2,
    "include_debug":false,
    "retrieval_docs":[
      {
        "law_name":"GB55023-2022施工脚手架通用规范",
        "article_number":"6.0.5(1)",
        "contents":"脚手架搭设达到设计高度或安装就位后,应进行验收,验收不合格的,不得使用。"
      }
    ]
  }'

示例输出,已删减:

{
  "ok": true,
  "generation_mode": "constrained",
  "answer_text": "我根据在线检索与候选筛选结果,整理出以下最相关条文:\n1. GB55023-2022施工脚手架通用规范 6.0.5(1)",
  "pred_indices": [1],
  "pred_items": [
    "GB55023-2022施工脚手架通用规范 6.0.5(1)"
  ],
  "pred_raw": "{\"indices\":[1]}",
  "thinking": "",
  "generation_enable_thinking": false,
  "usage": {
    "prompt_tokens": 1200,
    "completion_tokens": 8,
    "total_tokens": 1208
  }
}

POST /cg-rag/rag

请求字段:

字段 类型 必填 默认 说明
query string 用户问题
scope string usual 检索范围;建议显式传入
topk integer 78 检索候选数,范围 1..200
max_items integer 10 最多返回条文数,范围 1..20
include_debug boolean false 是否在 generation 中返回调试字段
generation_enable_thinking boolean/null null 单次请求是否开启 thinking;null 表示使用服务配置

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/rag \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-doc-rag' \
  -d '{"query":"脚手架验收需要检查哪些条文?","scope":"full","topk":20,"max_items":5}'

示例输出,已删减:

{
  "query": "脚手架验收需要检查哪些条文?",
  "request_id": "req-doc-rag",
  "retrieval": {
    "query": "脚手架验收需要检查哪些条文?",
    "num_docs": 20,
    "topk": 20,
    "profile_fingerprint": "3f4c6b7a8d9e0123",
    "cache": {
      "hit": false
    },
    "pipeline": {
      "active_scope": "full",
      "rerank_enabled": true
    },
    "retrieval_docs": [
      {
        "law_name": "GB55023-2022施工脚手架通用规范",
        "article_number": "6.0.5(1)",
        "contents": "脚手架搭设达到设计高度或安装就位后,应进行验收,验收不合格的,不得使用。"
      }
    ]
  },
  "generation": {
    "ok": true,
    "generation_mode": "constrained",
    "answer_text": "我根据在线检索与候选筛选结果,整理出以下最相关条文:\n1. GB55023-2022施工脚手架通用规范 6.0.5(1)",
    "pred_indices": [1],
    "pred_items": [
      "GB55023-2022施工脚手架通用规范 6.0.5(1)"
    ],
    "pred_raw": "{\"indices\":[1]}",
    "thinking": "",
    "generation_enable_thinking": false,
    "usage": {
      "total_tokens": 1208
    }
  }
}

POST /cg-rag/rag/stream

/cg-rag/rag/stream/cg-rag/rag 使用相同请求字段,但响应类型为 text/event-stream。服务会先发检索进度和检索结果,再按块发最终回答 token,最后发完整 final payload。

请求:

curl --noproxy '*' -N \
  -X POST http://127.0.0.1:8864/cg-rag/rag/stream \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-doc-rag-stream' \
  -d '{"query":"脚手架验收需要检查哪些条文?","scope":"full","topk":20,"max_items":5}'

事件序列示例,已删减:

event: progress
data: {"stage":"retrieval","label":"正在检索","status":"running","request_id":"req-doc-rag-stream"}

event: retrieval
data: {"query":"脚手架验收需要检查哪些条文?","num_docs":20,"cache":{"hit":false},"request_id":"req-doc-rag-stream"}

event: progress
data: {"stage":"generation","label":"正在生成","status":"running","request_id":"req-doc-rag-stream"}

event: token
data: {"channel":"answer","text":"我根据在线检索与候选筛选结果,整理出以下最相关条文:\n","request_id":"req-doc-rag-stream"}

event: token
data: {"channel":"answer","text":"1. GB55023-2022施工脚手架通用规范 6.0.5(1)","request_id":"req-doc-rag-stream"}

event: final
data: {"query":"脚手架验收需要检查哪些条文?","retrieval":{},"generation":{"ok":true,"answer_text":"..."},"request_id":"req-doc-rag-stream"}

事件说明:

事件 含义
progress 阶段进度,例如检索中、生成中、生成完成
retrieval 完整 retrieve-rerank 结果
token 可直接追加到 UI 的答案片段,channel 当前为 answer
error 业务或流式中断错误;出现后仍可能继续发送 final
final /cg-rag/rag 结构一致的完整最终结果

POST /cg-rag/answer

/cg-rag/answer 当前等价于 /cg-rag/rag,请求字段和响应结构一致。新集成建议优先使用 /cg-rag/rag,需要保留 answer 命名时再使用该别名。

POST /cg-rag/warmup

请求字段:

字段 类型 必填 默认 说明
scopes array of string 所有可用 scopes 要顺序加载的 scope 列表

请求:

curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/cg-rag/warmup \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-doc-warmup' \
  -d '{"scopes":["full"]}'

示例输出:

{
  "ok": true,
  "request_id": "req-doc-warmup",
  "requested_scopes": ["full"],
  "warmed_scopes": ["full"],
  "final_active_scope": "full",
  "warmed": [
    {
      "requested_scope": "full",
      "normalized_scope": "full",
      "active_scope": "full",
      "warmed": true,
      "resident": true,
      "scope_switched": false
    }
  ]
}

warmup 是顺序加载,不是多 profile 常驻。传入多个 scope 时,只有最后一个 scope 会成为最终 resident scope。

错误和业务失败

CG_RAG HTTP 路由使用稳定业务错误码,例如 invalid_requestcapacity.exceededservice_errorgeneration_not_configuredgeneration_response_invalidno_stable_article

视觉接口另有 vision_not_configured503)、invalid_image400)、vision_upstream_errorvision_response_invalid(均 502)。这些都是调用方可处理的失败,不会被包装成 HTTP 500,完整说明见视觉隐患识别

HTTP 请求体验证失败返回 HTTP 400:

{
  "request_id": "req_xxx",
  "error": {
    "code": "invalid_request",
    "message": "请求参数无效,请检查字段类型、范围和必填项。",
    "details": {
      "errors": [
        {
          "loc": ["include_debug"],
          "message": "Input should be a valid boolean",
          "type": "bool_type"
        }
      ]
    }
  }
}

非预期服务异常返回 HTTP 500:

{
  "request_id": "req_xxx",
  "error": {
    "code": "service_error",
    "message": "检索服务调用失败,请稍后重试或检查服务日志。",
    "details": {}
  }
}

非流式请求的容量等待超时返回 HTTP 429。错误详情只包含 limiter 名称、容量和等待时间,不包含 query 或候选正文:

{
  "request_id": "req_xxx",
  "error": {
    "code": "capacity.exceeded",
    "category": "capacity",
    "retryable": true,
    "message": "服务当前请求过多,请稍后重试。",
    "details": {
      "resource": "generation",
      "max": 16,
      "wait_timeout_seconds": 5.0
    }
  }
}

/rag/stream 的 limiter 在事件迭代期间取得;此时响应 header 已发送,因此容量耗尽不会改写为 429,而是保持 HTTP 200,发送 error 后再发送带相同错误的 final

生成接口未配置属于业务失败,不是 HTTP 500。/cg-rag/constrained-generate 示例:

{
  "ok": false,
  "error": {
    "code": "generation_not_configured",
    "message": "检索服务生成接口未配置,请检查服务配置。",
    "details": {}
  },
  "pred_indices": [],
  "pred_items": [],
  "pred_raw": ""
}

完整 RAG 没有稳定候选时,/cg-rag/rag/cg-rag/answer 不会把空候选传给 constrained generation,也不会返回 HTTP 500;它们会返回 generation.ok: false

{
  "query": "一个没有稳定命中的问题",
  "retrieval": {
    "num_docs": 0,
    "retrieval_docs": []
  },
  "generation": {
    "ok": false,
    "error": {
      "code": "no_stable_article",
      "message": "当前在线候选中未稳定选出明确条文。",
      "details": {}
    },
    "pred_indices": [],
    "pred_items": [],
    "pred_raw": ""
  }
}

兼容路由

/cg-rag/* 之外,服务还保留两个不带前缀的历史路由。它们是给既有的 FlashRAG 调用方用的,新接入不要使用。

GET /healthz

进程级存活探针,返回当前 active profile 的设备、索引与 scope 摘要。它反映生成或视觉配置是否就绪——负载均衡的存活检查可以用它,判断服务能不能干活要用 /cg-rag/health

curl --noproxy '*' -sS http://127.0.0.1:8864/healthz
{
  "ok": true,
  "device": "cpu",
  "store_topk": 78,
  "available_scopes": ["full", "usual", "usual_plus_law"],
  "default_scope": "full",
  "active_scope": "usual",
  "retrieval_method": "qwen3-0.6b"
}

POST /retrieve

FlashRAG 风格的检索路由。底层走的是和 /cg-rag/retrieve-rerank 完全相同的检索与重排,差别只在请求校验和响应形状:

  • 请求按历史语义处理,不做严格校验;topkscope 缺省时回落到服务启动参数,而不是 CG_RAG 的默认值。
  • 响应不含 cache 字段(缓存本身仍然生效),并额外带一个 pipeline.requested_scope,回显调用方原始传入的 scope。
curl --noproxy '*' -sS \
  -X POST http://127.0.0.1:8864/retrieve \
  -H 'Content-Type: application/json' \
  -d '{"query":"脚手架验收","topk":5,"scope":"usual"}'

新接入一律用 /cg-rag/retrieve-rerank:它有严格的请求校验、明确的默认值,并且会返回缓存命中信息。

集成建议

  • 调用 retrieve-only 场景时优先使用 /cg-rag/retrieve-rerank,不要调用完整 RAG 后丢弃 generation。
  • 调用完整 RAG 时优先检查 generation.ok,不要只看 HTTP 状态码。
  • 前端或 agent 需要动态吐字时使用 /cg-rag/rag/stream/cg-rag/vision/*/stream,并以 final 事件作为最终状态来源。
  • 消费视觉智能生成的流时必须处理 answer_reset:协议重试后服务会重发答案,忽略该事件会渲染出两份拼接的回答。
  • 生产调用建议显式传 scopetopkmax_items,避免默认值变化影响结果。
  • thinking 建议默认由服务配置控制;只在单次问题需要更强推理时传 generation_enable_thinking: true
  • 调试时短期开启 include_debug: true;常规服务调用保持默认 false,减少响应体和敏感配置暴露。