本地 AI 的瓶颈不总是模型太大,也可能是请求太多。单个智能体运行顺畅,并不代表研究、编码、检索等多个智能体同时工作时,一张 GPU 还能稳定响应。处于 Beta 阶段的 NVIDIA Personal AI Router(PAIR)试图解决这个问题:汇集局域网内多台计算机的推理能力,并自动把 AI 请求分配给它们。
它解决的是请求拥塞,而不只是算力不足
PAIR 最适合多个相互独立的模型调用。例如,一个多智能体工作流可能同时执行这些任务:
- 规划智能体拆解用户目标;
- 检索智能体整理本地文档;
- 编码智能体生成或检查代码;
- 总结智能体压缩其他智能体的输出。
如果所有请求都挤到同一张 GPU 上,显存竞争、排队时间和响应延迟会迅速增加。PAIR 在路由层分发请求,使局域网里的其他计算机也能承担推理工作。
需要注意,不能仅根据现有摘要把 PAIR 理解成“把多张显卡拼成一张大显卡”。其明确强调的是多个独立 AI 请求的分配,而不是模型切分、分布式训练或跨机器合并显存。因此,它更可能改善并发吞吐量,而不一定缩短单个大型请求的生成时间。
哪些工作负载更适合接入
判断是否值得部署,可以先观察任务是否具有足够的并行性。
适合优先尝试的场景包括:
- 多个智能体能够同时发起模型调用;
- 团队成员共享局域网内的本地推理节点;
- 批量摘要、分类、代码审查等任务包含大量独立请求;
- 某些机器经常满载,而另一些机器的 GPU 长时间空闲。
收益可能较小的场景则包括:
- 工作流严格串行,后一个请求必须等待前一个请求;
- 只有一台机器或一个推理节点;
- 单次请求本身就超出任意一台节点的显存容量;
- 网络传输、模型加载或磁盘读取才是主要瓶颈。
异构机器还会带来额外问题。不同 GPU、量化版本和推理后端可能产生不同延迟,甚至略有不同的输出。面向自动化流程时,应固定模型版本、采样参数和上下文限制,并确认路由失败后是否会重试。
用并发压测验证路由效果
PAIR 的具体安装方式和请求接口应以 Beta 版本文档为准。下面的脚本不是官方 PAIR API 示例,而是一个可以改造的验证工具:它假设路由器暴露了兼容 OpenAI Chat Completions 形式的 HTTP 接口。如果实际路径或请求结构不同,请修改 PAIR_URL 和 payload。
将以下内容保存为 bench_pair.py:
import json
import os
import statistics
import time
import urllib.request
from concurrent.futures import ThreadPoolExecutor, as_completed
URL = os.getenv("PAIR_URL", "http://127.0.0.1:8000/v1/chat/completions")
MODEL = os.getenv("PAIR_MODEL", "local-model")
API_KEY = os.getenv("PAIR_API_KEY", "")
REQUESTS = int(os.getenv("REQUESTS", "24"))
CONCURRENCY = int(os.getenv("CONCURRENCY", "6"))
def send_request(index: int):
payload = {
"model": MODEL,
"messages": [
{
"role": "user",
"content": f"Request {index}: summarize why parallel inference helps multi-agent systems in two sentences."
}
],
"temperature": 0.2,
"max_tokens": 100
}
headers = {"Content-Type": "application/json"}
if API_KEY:
headers["Authorization"] = f"Bearer {API_KEY}"
request = urllib.request.Request(
URL,
data=json.dumps(payload).encode("utf-8"),
headers=headers,
method="POST"
)
started = time.perf_counter()
with urllib.request.urlopen(request, timeout=120) as response:
response.read()
elapsed = time.perf_counter() - started
return index, response.status, elapsed
def main():
started = time.perf_counter()
latencies = []
failures = 0
with ThreadPoolExecutor(max_workers=CONCURRENCY) as pool:
futures = [pool.submit(send_request, i) for i in range(REQUESTS)]
for future in as_completed(futures):
try:
index, status, elapsed = future.result()
latencies.append(elapsed)
print(f"request={index:02d} status={status} latency={elapsed:.2f}s")
except Exception as exc:
failures += 1
print(f"failed: {exc}")
wall_time = time.perf_counter() - started
if latencies:
ordered = sorted(latencies)
p95_index = max(0, int(len(ordered) * 0.95) - 1)
print("\nSummary")
print(f"successful={len(latencies)} failed={failures}")
print(f"wall_time={wall_time:.2f}s throughput={len(latencies) / wall_time:.2f} req/s")
print(f"mean_latency={statistics.mean(latencies):.2f}s p95_latency={ordered[p95_index]:.2f}s")
if __name__ == "__main__":
main()
按实际地址和模型名运行:
PAIR_URL=http://192.168.1.20:8000/v1/chat/completions \
PAIR_MODEL=my-local-model \
REQUESTS=24 \
CONCURRENCY=6 \
python bench_pair.py
验证时不要只看单个请求的延迟。更有意义的指标是总完成时间、每秒完成请求数、P95 延迟和失败率。可以先把 PAIR_URL 指向一台推理服务器,再指向 PAIR 的路由入口,使用同一批提示词和并发参数比较结果。
同时可以从管理机检查各节点的 GPU 是否真正承担了负载。运行前把主机名替换成自己的节点:
for host in ai-node-1 ai-node-2 ai-node-3; do
echo "=== $host ==="
ssh "$host" 'nvidia-smi --query-gpu=name,memory.used,memory.total,utilization.gpu --format=csv,noheader'
done
部署前别忽略这些边界
局域网推理减少了对外部服务的依赖,但“数据没有离开办公室”并不等于安全问题自动消失。接入 PAIR 前,至少应检查:
- 路由入口和节点之间是否启用身份认证与访问控制;
- 提示词、文档内容和模型输出是否会写入日志;
- 节点离线或超时时,请求会重试、转移还是直接失败;
- 所有节点是否加载兼容的模型、量化格式和上下文长度;
- 调度是否考虑 GPU 显存、当前队列和节点性能差异;
- 是否能够定位某次请求最终由哪个节点执行。
PAIR 的价值不在于让每个请求都神奇地加速,而在于把闲置的本地算力组织起来。对于并发明显的多智能体系统,建议先用两台机器、小规模请求和固定模型做基准测试;确认吞吐量、输出一致性和故障行为后,再逐步增加节点与并发度。