必须用threadpoolexecutor显式并发调用多模型,禁用串行invoke;hermes需配置hermes_max_concurrent并启用asyncio.semaphore;结果须带task_id键值返回防乱序覆盖。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

需要让多个大模型(如百川、Hermes Agent、Qwen等)在同一时间发起请求,避免串行等待导致整体耗时翻倍,必须显式开启并发机制而非依赖默认单线程行为。
确认模型调用是否天然支持并发
不是所有封装好的 SDK 都默认启用并发。例如 requests 库本身是同步阻塞的,直接 for 循环调用会串行执行;而某些高级封装(如 langchain 的 AsyncLLMChain)可能内置异步支持,但需主动调用 ainvoke 而非 invoke。
若你当前代码中每个模型调用都写成 result = model.invoke(prompt),那它就是串行的——这一步必须改。
Python 中用 ThreadPoolExecutor 开启多模型并发
这是最通用、兼容性最强的方式,适用于任意基于 requests 或 httpx 的模型 API 封装。
方法一:为每个模型定义独立调用函数
第一步:分别编写三个函数,各自封装一个模型的完整请求逻辑(含 headers、data、URL、错误处理),确保它们彼此隔离、无共享状态。
第二步:将三个函数名和对应 prompt 组成元组列表,例如:[(call_baichuan, "解释量子计算"), (call_hermes, "生成测试用例"), (call_qwen, "写一封辞职信")]。
第三步:使用 ThreadPoolExecutor(max_workers=3) 提交任务,用 executor.submit(func, *args) 分别触发,不要用 map——因为函数签名不一致。
【max_workers 必须等于模型数量,否则部分模型会被排队延迟启动】
方法二:统一接口 + 模型标识参数
把所有模型请求逻辑收进一个函数,用 model_name 参数区分行为,再传入 prompts 列表与对应模型名列表,用 executor.map 并发执行。这种方式适合模型结构高度相似的场景。
控制 Hermes Agent 的并发安全边界
如果你调用的是 Hermes Agent,它内部已预置并发控制层,但必须手动启用,否则仍走串行沙箱初始化路径。
打开 environments/agent_loop.py,找到 _creation_locks_lock = threading.Lock() 所在位置。
确认该文件中存在 asyncio.Semaphore(max_concurrent_requests) 初始化语句,且其值来自配置项而非硬编码 1。
在发起批量请求前,显式设置环境变量 HERMES_MAX_CONCURRENT=5 或修改配置文件中 max_concurrent_requests: 5,否则信号量不会生效。
这一步漏掉会导致所有 Agent 请求被强制串行化,哪怕外层用了线程池也无效。
避免结果乱序与数据污染
并发请求返回顺序不等于提交顺序,尤其当各模型响应时间差异大时(如百川快、Hermes 慢、Qwen 中等)。
不要依赖 results[0] 一定对应第一个 prompt——必须在每个调用函数内部将 prompt 或 task_id 带入返回值,例如 {"task_id": "qwen_1", "response": "..."} 。
使用字典而非列表收集结果,以 task_id 为 key,可彻底规避顺序错位问题。
如果共用全局变量(如一个 shared_dict)接收结果,且未加锁或原子操作,【会出现键值覆盖,丢失部分模型输出】。











