# 交接文档:Video Deep Research 视频优质度判别 Demo > 负责人:高振坤(zhenkun / zhenkungao) > 文档用途:说明本 demo 的功能、运行环境、运行方式、配置与密钥、排错与待办,便于他人接手 / 迁移到新服务器 / 后续网页化。 > 代码当前位置:`/home/tione/notebook/gaozhenkun/demo/video_deep_research_demo/` > 本目录已**自包含全部源码**,可整目录拷贝/建 git 后迁移。 --- ## 一、这个 Demo 做什么 给定一个 **YouTube 视频链接**,自动判别该视频是否为「优质素材」(当前业务口径:是否含可抽取的**高颜值男女(帅哥/美女)素材**),输出结构化判定(`approve` / `reject` / `undecided`)+ 推理轨迹。 核心方法是 **Video Deep Research**:让一个 VLM(视频多模态大模型)以「多轮工具调用」的方式自己去研究视频——抽帧、锁定关键帧、放大、反向图搜、网页文搜,最后给出判定。 判别逻辑**不是**简单分类,而是:模型在每一轮自行决定调用 5 个工具中的哪一个,最终在 `` 里输出 JSON 判定,由脚本解析(`parse_answer_json`),**本链路没有独立的 LLM-as-judge 打分环节**(judge/summarizer 只在 `image_search` 摘要里用到)。 ### 5 个工具(Video Deep Research 工具集) | 工具 | 作用 | |------|------| | `choose_frames` | 选定一个时间/帧区间,返回均匀采样的若干帧 | | `find_frame` | 锁定单个具体帧,细看 | | `zoom_in` | 放大锁定帧的某个 bbox 区域 | | `image_search` | 对锁定帧的某个区域做反向图搜(识别未知实体) | | `web_search` | 文本网页搜索(已知实体,查外部知识)。本 demo 走 **Tavily** 公网搜索 | > 工具定义在 `inference/attractive_leads_prompt.py` 的 `_TOOLS_BLOCK`,与训练侧 `config/tool_config/tools_video_train.yaml` 的 5 个工具一一对应(名称/参数/required 一致)。bbox 文案一处是 0–1000、一处是 0.0–1.0,运行时自动识别坐标制式,无影响。 --- ## 二、整体流程(脚本 `run_people_online_tavily.sh` 做了什么) ``` YouTube URL │ ├─[第1步 抓取] inference/fetch_youtube_online.py │ yt-dlp 下载 mp4 + info.json(含评论) → 规范化 comments.json / metadata.json │ 以 ---FETCH--- KEY=VALUE ---END--- 块把 VIDEO_ID/VIDEO_PATH/COMMENTS_FILE/... 回传 shell │ ├─[第2步 推理] inference/run_people_quality_inference.py (单条模式) │ 调用 eval.py::evaluate_video_tool() 跑「5 工具多轮」推理 │ ├─ 每轮请求外部 VLM 服务 (MODEL_BASE_URL, OpenAI 兼容) │ ├─ web_search → Tavily (公网) │ └─ image_search → 内网 gateway/Serper + summarizer (可选) │ └─ 产出:判定 JSON + HTML 轨迹 + 决策表 CSV + 帧图 ``` - **demo 本机不需要 GPU**:它是「客户端」,模型在外部 `MODEL_BASE_URL` 上已部署。 - 两步之间用「临时文件 + KEY=VALUE 文本块」中转,不是函数直调(后续网页化时这里要改成 Python API)。 --- ## 三、运行环境 ### 1. 机器 / 硬件 - 无需 GPU(模型在远端服务上)。普通 CPU 机器即可。 - 需能访问:① 外部 VLM 推理服务;② 公网(yt-dlp 拉 YouTube、Tavily 搜索);③(可选)内网图搜 gateway / MARS summarizer。 ### 2. 系统依赖 - **ffmpeg**(必需,yt-dlp 合并 mp4 用,要在 PATH)。 - **yt-dlp**(pip 或系统包;脚本会在 `CONDA_ENV/bin`、`CONDA_BASE/bin`、PATH 里自动探测,也可用 `YT_DLP` 指定)。 - **playwright + chromium**:`eval.py` 顶层 `import playwright`,必须装浏览器内核,否则 import 直接失败。 ### 3. Python 环境 当前本地环境:conda env `/home/tione/notebook/gaozhenkun/envs/sglang`。 新机器自建: ```bash /home/tione/notebook/gaozhenkun/envs/sglang/bin/python -m pip install -r requirements.txt PLAYWRIGHT_BROWSERS_PATH=$PWD/.playwright-browsers \ /home/tione/notebook/gaozhenkun/envs/sglang/bin/playwright install chromium # 必做 ``` `requirements.txt` 关键依赖(版本锁自 sglang9,可放宽): `aiohttp / openai / pillow / playwright / requests / beautifulsoup4 / PyYAML / numpy / yt-dlp`。 `google-*`(Vertex/Gemini)仅 `--model-client vertex` 时需要,默认不用装。 ### 4. 网络 / 外部依赖服务清单 | 依赖 | 用途 | 走代理? | 在哪配 | |------|------|---------|--------| | VLM 推理服务 `MODEL_BASE_URL` | 多轮推理主模型 | 否(内网直连,加入 no_proxy) | 脚本 `MODEL_BASE_URL`,默认 `http://100.102.37.219:8008` | | Tavily | `web_search` 公网搜索 | 是 | `TAVILY_API_KEY_FILE` / `TAVILY_API_KEY` | | yt-dlp → YouTube | 下载视频/评论 | 是 | `HTTP_PROXY_URL` | | 内网 gateway 图搜 | `image_search`(可选) | 否(no_proxy) | `GATEWAY_URL` / `GATEWAY_TOKEN` 等环境变量 | | MARS summarizer | 图搜结果摘要(可选) | 否(no_proxy) | `MARS_SUMMARIZER_ADDRESS` / `MARS_SUMMARIZER_MODEL` | 代理机制:脚本默认 `HTTP_PROXY_URL=http://127.0.0.1:17890`,公网流量走代理,内网服务进 `no_proxy` 直连。**新机器若直连公网,设 `HTTP_PROXY_URL=""` 关掉代理。** --- ## 四、如何运行 ### 快速开始(当前本地环境) ```bash cd /home/tione/notebook/gaozhenkun/demo/video_deep_research_demo ./run_people_online_tavily.sh https://www.youtube.com/shorts/ZHI5IkRfXAM ``` ### 常用调用方式 ```bash # 用环境变量传 URL VIDEO_URL=https://www.youtube.com/watch?v=XXXX ./run_people_online_tavily.sh # 限制抓取评论数 MAX_COMMENTS=50 ./run_people_online_tavily.sh # `--` 之后的参数透传给推理脚本,例如改温度 ./run_people_online_tavily.sh --temperature 0.6 ``` ### 关键环境变量(迁移时覆盖默认值) | 变量 | 作用 | 默认值 | 迁移必改 | |------|------|--------|:--------:| | `CONDA_ENV` | 要激活的 conda 环境路径/名 | `/home/tione/notebook/gaozhenkun/envs/sglang` | 视情况 | | `CONDA_BASE` | conda 安装根(`conda shell.bash hook`) | `/root/miniconda3` | 视情况 | | `MODEL_BASE_URL` | VLM 服务(OpenAI 兼容 `/v1`) | `http://100.102.37.219:8008` | ✅ | | `MODEL_NAME` | 模型名 | `qwen3-vl-video-dr` | 视情况 | | `TAVILY_API_KEY_FILE` | Tavily key 文件(每行一个 key) | `demo/secrets/tavily_api_keys.txt` | 视情况 | | `HTTP_PROXY_URL` | 公网代理;直连设 `""` | `http://127.0.0.1:17890` | ✅ | | `YT_DLP` | yt-dlp 路径 | 自动探测 | 视情况 | | `MAX_COMMENTS` / `MAX_TURNS` / `MAX_CONCURRENT` | 评论数 / 最大轮数 / 并发 | 100 / 10 / 1 | 可选 | | `WORK_DIR` | 复用已下载产物,避免重下 | 每次新建 | 可选 | | `YT_COOKIES` / `YT_COOKIES_FROM_BROWSER` | 给 yt-dlp 传 cookie(应对 YouTube 风控) | 无 | 视情况 | ### 迁移示例(新机直连公网、自建 conda) ```bash export CONDA_ENV=/home/tione/notebook/gaozhenkun/envs/sglang export CONDA_BASE=/root/miniconda3 export MODEL_BASE_URL=http://:8000 export MODEL_NAME= export TAVILY_API_KEY=tvly-xxxxxxxx export HTTP_PROXY_URL="" # 直连,不走代理 ./run_people_online_tavily.sh ``` --- ## 五、产物 - **抓取缓存** `/`(默认 `inference/online_runs/_/`): `.mp4`、`.info.json`、`comments.json`、`metadata.json`。 - **推理结果** `/`(默认 `demo/lead_filter_runs/online__/`): - `results.jsonl` — 结构化结果(含每轮工具调用) - `results.html` — **可视化推理轨迹**(逐轮工具/帧图,演示首选) - `summary.json`、`decision_table.csv` — 判定汇总 - `images/`、`frame_cache/` — 抽帧与裁剪图 - **日志** `.log`。 --- ## 六、配置与密钥 ⚠️(迁移 / 建 git 必读) `video_dr_gen/config.py` 已改为**从环境变量读取凭证和内网地址**,默认不再写死旧机器路径或明文 secret: | 位置 | 内容 | |------|------| | `config.py` | `SERPER_API_KEY`、`GATEWAY_URL/USERNAME/USERID/GATEWAY_TOKEN`、`MARS_RETRIEVAL_ADDRESS`、`MARS_SUMMARIZER_ADDRESS`、OSS 配置均读环境变量 | | `run_people_online_tavily.sh` | `TAVILY_API_KEY_FILE` 默认指向 `demo/secrets/tavily_api_keys.txt`;`MODEL_BASE_URL` 仍需按实际模型服务配置 | **因此:** 1. 不要把真实 `GATEWAY_TOKEN`、`SERPER_API_KEY`、Tavily key、OSS key 写回源码或提交。 2. `MARS_SUMMARIZER_ADDRESS` 默认空,自检会跳过;只有显式配置后才会探测。 3. 若需要 `image_search`,需要额外配置 gateway/Serper 与 OSS 上传相关环境变量,否则该工具会返回配置缺失错误。 --- ## 七、运行前自检 ```bash # 1) 模型服务可达? curl "$MODEL_BASE_URL/v1/models" # 2) 源码闭包可导入?应输出 IMPORT_OK cd demo/inference && python -c "import fetch_youtube_online, run_people_quality_inference; print('IMPORT_OK')" # 3) ffmpeg / yt-dlp / chromium 就绪? ffmpeg -version | head -1; yt-dlp --version; python -c "from playwright.sync_api import sync_playwright; print('pw ok')" ``` --- ## 八、常见问题排错 | 现象 | 原因 / 处理 | |------|------| | import 阶段报 playwright 相关错 | 没装内核:`playwright install chromium` | | yt-dlp 下载失败 / 被风控 / 403 | YouTube 对云 IP 风控。配 `HTTP_PROXY_URL`,或用 `YT_COOKIES` / `YT_COOKIES_FROM_BROWSER` 传 cookie;必要时降频 | | 启动卡在自检 / judge 连不上 | `config.py` 的 `MARS_SUMMARIZER_ADDRESS` 内网不可达,按第六节设为 `""` | | `web_search` 报缺 key | 提供 `TAVILY_API_KEY` / `TAVILY_API_KEYS` / `TAVILY_API_KEY_FILE` 三选一 | | 模型请求超时 | 检查 `MODEL_BASE_URL` 可达、模型名 `MODEL_NAME` 是否匹配;`curl $MODEL_BASE_URL/v1/models` | | 内网服务走了代理连不上 | 确认该地址在脚本 `no_proxy` 列表里(默认已含模型 host 与 MARS 地址) | | ffmpeg 报错 / mp4 合并失败 | 装 ffmpeg 并加入 PATH | --- ## 九、目录结构速查 ``` demo/ ├── run_people_online_tavily.sh # 入口脚本(REPO_ROOT 自动取本目录) ├── requirements.txt # Python 依赖(锁自 sglang9) ├── README.md # 简版说明 ├── HANDOVER.md # 本交接文档 ├── inference/ │ ├── fetch_youtube_online.py # 第1步:yt-dlp 抓视频/评论 │ ├── run_people_quality_inference.py# 第2步:单条筛选推理入口(含 health_check) │ ├── attractive_leads_prompt.py # ★工具定义 _TOOLS_BLOCK + 业务 system prompt │ ├── eval.py # 核心引擎:5工具多轮 + Tavily/图搜 + HTML 轨迹 │ └── video_dr_bridge.py # 桥接层:自动定位 video_dr_gen(VIDEO_DR_SOURCE_ROOT 可覆盖) └── video_dr_gen/ # 被 bridge 依赖的闭包(4 文件) ├── config.py # 本地默认配置,secret/内网地址从环境变量读取 ├── utils.py # normalize_bbox / crop_frame / real_image_search ... ├── prompts.py └── assemble_sft_dataset.py ``` > `inference/` 与 `video_dr_gen/` 必须保持现在的相对位置(同在 `demo/` 下)。 --- ## 十、已知问题 / 后续待办 1. **网页化(GitHub / HuggingFace Space)需新增**: - Web 层(Gradio/FastAPI)包住现有两步 CLI; - 把 shell+文件中转改成可调用、可流式吐进度的 Python API(推理耗时长,需进度条); - 系统依赖打包(ffmpeg / playwright chromium,Dockerfile 或 HF `packages.txt`); - 增加「本地视频上传」备选输入,规避云端拉 YouTube 被风控; - 并发队列 / 超时 / 临时目录清理 / 限流。 ---