HTTP API¶
本文描述 CG_RAG 当前对外暴露的 HTTP API。示例默认服务地址为:
如通过代理或网关访问,请把示例中的主机和端口替换为实际入口。
核心约定¶
- CG_RAG 编排不包含 domain gate。
retrieve-rerank只返回候选文档,不调用 LLM。constrained-generate只基于调用方传入的候选文档做受约束生成。rag和answer会串联 retrieve、rerank、constrained generation;answer是当前 HTTP 兼容别名。rag/stream会以 SSE 返回完整 RAG 流程事件,适合前端动态吐字。vision/*接收 base64 图片并返回隐患报告;自由生成不检索、不带引用,智能生成自行检索并带[cite^n]引用。字段与示例见视觉隐患识别。- 视觉接口需要单独配置多模态上游(
CG_RAG_VISION_*);未配置时只影响vision/*,检索与文本生成不受影响。 - 可用
scope为full、usual、usual_plus_law。自动化调用建议显式传入目标scope。 topk会被限制在1..200,max_items会被限制在1..20。include_debug和generation_enable_thinking必须是 JSON boolean;"true"、1、0等字符串或数字会被判为无效请求。- 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、
topk和profile_fingerprint;索引、语料、embedding/rerank 配置变化后不会误命中旧缓存。 - retriever manager 同时只保留一个 active profile。
warmup会顺序加载 scopes,但最终只保留最后一个 active scope。 - retrieval 与 generation 使用独立容量限制器。非流式请求等待超时返回 HTTP
429和capacity.exceeded;/rag/stream响应开始后的容量错误通过 SSEerror+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_docs、cache.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 | ok、final_active_scope |
POST |
/cg-rag/vision/answer |
图片隐患识别(自由生成,不检索) | ok |
POST |
/cg-rag/vision/answer/stream |
自由生成的 SSE 版本 | final.ok |
POST |
/cg-rag/vision/observe |
结构化视觉观察,返回校验过的隐患标签 | ok、parse_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¶
请求:
示例输出,已删减:
{
"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 只暴露主机名,不暴露完整地址和密钥。
健康检查中的 retriever、profile_fingerprint、retrieve_cache 和 hydration 用于排查远端性能问题:先看 active scope 是否符合预期,再看当前 fingerprint 是否随索引/模型配置变化,再看缓存命中和 hydration lookup 是否异常。
GET /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.hit 为 true,响应会保留当前 pipeline,并额外带 cached_pipeline 记录缓存写入时的原始 pipeline 摘要。缓存 key 包含 normalized scope、去首尾空白后的 query、topk 和 profile_fingerprint。profile_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_request、capacity.exceeded、service_error、generation_not_configured、generation_response_invalid 和 no_stable_article。
视觉接口另有 vision_not_configured(503)、invalid_image(400)、vision_upstream_error 与 vision_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。
{
"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 完全相同的检索与重排,差别只在请求校验和响应形状:
- 请求按历史语义处理,不做严格校验;
topk、scope缺省时回落到服务启动参数,而不是 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:协议重试后服务会重发答案,忽略该事件会渲染出两份拼接的回答。 - 生产调用建议显式传
scope、topk和max_items,避免默认值变化影响结果。 - thinking 建议默认由服务配置控制;只在单次问题需要更强推理时传
generation_enable_thinking: true。 - 调试时短期开启
include_debug: true;常规服务调用保持默认false,减少响应体和敏感配置暴露。