1. 项目概述:一个去中心化的AI协作网络

最近在折腾大语言模型本地部署的朋友,可能都体会过那种“硬件焦虑”——显存不够、模型太大、推理速度慢。我自己之前为了跑一个130亿参数的模型,差点把显卡给烧了。就在我琢磨着是不是得再升级一下装备的时候,一个叫 petals-infra/chat.petals.dev 的项目进入了我的视野。这玩意儿有点意思,它没让我去堆硬件,而是换了个思路: 既然一个人跑不动整个模型,那为什么不把模型拆开,让网络上的很多人一起跑呢?

简单来说,Petals 构建了一个去中心化的网络,允许你将一个超大规模的语言模型(比如 LLaMA、Falcon 这些动辄数百亿参数的大家伙)分割成许多块,每一块都运行在网络中不同的志愿者计算机上。当你想使用这个模型进行对话或生成文本时,你的请求会被自动路由到这些分散的节点上,由它们协同完成计算,最后把结果汇总返回给你。 chat.petals.dev 就是这个理念的一个具体实现,一个基于 Web 的聊天客户端,让你能像使用 ChatGPT 一样,直接通过浏览器与运行在 Petals 网络上的大模型对话,而无需关心背后复杂的分布式计算。

这解决了什么痛点?最直接的就是 降低了个人使用前沿大模型的门槛 。你不再需要一块价值不菲的 40GB 显存显卡,甚至用集成显卡的笔记本,只要能联网,就能体验到百亿参数模型的对话能力。其次,它 提升了资源利用率 ,让闲置的算力(比如研究机构的服务器空闲时段)能够被有效整合。最后,它指向了一种 更加开放和协作的AI未来 ,而不是算力被少数几家巨头垄断。

2. 核心架构与工作原理深度拆解

要理解 Petals,不能把它简单看作一个“在线版 ChatGPT”。它的核心魅力在于其背后的分布式架构,这和我们熟悉的客户端-服务器模式有本质区别。

2.1 分布式模型推理:把模型“拆了”跑

传统的大模型服务,比如 OpenAI 的 API,模型完整地运行在官方的超级计算集群上。你的请求发送到他们的服务器,计算结果再返回。这是一个典型的中心化模式。

Petals 则采用了 “模型并行” 的分布式推理策略。想象一下,一个巨大的语言模型就像一本厚重的百科全书。中心化服务是把整本书放在一个图书馆里,谁要查资料都得来这个图书馆。而 Petals 的做法是,把这本书的各个章节拆分开,分散存放在社区里许多人的书架上(这些书架就是参与网络的节点)。

  • 模型分块(Block) :Petals 会将一个完整的 Transformer 模型(如 LLaMA-65B)按层进行切割。每一层或连续几层被定义为一个“块”(Block)。每个块包含该部分模型的所有参数和计算逻辑。
  • 节点(Peer) :网络中的任何一台加入的计算机,都可以选择托管一个或多个这样的“块”。这台计算机就成为了网络的一个节点(或称为“对等点”)。
  • 路由与协同计算 :当你通过 chat.petals.dev 发起一个对话时,你的客户端(或一个轻量级的协调节点)会将你的输入文本进行预处理(分词),然后开始计算流程。计算过程会像接力赛一样,依次流过托管不同模型块的节点。节点 A 完成第1-5层的计算后,将中间结果(激活值)传递给节点 B,节点 B 接着计算第6-10层,以此类推,直到通过所有层,得到最终输出。

这种模式的关键在于, 单个节点只需要存储和计算整个模型的一小部分 ,因此对显存的要求大大降低。一个 65B 的模型,单个节点可能只需要负责其中 5-10B 参数对应的层,这使得消费级显卡(如 RTX 3060 12GB)参与成为可能。

2.2 网络拓扑与一致性保障

一个自发组织的分布式网络,如何保证稳定和可靠?Petals 借鉴了 P2P 网络的思想。

  • 去中心化发现(DHT) :节点加入网络时,会通过一个分布式哈希表(DHT)来发现其他节点。DHT 就像一个公共电话簿,记录了哪个节点持有哪些模型块。这个电话簿本身也是分布在网络中的,没有单点故障。
  • 任务调度与负载均衡 :当有推理请求到来时,调度器(可能内置于客户端,也可能由某个节点临时担任)会查询 DHT,找到当前在线且负载较低的、持有所需模型块的节点,将计算任务分配过去。如果某个节点掉线,调度器能快速发现,并将任务重新路由到持有相同模型块的其他备份节点上。
  • 一致性挑战 :这是分布式系统的经典难题。Petals 通过相对宽松的一致性模型来处理。对于模型参数,它们被认为是 静态的、只读的 。所有节点在加入网络时,都必须保证其托管的模型块是从可信来源(如官方 Hugging Face 仓库)下载的、经过哈希校验的相同版本。这确保了计算基础的一致性。对于推理过程中的临时状态,则通过请求-响应协议来保证单次会话内计算流的正确传递。

注意 :这种网络的性能极度依赖于参与节点的带宽和延迟。如果中间某个节点的网络很慢,就会成为整个推理流水线的瓶颈,导致响应时间变长。因此,它更适合对实时性要求不是极端苛刻的文本生成场景,而不是需要毫秒级响应的交互。

2.3 客户端角色: chat.petals.dev 做了什么

chat.petals.dev 作为前端,它的工作相对清晰:

  1. 提供用户界面 :一个简洁的聊天窗口,处理用户输入和结果显示。
  2. 连接 Petals 网络 :它内嵌或连接了一个轻量级的 Petals 客户端库。
  3. 协调推理请求 :将你的对话内容组织成模型能理解的格式(Prompt),发起对 Petals 网络的远程过程调用(RPC)。
  4. 流式输出 :接收网络返回的生成结果(通常是 token 流),并实时显示在界面上,模拟打字机效果。

它本身不托管任何模型块,只是一个服务的消费者和展示层。这种设计意味着,只要 Petals 网络中存在可用的模型,任何开发者都可以基于 Petals 的客户端 SDK 构建自己的聊天应用、写作助手或集成工具。

3. 从零开始:部署自己的节点与深度参与指南

仅仅使用公共的 chat.petals.dev 只是体验的开始。要真正理解这个网络并为其贡献力量(同时可能获得更稳定的服务优先级),最好的方式是部署自己的节点。下面是我在 Ubuntu 服务器上部署一个节点的详细过程。

3.1 硬件与基础环境准备

Petals 对节点的最低要求很灵活,但为了有较好的体验和贡献度,建议如下:

  • GPU :至少 8GB 显存。这是参与大多数主流大模型(如 LLaMA-2-70B 的一个块)的基本要求。显存越大,你能托管的模型块就越大或越多。
  • 内存 :16GB 以上系统内存。
  • 存储 :至少 50GB 可用空间,用于存放模型权重。
  • 网络 :稳定的公网 IP 或配置了良好 NAT 穿透的内网环境(需要 UPnP 或手动端口转发)。上传带宽尤为重要,因为你需要向其他节点发送中间激活值。
  • 操作系统 :Linux(如 Ubuntu 20.04/22.04)是首选,对 Docker 和 Python 生态支持最好。Windows 可通过 WSL2 参与。

首先,更新系统并安装基础依赖:

sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip git curl wget

接着安装 CUDA 工具包(以 Ubuntu 22.04 和 CUDA 12.1 为例):

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin
sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda-repo-ubuntu2204-12-1-local_12.1.0-530.30.02-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2204-12-1-local_12.1.0-530.30.02-1_amd64.deb
sudo cp /var/cuda-repo-ubuntu2204-12-1-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update
sudo apt-get -y install cuda-toolkit-12-1

安装后,将 CUDA 路径加入环境变量:

echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

3.2 安装 Petals 与运行节点

Petals 提供了 pip 包,安装非常简便。强烈建议在虚拟环境中进行:

python3 -m venv petals-env
source petals-env/bin/activate
pip install --upgrade pip
pip install petals

如果你的显卡不是特别新,可能需要安装特定版本的 PyTorch 以兼容 CUDA。可以在安装 petals 前先安装 PyTorch:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

安装完成后,运行一个节点只需要一行命令。这里以托管 meta-llama/Llama-2-70b-chat-hf 模型的一部分为例:

python -m petals.cli.run_server meta-llama/Llama-2-70b-chat-hf --num_blocks 5 --throughput 10

让我解释一下这几个关键参数:

  • meta-llama/Llama-2-70b-chat-hf :这是 Hugging Face 模型库中的模型 ID。你需要确保你有权访问这个模型(对于 LLaMA 2,需要先在 Hugging Face 上申请同意)。
  • --num_blocks 5 :指定你这个节点托管该模型的连续 5 个“块”。块数越多,需要的显存越大。你可以通过 --help 查看模型的总块数,然后根据你的显存决定。一个经验法则是,每 10B 参数大约需要 2-3GB 显存(以 BF16 精度计算)。
  • --throughput 10 :一个优先级指标。它向网络宣告你这个节点期望的处理速度(可以理解为“意愿强度”),会影响调度器分配任务的权重。不是绝对的吞吐量。

第一次运行会从 Hugging Face 下载你负责的那部分模型权重,下载量取决于你托管的块数。下载完成后,节点就会启动,连接到 Petals 的 DHT 网络,并广播自己持有的块信息。

3.3 高级配置与优化技巧

要让你的节点更稳定、高效,还需要一些调整。

1. 使用自定义模型或本地模型: 如果你有自己微调过的模型,或者网络下载慢,可以先在本地用 transformers 库下载完整模型,然后指向本地路径。

# 首先,将模型下载到本地目录
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "your-model-id"
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16)
tokenizer = AutoTokenizer.from_pretrained(model_name)
model.save_pretrained("./local-model")
tokenizer.save_pretrained("./local-model")

# 然后,运行节点时指向本地路径
python -m petals.cli.run_server ./local-model --num_blocks 5

2. 网络与端口配置: 如果节点运行在防火墙或 NAT 后,需要确保端口能被访问。Petals 默认使用 31337 端口。你需要在路由器上设置端口转发(TCP),将公网 IP 的 31337 端口映射到内网节点的 31337 端口。或者,在云服务器上,配置安全组开放此端口。

3. 性能监控与日志: 运行节点时,它会输出日志,显示连接状态、接收的请求和推理延迟。你可以通过 --log_level INFO DEBUG 获取更详细信息。监控 GPU 使用情况可以用 nvidia-smi -l 1 命令。

4. 安全考虑: 目前,加入公共 Petals 网络意味着你的计算资源将无偿提供给网络中的随机请求使用。虽然单个请求消耗不大,但理论上存在被滥用的可能(例如,有人大量发送请求占用资源)。Petals 团队正在开发信誉系统和资源配额机制。现阶段,如果你有顾虑,可以:

  • 限制 --throughput 值,降低被分配任务的频率。
  • 考虑在测试后暂时关闭公共服务,或仅加入私有的、受信任的 Petals 网络集群。

4. 基于 Petals API 开发自定义应用实战

chat.petals.dev 很好,但有时我们需要将大模型能力集成到自己的应用中。Petals 提供了 Python 客户端库,让这变得非常简单。下面我将通过两个实战例子来演示。

4.1 构建一个命令行聊天机器人

首先,确保安装了 petals 客户端库(如果之前安装过 petals 则已包含)。

# chatbot.py
from petals import DistributedBloomForCausalLM
from transformers import BloomTokenizerFast

# 1. 选择模型并连接到网络
# 注意:这里以 BLOOM 为例,实际可以使用任何 Petals 网络支持的模型
model_name = "bigscience/bloom-petals"
tokenizer = BloomTokenizerFast.from_pretrained(model_name)
model = DistributedBloomForCausalLM.from_pretrained(model_name)

# 2. 定义聊天循环
print("连接到 Petals 网络成功!输入你的消息(输入 'quit' 退出)")
while True:
    user_input = input("\nYou: ")
    if user_input.lower() == 'quit':
        break

    # 3. 构建对话 Prompt(这里使用简单的格式)
    prompt = f"Human: {user_input}\nAssistant:"
    inputs = tokenizer(prompt, return_tensors="pt")

    # 4. 使用模型生成回复
    # max_new_tokens: 生成的最大token数
    # do_sample=True: 使用采样,使回复更多样化
    # temperature=0.9: 采样温度,越高越随机
    # top_p=0.95: 核采样参数,限制候选词集合
    outputs = model.generate(
        inputs.input_ids,
        max_new_tokens=256,
        do_sample=True,
        temperature=0.9,
        top_p=0.95,
        pad_token_id=tokenizer.eos_token_id
    )

    # 5. 解码并打印回复
    # skip_special_tokens=True 会过滤掉模型添加的特殊token
    reply = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # 只提取 Assistant 部分
    assistant_reply = reply.split("Assistant:")[-1].strip()
    print(f"Assistant: {assistant_reply}")

这个脚本的核心是 DistributedBloomForCausalLM.from_pretrained(model_name) 。这行代码并不会下载整个模型,而是连接到 Petals 网络,准备进行分布式推理。之后的 generate 调用会被透明地分发到网络中的各个节点。

4.2 创建异步流式响应的 FastAPI 服务

对于 Web 应用,我们往往需要流式输出(像 ChatGPT 那样一个字一个字地出现)。下面用 FastAPI 和 Server-Sent Events (SSE) 实现一个简单的 API。

# api_server.py
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from petals import DistributedBloomForCausalLM
from transformers import BloomTokenizerFast
import asyncio
import json

app = FastAPI()
model_name = "bigscience/bloom-petals"
tokenizer = BloomTokenizerFast.from_pretrained(model_name)
model = DistributedBloomForCausalLM.from_pretrained(model_name)

async def generate_stream(prompt: str, max_tokens: int = 200):
    """异步生成器,用于流式输出token"""
    inputs = tokenizer(prompt, return_tensors="pt")
    input_length = inputs.input_ids.shape[1]

    # 使用模型的generate方法,并开启streamer
    # 注意:Petals的分布式generate目前对streamer的支持可能有限,这里是一种模拟流式的方法。
    # 更佳实践是使用模型的forward方法进行手动循环生成。
    for token_id in model.generate(
        inputs.input_ids,
        max_new_tokens=max_tokens,
        do_sample=True,
        temperature=0.7,
        top_p=0.9,
        pad_token_id=tokenizer.eos_token_id
    )[0][input_length:]:  # 只取新生成的token
        token = tokenizer.decode(token_id, skip_special_tokens=True)
        # 过滤掉一些奇怪的空白符,让输出更干净
        if token.strip() or token in [' ', '\n']:
            yield f"data: {json.dumps({'token': token})}\n\n"
        await asyncio.sleep(0.01)  # 稍微延迟,模拟打字效果

@app.post("/chat/stream")
async def chat_stream(request: Request):
    data = await request.json()
    user_message = data.get("message", "")
    if not user_message:
        return {"error": "Message is required"}

    # 构建prompt
    full_prompt = f"Human: {user_message}\nAssistant:"
    # 返回SSE流
    return StreamingResponse(
        generate_stream(full_prompt, max_tokens=300),
        media_type="text/event-stream"
    )

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

运行 python api_server.py 后,你就可以通过 /chat/stream 端点发送 POST 请求(例如用 curl 或前端页面),并以流的形式接收生成的文本。前端可以使用 EventSource API 来接收这些数据并实时渲染。

实操心得 :在开发中,直接使用 generate 方法最简单,但控制粒度较粗。对于需要更高可控性的场景(比如精确控制停止词、实现复杂的对话逻辑),可以考虑使用模型的 forward 方法进行手动循环生成:每次调用 forward 得到一个下一个 token 的 logits,然后自己实现采样、判断是否结束等逻辑。这虽然复杂,但提供了最大的灵活性。

5. 性能、局限与未来展望

经过一段时间的实测和开发,我对 Petals 的优缺点有了更深的体会。

5.1 实测性能与影响因素分析

我分别在本地网络(与节点延迟 <50ms)和跨洲网络(延迟 >200ms)下测试了 chat.petals.dev 以及自建客户端调用 LLaMA-2-70B 模型的表现。

  • 首字延迟(Time to First Token) :这是体验的关键。在理想情况下(网络通畅,节点负载低),首字延迟可以控制在 2-5 秒。这比本地加载 70B 模型动辄几分钟要快得多。但网络波动时,延迟可能增加到 10 秒以上,因为需要跨多个节点串联通信。
  • 生成速度(Tokens per Second) :在节点性能充足且网络良好的情况下,生成速度可以达到 5-15 token/秒。这比在单张消费级显卡上本地运行 70B 模型(可能不到 1 token/秒)要快一个数量级。 但是 ,这个速度是不稳定的,它取决于当前任务流经的所有节点中最慢的那个环节(“木桶效应”)。
  • 影响因素
    1. 网络延迟与带宽 :这是最大的变量。节点间的网络质量直接决定了流水线的效率。
    2. 节点负载 :如果持有某个关键块的节点正在为其他请求服务,你的请求就需要排队。
    3. 模型块分布 :如果模型块在全球范围内分布非常分散,一次推理可能绕地球半圈,延迟必然高。
    4. 客户端与网络的连接质量 :你本地的网络状况也很重要。

5.2 当前面临的主要挑战与局限性

Petals 的理念非常前沿,但也面临一些现实的挑战:

  1. 响应时间不可预测 :由于网络的动态性,你无法像调用商业 API 那样获得一个稳定的 SLA(服务等级协议)。这对于需要稳定低延迟的生产环境来说是个障碍。
  2. 隐私与数据安全 :你的输入文本(Prompt)和生成的中间结果会在多个不受你控制的节点间传输。尽管传输的是经过处理的激活值而非原始文本,且目前没有证据表明能从中反推原文,但从隐私安全角度,这仍然是一个需要用户知情和权衡的风险。不适合处理高度敏感的商业或个人信息。
  3. 模型一致性与恶意节点 :网络依赖于节点的诚实。虽然模型权重是只读且可校验的,但一个恶意节点可能返回错误的计算结果,导致生成无意义或有害的内容。Petals 需要通过经济激励、信誉系统或验证计算等技术来缓解。
  4. 网络依赖与单点故障 :虽然 DHT 是去中心化的,但当前的 Petals 网络仍然有一些引导节点(bootstrap nodes)。如果这些节点全部失效,新节点可能难以加入网络。不过,已有节点间的通信可以继续。
  5. 支持的模型结构 :Petals 的模型并行框架需要对 Transformer 架构有较好的支持。一些特别新颖或修改较大的模型架构可能需要适配才能高效运行在 Petals 上。

5.3 生态发展与应用场景展望

尽管有局限,Petals 代表的方向极具潜力。它的应用场景正在扩展:

  • 学术研究与开放科学 :让资源有限的研究者和学生也能接触和实验超大规模模型,促进了 AI 研究的民主化。
  • 长尾语言与领域模型 :社区可以协作托管针对小众语言或专业领域(如法律、医疗)微调的大模型,服务特定群体。
  • 去中心化应用(dApp)的 AI 后端 :与区块链等去中心化技术结合,为 dApp 提供去中心化的智能对话或内容生成能力。
  • 算力共享经济 :未来可能形成一种模式,贡献算力的节点获得代币激励,使用者支付少量费用,形成一个可持续的分布式算力市场。

从我个人的实践来看,Petals 目前最适合的场景是 非实时的创意生成、代码辅助、学习研究以及作为商业 API 之外的一个备用或补充选择 。它让我们看到了在“大模型算力竞赛”之外的另一条路径——协作。随着网络规模的扩大、调度算法的优化以及隐私计算技术的引入,如果它能逐步解决稳定性和信任问题,未必不能成为一种主流的 AI 服务范式。

最后,给想深入玩转 Petals 的朋友一个小技巧:关注其 GitHub 仓库的 dev 分支和 Discord 社区。这个项目迭代很快,新的优化(如自适应路由、模型压缩集成)和模型支持会最先在那里讨论和测试。参与进去,你不仅是用户,也可能成为塑造未来分布式 AI 网络的一员。

更多推荐