DeepStreamSOP推理微服务技能Skill "deepstream-sop"

该技能用于构建、部署、评估、调试和测量DeepStream SOP推理微服务——这是一个GPU加速的FastAPI服务,利用事件边界检测(GEBD)和视觉语言模型(VLM)来检测工业装配线操作员是否按标准操作流程(SOP)执行步骤,包括验证步骤顺序、检测缺失或乱序步骤、对工厂/工作单元视频进行合规性评分。支持文件、RTSP、Basler相机输入,提供SSE流式、Kafka输出、Prometheus指标、Docker部署、TensorRT优化、Chunk级延迟测量等功能。关键词:DeepStream, SOP, VLM, GEBD, DDM, Triton, FastAPI, 视频分析, 工业合规, 动作检测, 边界事件检测, vLLM, Cosmos Reason, Docker, Kafka, RTSP, 相机, GPU加速, 微服务。

视频分析平台 0 次安装 0 次浏览 更新于 9/6/2026
名称 “deepstream-sop”
描述 > 使用此技能用于构建、部署、评估、调试或测量 DeepStream SOP 推理微服务的延迟——这是一种 GPU 加速的 FastAPI 服务,通过事件边界检测 (GEBD) 和 VLM 分类来检测操作员是否按顺序执行装配线步骤。即使用户没有明确提及也会触发:验证操作员步骤顺序,检测缺失/乱序的 SOP 步骤,对工厂/工作单元视频进行程序合规性评分,在工业摄像头上运行基于 VLM 的 SOP 检查,或调用带有文件、RTSP 或 Basler 相机的 /v1/chat/completions。同样适用于其内部组件:SOPVideoProcessor、DeepStream GEBD 模型(例如 DDM)通过 Triton CAPI、nvds_custom_postprocess、Cosmos Reason 1/2 vLLM、SSE 流式、Kafka NvProto/JSON 输出、Basler/Pylon 相机 + 仿真、Docker compose、分块级延迟。请勿为通用 DeepStream 管线、目标检测/跟踪、NIM 导入或视频摘要触发。 owner: “windy@nvidia.com” service: “deepstream-sop”
版本 “1.0.0”
开源协议 “CC-BY-4.0 AND Apache-2.0” reviewed: “2026-04-08” metadata:
作者 “Wind Yuan windy@nvidia.com” tags: - deepstream - sop - vlm - triton - gpu languages: - python frameworks: - deepstream - triton - fastapi domain: video-analytics

DeepStream SOP 推理微服务技能

本技能用于指导 AI 编程助手构建、扩展和调试 NVIDIA DeepStream SOP(标准操作流程)推理微服务 —— 面向工业视频流的、基于 GPU 加速的时序动作检测与 VLM 驱动的 SOP 合规性监控管线。

参考仓库: https://github.com/NVIDIA/sop-monitoring-blueprints/tree/main/microservices/sop-inference-bp 本地参考代码: sop-inference-bp/ 目录(来自仓库的本地克隆)


模型

两个推理阶段均不依赖具体模型 —— 可通过环境变量(以及 GEBD 对应的 Triton 目录)进行替换。

阶段 作用 模型类型 默认值 替换方式
阶段 1 (CV) 逐帧边界评分 → 块划分 通用事件边界检测 (GEBD) DDMMCG-NJU/DDM)通过 Triton Python 后端 替换 triton_model_repo/<model>/DDM_MODEL_PATH(见 §5)
阶段 3 (VLM) 每个块的行动分类 基于 LLM 的视觉语言模型(vLLM 运行) Cosmos Reason 1 7B(同时支持 Reason 2) VLLM_MODEL_PATH 设置为不同的 HF ID 或本地路径

“GEBD”是可替换的阶段 1 槽;“DDM”是默认架构(术语可互换使用)。

分块方式在每个请求中可选择(见§2):默认 ddm-net 使用 GEBD;uniform 产生固定长度块,并 绕过阶段 1 的 GEBD(见§3、§6)。DDM 的时间窗口可通过 FRAMES_PER_SIDE / SEQUENCE_BATCH(见§4、§5)配置,并支持可选的 TensorRT(见§5)。


架构总览

在 Docker 容器(nvds-action-sop)中运行,并旁边运行 Kafka 容器。完整图示请见 references/sop_architecture.svg

数据流经 4 阶段 SOPVideoProcessor 管线(每个请求一个实例):

输入源                         Docker 容器: nvds-action-sop
─────────────                    ──────────────────────────────────────────────────
视频文件 ──┐                  FastAPI 服务器 (端口 8300)
RTSP 流 ─┤── base64/       ├─ /v1/chat/completions → SOPProcessManager
Basler 相机 ┘   file/rtsp/       │
                  camera           │ ModelInitializer: 先加载 VLM,再加载 DDM 哑管线
                                   │ 4 个线程池: cv(32), clip(32), vlm(64), vlm_req(64)
                                   │
                                   ▼ SOPVideoProcessor (每个请求一个实例)
                                   ┌────────────────────────────────────────────────┐
                                   │ 阶段 1: DeepStream 管线 (GPU)                  │
                                   │   源 → nvstreammux → tee1                    │
                                   │    ├─[推理] queue1 → nvdspreprocess           │
                                   │    │  → nvinferserver (Triton CAPI + DDM)     │
                                   │    │  → InferOutputTensorParser → score_queue │
                                   │    ├─[帧] queue3 → nvvideoconvert             │
                                   │    │  → capsfilter → appsink                  │
                                   │    │  → DecodedFrameRetriever → frame_queue    │
                                   │    └─[RTSP 输出] queue → convert → H.264 编码  │  (可选,见 §18)
                                   │       → rtppay → udpsink → RTSPServer (§18)   │  按需启用
                                   │              │ 边界分数                        │
                                   │              ▼                                 │
                                   │ 阶段 2: 剪辑后处理                           │
                                   │   边界检测 → 块划分                           │
                                   │              │ 视频帧 + 时间戳                    │
                                   │              ▼                                 │
                                   │ 阶段 3: VLM 推理                              │
                                   │   内嵌 vLLM (Cosmos Reason 1/2)               │
                                   │   以 VLM_FPS 进行帧采样 → 分类                 │
                                   │              │ 动作标签                         │
                                   │              ▼                                 │
                                   │ 阶段 4: SOP 校验器                           │
                                   │   顺序验证 → 缺少/错序检测                      │
                                   │              │ 块结果                           │
                                   │              ▼                                 │
                                   │         final_queue                           │
                                   └────────────────────────────────────────────────┘
                                          │
输出                                    ▼
──────                             ┌─────────────────┐
SSE 流 (chat.completion.chunk)      │ Kafka 消息       │
非流式 (chat.completion)            │ (JSON/Protobuf)  │
Prometheus 指标 (/v1/metrics)       └────────┬────────┘
                                            ▼
                                   Docker 容器: kafka
                                   (apache/kafka:3.7.0)

章节索引

每个章节都是 references/ 下的独立文件 —— 仅加载你的任务所需的章节。

§ 文件 职责
1 skill_01_fastapi_endpoints.md FastAPI 端点、服务器初始化、Prometheus 指标
2 skill_02_pydantic_schemas.md 请求/响应 Pydantic 模型(api_types.py
3 skill_03_deepstream_pipeline.md DeepStream pyservicemaker 管线、张量解析器、哑管线
4 skill_04_config_templates.md nvdspreprocess / nvinferserver 配置模板 + 渲染
5 skill_05_triton_ddm_model.md Triton 模型仓库、config.pbtxt、model.py、ddm_net.py
5b skill_05b_custom_postprocess.md C++ 后处理插件、Makefile、IOptions API
6 skill_06_sop_process_manager.md SOPProcessManager、SOPVideoProcessor、VLLMInference、Kafka
6b skill_06b_sop_checker.md SOP 顺序与校验合规:MissingNumberDetector、SopCheckerCache、SopCheckerRequest/Response
7 skill_07_sse_streaming.md SSE 生成器、流式响应格式、哑测试模式
8 skill_08_basler_camera.md Basler 相机支持、Pylon SDK、仿真、格式
9 skill_09_docker_build_deploy.md Docker 构建、部署、.env 配置
10 skill_10_test_suite.md 测试套件覆盖率、断言、运行测试
11 skill_11_env_variables.md 所有环境变量参考
12 skill_12_evaluation_workflow.md 端到端评估工作流:静态检查、构建、启动、测试、API/相机/Kafka 检查、报告
13 skill_13_verification_curl.md 验证步骤和 curl 示例
14 skill_14_implementation_checklist.md 实现清单:文件复制列表、生成文件、Docker 前置条件、验证
15 skill_15_latency_measurement.md 通过 SSE 流式测量文件输入的 TTFC 和 C2C 延迟
16 skill_16_message_schema.md Kafka 消息模式选择(默认 JSON vs NvProtoSchema)以及扩展自定义数据的消息
17 skill_17_camera_latency_measurement.md 相机/直播流的块级端到端延迟测量,使用内部管线时间戳
18 skill_18_rtsp_streaming_output.md 可选 RTSP 流式输出:tee1 分接头重流、RTSPStreamingServerSW_ENCODER 切换。仅当用户明确请求 RTSP 时才生成。

若要端到端评估,请先阅读 §12;然后根据需要加载构建/测试/curl/延迟/相机/Kafka 等章节。

§18 为可选 —— 仅当用户明确请求 RTSP 输出时生成;否则跳过 §18 及以下 RTSP_* 规则。


关键文件映射

完整的源文件到目标文件的映射表见 skill_14_implementation_checklist.md:

  • references/ 原样复制的文件(非平凡算法——循环检测、qwen_vl_utils 预处理、DeepStream IOptions API、protobuf 源码),并说明每个文件的理由。
  • 作为可适配模板复制的文件(Dockerfile、compose.yaml、Triton 配置和 model.pyddm_net.py、Pylon 仿真配置等)。
  • 由技能章节生成的文件 —— 每项都标注了必须精确遵循的下方关键规则。
  • Docker 构建前置条件和构建后验证清单。

配置文件(nvds_preprocess_template.txtnvds_inference_template.txtvlm_prompts.txt)是从 configs/ 按原样使用的。

当加载 skill_06b 时,从项目根目录读取 configs/actions.json,并按 §6b-G 生成工作流生成 nvds_action_detector/missing_number_detector.py。 如果 configs/actions.json 不存在或无效,则回退到复制参考文件。


关键规则

每条规则的完整详情位于所链接的 skill_NN_*.md 参考文件中。

标签 规则摘要 详情位置
MANAGER_INIT_IN_MAIN SOPProcessManagermain() 中初始化,需在 uvicorn.run() 之前 —— 不能在 lifespan() skill_01_fastapi_endpoints.md
NAMED_KWARGS create_video_processor() 使用命名关键字参数;相机参数作为单独关键字参数 skill_06_sop_process_manager.md
LIVE_REQUIRES_STREAM_TRUE 实时输入 (RTSP/相机) 必须 stream: true skill_08_basler_camera.md
VLM_DISABLED_DISABLES_SOP_CHECKER DISABLE_VLM_INFERENCE=true 在导入时自动禁用 SOP 校验器 skill_06_sop_process_manager.md
CHUNK_PARAMS_MAX_LENGTH ChunkParams.max_length_sec 内部为 10 秒;API 默认 60 秒 skill_06_sop_process_manager.md
VLM_WARMUP_BEFORE_DDM ModelInitializer: 先做 VLM 预热,再做 CV 哑管线 skill_06_sop_process_manager.md
VLM_WARMUP_3_FRAMES VLM 预热需要 3 帧(torch.zeros)—— Qwen3VL 在少于 3 帧时会挂起 skill_06_sop_process_manager.md
THREAD_POOL_SIZES 4 个线程池:cv(32)、clip(32)、vlm_inference(64)、vlm_request(64) skill_06_sop_process_manager.md
MEDIA_INFO_PYMEDIAINFO 媒体信息通过 pymediainfo;实时源直接设置 fps=30/duration=inf skill_06_sop_process_manager.md
CAMERA_EMULATION_PYLON_CAMEMU PYLON_CAMEMU=1 开启相机仿真(序列号 0815-0000 skill_08_basler_camera.md
DEEPSTREAM_LIB_HIDE DeepStream 库隐藏技巧:在 gst-plugin-pylon 构建期间将 lib 重命名为 lib.tmp skill_08_basler_camera.md
VLM_REAL_GPU_FRAMES VLM 使用通过 DecodedFrameRetriever 获取的真实 GPU 帧;推理时绝不使用 torch.zeros skill_06_sop_process_manager.md
BUFFER_RETRIEVER_STATIC_BASE DecodedFrameRetriever 必须静态继承 BufferRetriever,通过 super().__init__();运行时的 __class__.__bases__ 变更会导致 pipeline.attach() 挂起 skill_06_sop_process_manager.md
FRAME_RETRIEVER_PRIORITY create_inference_pipeline: frame_retriever= 关键字参数优先于 frame_queue skill_03_deepstream_pipeline.md
MUX_ORIGINAL_RESOLUTION nvstreammux 使用原始分辨率(不是 224);从 get_media_info() 传入 mux_width/mux_height(对非相机输入探测实时 RTSP;相机路径不受影响) skill_03_deepstream_pipeline.md, skill_06_sop_process_manager.md
FILE_URI_NO_DOUBLE_PREFIX create_inference_pipeline 文件源:在添加前缀前检查 file_path.startswith("file://") — API 直接传递 file:// URL skill_03_deepstream_pipeline.md
CLEANUP_ON_DISCONNECT 客户端断开时管线清理,通过 trigger_stop_processorstry/finally 中实现 skill_07_sse_streaming.md
UNIFIED_CLIP_POST_PROCESS 文件和实时输入共用 clip_post_process()stop()_score_queue 放入 None skill_06_sop_process_manager.md
ABORT_INFLIGHT_VLM stop() 时通过 llm.abort(req_id) 中止进行中的 VLM 请求 skill_06_sop_process_manager.md
LOGGER_EXPORT_GET_LOGGER ds_logger.py 必须导出 get_logger skill_06_sop_process_manager.md
KAFKA_USE_CREATE_PRODUCER Kafka:使用来自 messager.pycreate_producer();没有 Messager skill_06_sop_process_manager.md
USER_PROMPT_PRIORITY 用户请求文本优先于 VLM_PROMPT_PATH 文件;请求中的 {"type":"text"} 覆盖配置文件中的提示词 skill_06_sop_process_manager.md
EVAL_USE_CONFIG_PROMPT 评估/延迟请求默认省略请求文本,使 VLM 使用 VLM_PROMPT_PATH skill_12_evaluation_workflow.md, skill_13_verification_curl.md, skill_15_latency_measurement.md, skill_17_camera_latency_measurement.md
CHUNK_SCHEMA_FIELD_NAMES 块模式:chunk_idxcv_boundary_scorechecker_result;摘要 chunk_idx=-1 skill_06_sop_process_manager.md
SEQUENTIAL_FRAME_DRAIN 在单个线程中按顺序排空 decoded_frame_queue(FIFO,跨块共享)并逐个提交 VLM;并行排空会偷帧 → 导致 0 帧块或错误的 VLM 输入 skill_06_sop_process_manager.md
WALL_CLOCK_BEFORE_GPU DecodedFrameRetriever.consume(): 在 GPU dlpack 之前捕获 wall_clock_entry = time.time();将 3 元组 (timestamp, wall_clock_entry, tensor) 放入队列 skill_06_sop_process_manager.md, skill_17_camera_latency_measurement.md
CHUNK_E2E_PIPELINE_TIMESTAMPS pipeline_chunk_end_timestamp(最后一帧的墙钟时间)和 pipeline_vlm_ready_timestamptm_e2e.now())写入 chunk_info 用于相机延迟测量(§17) skill_06_sop_process_manager.md, skill_17_camera_latency_measurement.md
VLM_INFERENCE_REQUIRED_KWARGS 每次 VLLMInference.inference() 调用必须传递 video_fpssystem_promptmax_completion_tokens skill_06_sop_process_manager.md
UNIFORM_CHUNKING_BYPASSES_DDM chunking_options.algorithm="uniform" → 固定长度块;create_inference_pipeline(uniform_chunk=True) 跳过 DDM 但保留 tee1 分叉;阶段 2 使用 uniform_clip_post_process skill_02_pydantic_schemas.md, skill_03_deepstream_pipeline.md, skill_06_sop_process_manager.md
DDM_TEMPORAL_CONFIGURABLE SLIDING_WINDOWS_SIZE = 2*FRAMES_PER_SIDE + SEQUENCE_BATCH 渲染进 preprocess/nvinferserver(没有硬编码 18);Triton config.pbtxt 序列维度为 -1 skill_04_config_templates.md, skill_05_triton_ddm_model.md
DDM_TRT_OPTIONAL_PATH DDM_TRT_OPTIMIZATION=true 通过 TensorRT 运行 DDM(每线程上下文,固定 batch = SEQUENCE_BATCH);否则使用 PyTorch;两者不会同时启用。PyTorch 是默认配置 skill_05_triton_ddm_model.md
DDM_TRT_STREAM_ORDERING DDMTensorRTEngine.infer(): wait_stream(current)execute_async_v3torch.cuda.synchronize(device)(不是每流同步)。每流同步会使 TRT 辅助流的工作尚未完成 → 导致 gst-CV SIGSEGV(NVBug 6289256) skill_05_triton_ddm_model.md
METADATA_LICENSE_FROM_FILE /v1/metadataDS_SOP_LICENSE_PATH(默认 /opt/nvidia/nvds_sop/license.txt)读取 licenseInfo;绝不硬编码许可证文本 skill_01_fastapi_endpoints.md
CAMERA_EMULATION_FRAMES_RGB Pylon 仿真 PNG 必须为显式 3 通道 RGB(与 Emulation_0815-0000.pfs PixelFormat=RGB8Packed 匹配);通过 nvvideoconvert ! videoconvert ! "video/x-raw,format=RGB" ! pngenc 生成 skill_08_basler_camera.md
COMPOSE_ENV_PASSTHROUGH docker compose 只替换 ${VAR} 引用;每个运行时环境变量必须显式列在 environment: 下才能进入容器 skill_09_docker_build_deploy.md

下面四个 RTSP_* 规则仅在使用可选 RTSP 流式输出功能(§18)时适用。不要用于默认构建 —— 如果用户没有要求 RTSP 输出,请跳过这些规则。

| RTSP_OUTPUT_TAPS_TEE1 | 仅当存在 rtsp_port 时,RTSP 输出分支才从现有 tee1(在主推理链路之后添加的)连接。 | skill_18_rtsp_streaming_output.md | | RTSP_LEAKY_QUEUE_TINY | RTSP 分支队列必须为 leaky=2 + 极小容量(max-size-buffers=2),以防止背压和 NVMM 池耗尽。 | skill_18_rtsp_streaming_output.md | | RTSP_KEYINT_MAX_30 | RTSP H.264 编码器必须设置 key-int-max=30(并禁用 B 帧),以允许下游 seek。 | skill_18_rtsp_streaming_output.md | | RTSP_ENCODER_FALLBACK | 根据 SW_ENCODER 选择软件/硬件 H.264 编码器,并提供 MJPEG 回退。 | skill_18_rtsp_streaming_output.md |