中文 | English
S1-deepresearch 推理框架
核心特性
- 多 LLM 客户端: 支持 vLLM、Azure OpenAI、AIHubMix 等多种 LLM 服务
- 丰富的工具集: 提供 9 种工具,涵盖搜索、网页访问、文件解析、代码执行、多模态问答、bash 等
- 批量推理: 支持并发批量推理,自动断点续传,定期保存结果
- 单条推理: 支持单条查询的详细调试和测试
- 负载均衡: 支持多 LLM 节点的负载均衡和一致性调度
- 详细日志: 为每个查询生成独立的日志文件,便于问题追踪和分析
项目结构(当前)
./
├── run_batch_inference_demo.sh # 本地/vLLM 脚本模板
├── run_batch_inference_online_demo.sh # 在线平台脚本模板
├── inference/
│ ├── run_batch_inference.py
│ └── run_single_inference.py
├── server/
├── tool_kits/
├── utils/
│ └── config/
│ ├── config.example.json
│ └── README.md
├── models/tokenizer/
└── test_all_tools.py
快速开始
1. 安装依赖
pip install -r requirements.txt
2. 配置(推荐 JSON 或环境变量)
配置优先级:自定义 JSON > 环境变量 > utils/config.py 默认值。
常用做法:
cp utils/config/config.example.json utils/config/config.local.json
然后按需修改 config.local.json,例如:
TOOLS_SERVER_BASE_ENDPOINT_URLAIHUBMIX_KEY/AZURE_KEY/VOLCANO_KEY/ALIYUN_KEYCLIENT_TIMEOUT
也可以通过环境变量覆盖,例如:
export S1_DR_CONFIG_JSON="utils/config/config.local.json"
3. 准备输入 JSONL
输入文件每行一个 JSON。最少建议包含 question,通常同时包含 id 与 file_path。
3.1 jsonl 示例(涉及文件输入)
{"id":"query_001","question":"阿里巴巴成立时,18位创始团队成员中,姓马、姓蔡、姓张的创始人的平均年龄,保留一位小数","file_path":[]}
{"id":"query_002","question":"阅读当前说明书,大疆发布的起飞重量最大的AIR系列无人机飞完半程马拉松,电池还剩多少毫安时的电能?(注1:假设水平无风,最低耗能的情况为最大航速的60%飞行;注2:耗电可以按最长飞行时间换算)","file_path":["/path/to/file.pdf"]}
3.2 jsonl 示例(涉及 Skill 使用)
{"id":"query_003","question":"Use pymatgen to build a simple TiO2 surface slab. Please generate a common low-index surface, report the Miller index, slab thickness, and vacuum size, and briefly describe the resulting surface structure.","skills":[{"name": "skill_name1", "description": "description1", "skill_path": "skill_path1"}, {"name": "skill_name2", "description": "description2", "skill_path": "skill_path2"}]}
推荐启动方式:复制脚本后运行
A. 本地 / vLLM(run_batch_inference_demo.sh)
cp run_batch_inference_demo.sh run_batch_local.sh
mkdir -p run_logs
# 编辑 run_batch_local.sh 中的参数
bash run_batch_local.sh
说明:
- 脚本内部已使用
nohup ... &启动 Python,会打印后台 PID。 - 常看日志:
tail -f run_logs/run.log
B. 在线平台(run_batch_inference_online_demo.sh)
cp run_batch_inference_online_demo.sh run_batch_online.sh
mkdir -p run_logs
# 编辑 run_batch_online.sh 中的参数
bash run_batch_online.sh
说明:
- 重点修改:
LLM_CLIENT_URLS、LLM_CLIENT_MODELS、SYSTEM_FORMAT - 常看日志:
tail -f run_logs/run_batch_*.log
脚本参数说明
基础参数
LLM_CLIENT_URLS:模型服务地址,多个地址用空格分隔(与模型列表一一对应)LLM_CLIENT_MODELS:模型名列表,多个模型用空格分隔TEST_DATA_FILE:输入 JSONL 路径OUTPUT_FILE:ROLLOUT_NUM=1时的输出文件OUTPUT_DIR:ROLLOUT_NUM>1时输出目录(生成rollout_01.jsonl等)ROLLOUT_NUM:每条样本重复推理次数RESUME_FROM_FILE:断点续跑文件(可空)AVAILABLE_TOOLS:启用工具列表(空格分隔)TASK_TYPE:是否按“输入仅文本”场景处理,默认input_only
推理控制参数
MAX_ROUNDS:单 query 最大轮次CONCURRENCY_WORKERS:并发 worker 数SAVE_BATCH_SIZE:每处理多少条就自动落盘一次TEMPERATURE:采样温度TOP_P:top-p(run_batch_inference_demo.sh已包含)EXTRA_PAYLOAD:额外模型 payload(JSON 字符串,run_batch_inference_demo.sh已包含)TIMEOUT_FOR_ONE_QUERY:单 query 超时时间(秒)LLM_API_RETRY_TIMES:LLM 请求失败后的重试次数(不含首次)SYSTEM_PROMPT:自定义 system prompt;留空时使用内置默认 promptSYSTEM_FORMAT:平台格式(主要在run_batch_inference_online_demo.sh)
上下文截断相关参数
DISCARD_ALL_MODE:是否启用 discard-all(true/false)MODEL_MAX_CONTEXT_TOKENS:模型最大上下文长度DISCARD_RATIO:触发 discard 的比例阈值TOKENIZER_PATH:token 统计所用 tokenizer 路径
日志参数
LOG_LABEL:日志标签,目录形如logs/YYYY_MM_DD_<LOG_LABEL>/LOG_FILE:脚本启动日志文件(run_logs/*.log)LOGGING_ROOT:日志根路径(run_batch_inference_demo.sh已包含,可空)
SYSTEM_FORMAT 可选值
SYSTEM_FORMAT 将对应不同的平台处理逻辑,根据该关键词进入不同的处理分支。
deep_research:本地 deep research 格式(vLLM 部署)azure:Azure OpenAIaihubmix:AIHubMix(OpenAI 兼容)aihubmix_claude:AIHubMix Claude 格式aihubmix_glm:AIHubMix GLM 格式volcano:火山引擎aliyun:阿里云百炼平台格式
当前默认可用工具(9 个)
wide_search:基于 Serp 进行通用网页搜索,支持一轮提交多个 queryscholar_search:基于 Google Scholar 进行学术检索 + web 结果)image_search:图片检索,支持多 query。wide_visit:访问网页并按目标goal产出摘要file_wide_parse:解析本地/在线文件(PDF、DOCX、MD、CSV等)execute_code:执行 Python 代码ask_question_about_image:图像理解与问答ask_question_about_video:视频理解与问答bash:执行 shell 脚本
各工具对应的 schema 定义详见 utils/prompts.py 下的 DEEPRESEARCH_SYSTEM_PROMPT
输出与日志
输出 JSONL(字段详解)
run_batch_inference.py 写出的每行字段如下:
time_stamp:该行结果写入时的时间戳(YYYY-MM-DD HH:MM:SS)。query_id:批处理层生成的 query 标识(基于question哈希)。query:本条输入的question文本。result:单个 segment 的详细结果对象(来自run_single_inference.py)。status:任务状态,success/timeout/error。discard_segments:被discard-all截断并做 summary 的段数(不含最终段)。elapsed_sec:该 query 本次 rollout 的总耗时(秒)。rollout_idx:第几次 rollout(从 1 开始)。src:原始输入行完整内容(通常含id、question、file_path、skills 等)。segment_idx:当前是第几个 segment(从 1 开始)。segment_total:该 query 共拆成多少个 segment。若无有效result,会写成0。
其中 result 常见字段(run_single_inference.py):
query_id:单次运行实例 ID(含时间后缀)。tools:本次启用的 tools schema(字符串形式)。messages:用于模型推理与工具交互的日志消息。final_answer:当前 segment 的回答文本。transcript:更完整的对话轨迹(含工具回填)。rounds:该 segment 执行到的轮数。stopped_reason:停止原因(如no_tool_calls、discard_all_01、discard_all_final、max_rounds_exceeded)。error:仅在异常时可能出现。
日志目录
默认日志结构如下(LOGGING_ROOT 为空时):
logs/
└── YYYY_MM_DD_<LOG_LABEL>/
├── collect.log
└── <query_id>/
├── run.log
└── result.json
工具测试
运行工具测试脚本:
python test_all_tools.py
该脚本会测试所有注册的工具,验证其基本功能是否正常。