AIREITER

使用 vLLM 在本地部署 AstaBrief 8B,构建私有 RAG

最后更新: 2026-10-02 19:10:19

AstaBrief 8B 不是检索器。它的作用是接收研究问题和你提供的科学文献摘录,再生成带引用的报告。理解这一边界,是做好私有化部署的关键:让生成模型运行在防火墙之后,文档解析和搜索全部留在本地,只把经过排序、带有稳定来源 ID 的证据传给模型。

AstaBrief 8B 真正需要什么

AstaBrief 8B 是 Ai2 推出的 80 亿参数文本生成模型,基于 Qwen3-8B 构建,采用 Apache 2.0 许可证。官方模型卡明确要求输入研究问题和检索到的科学文献摘录,而不是让模型自行搜索答案。模型卡还提醒,修改微调时使用的提示词或交互格式,可能导致性能下降或行为不稳定。

本文使用最终版 allenai/AstaBrief_8B 检查点。模型卡示例中出现的是 allenai/AstaBrief_8B_SFT,这是监督微调阶段的前置模型。下载检查点时,应把这个名称差异当作需要核对的文档细节,不要默认两个模型可以互换。

Ai2 的开源 ScholarQA 仓库适合用来理解参考架构:检索、可选的重排序、论文级聚合、引文提取和报告生成彼此独立。即使你的私有实现使用内部索引替代 Semantic Scholar,也建议保留这种分层设计。

一套可复现的本地架构

一个私有检索流水线应明确拆分为六个阶段:

  1. 导入:解析 PDF,对扫描页面执行 OCR,并保留文档 ID、标题、页码、章节和字符偏移。
  2. 切分:把文本拆成大小适中的段落,同时保留页边界和标题信息。
  3. 检索:在术语、标识符或精确短语很重要时,将词法搜索与向量检索结合起来。
  4. 重排序:根据完整问题重新评估第一阶段召回的候选项,只保留规模较小的证据集合。
  5. 拼装:分配不可变的引用 ID,并按照 AstaBrief 预期的参考文献结构格式化摘录。
  6. 生成:将拼装好的提示词发送到本地 vLLM 接口。

真正重要的设计选择不是某个特定的向量数据库,而是证据契约:发送给模型的每段内容都必须带有稳定 ID,应用可以据此映射回具体文档和页码。

让引用 ID 保持稳定

使用 DOC_014_P07_A 这类 ID,而不要使用数组下标。检索参数一变,数组位置就可能变化;由文档、页码和文本片段组成的 ID 则更容易审计。

把映射关系保存在提示词之外:

{
  "DOC_014_P07_A": {
    "document": "internal_protocol.pdf",
    "page": 7,
    "section": "Methods",
    "char_start": 18420,
    "char_end": 19210
  }
}

在提示词中,让摘录旁边显示同一个 ID。生成完成后,拒绝或标记那些不在本次请求 ID 集合中的引用。这样并不能证明引用的段落支持每一条相关论断,但至少可以阻止最简单的引用伪造。

在拼装上下文前确定检索深度

不要把所有匹配到的文本块一股脑塞进上下文。第一阶段可以尽量扩大召回范围,随后进行重排序,最后只拼装那些既能放进提示词预算、又能直接回答问题的段落。如果合并同一页面上的相邻文本块能够保留完整论证,可以进行合并;但如果最终报告需要精确到页级追溯,就应保留独立的 ID。

Ai2 ScholarQA 仓库介绍了一套参考配置:先检索 256 个候选项,完成重排序后保留 50 个论文级结果。这些数值属于那条公开流水线,并不是 AstaBrief 的通用要求。面对规模较小的私有文档集合,应从更小的范围开始,通过检查遗漏证据,再根据你自己的问题调节检索和上下文限制。

使用 vLLM 运行 AstaBrief 8B

官方资料没有针对所有数据类型、上下文长度和并发水平给出统一的显存要求。可以先在能够加载模型的硬件上运行未量化检查点;如果资源不足,优先降低并发数或上下文长度,再评估量化版本。不要未经测试就假设量化不会影响你的语料上的引用行为。

在与 CUDA 和 PyTorch 环境匹配的干净环境中安装 vLLM,然后使用最终检查点启动 OpenAI 兼容服务器:

pip install -U vllm openai

vllm serve allenai/AstaBrief_8B \
  --host 127.0.0.1 \
  --port 8000 \
  --dtype auto \
  --max-model-len 16000

--max-model-len 设置的是运行上限,并不意味着每个请求都应该包含 16,000 个 token;模型卡给出的训练最大长度是 16,000 个 token,而示例生成时使用的 max_tokens=4096。

验证本地接口

curl http://127.0.0.1:8000/v1/models

接下来,用与微调数据相同的提示词风格调用接口。官方示例使用温度参数 0.7、top-p 0.95、最多生成 4,096 个 token,并将 tokenizer 的 EOS token 作为停止条件。

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:8000/v1",
    api_key="local-only",
)

response = client.chat.completions.create(
    model="allenai/AstaBrief_8B",
    temperature=0.7,
    top_p=0.95,
    max_tokens=4096,
    messages=[
        {"role": "user", "content": assembled_prompt},
    ],
)

print(response.choices[0].message.content)

对于私有服务器,应绑定回环地址或内部网卡,在网关层处理认证和 TLS,并阻断公网入口。模型在本地运行,并不代表日志、临时 PDF 文件或链路追踪数据就天然属于私有范围。

构建私有检索请求

下面的代码骨架有意没有限定索引实现。真正关键的是经过排序的证据列表、不可变 ID,以及清晰的提示词边界。

from dataclasses import dataclass
from openai import OpenAI

@dataclass
class Evidence:
    ref_id: str
    text: str
    title: str
    page: int


def build_prompt(question: str, evidence: list[Evidence]) -> str:
    references = "\n\n".join(
        f"[{item.ref_id}] {item.title} (page {item.page})\n{item.text}"
        for item in evidence
    )
    return f"""Research question:
{question}

Retrieved references:
{references}

Write a cited research report answering the question. Use only the supplied
references for factual support. Attach the supplied reference IDs to claims.
If the references do not establish a point, say that the evidence is
insufficient instead of inventing a source.
"""


def answer(question: str, evidence: list[Evidence]) -> str:
    client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="local-only")
    prompt = build_prompt(question, evidence)
    result = client.chat.completions.create(
        model="allenai/AstaBrief_8B",
        temperature=0.7,
        top_p=0.95,
        max_tokens=4096,
        messages=[{"role": "user", "content": prompt}],
    )
    return result.choices[0].message.content

在生产环境中,请使用官方 AstaBrief 提示词模板,并在保留引用 ID 的前提下插入检索到的摘录。上面的精简指令只是为了展示如何接入 vLLM,不能替代微调时使用的格式。

你的私有索引可以采用 BM25、向量检索或混合检索。元数据必须贯穿整个处理流程。一段没有文档 ID 和页码的文本,即使生成的内容听起来很准确,也不足以支撑一份经得起审查的研究报告。

上线前增加引用与隐私校验

AstaBrief 在 ScholarQA-CS2 上公布的结果可以作为参考,但不能视为对你自己语料的保证。在模型卡的 100 个问题测试集上,AstaBrief 8B 的引用精确率为 90.5,引用召回率为 78.2,答案精确率为 89.0。引用召回率低于引用精确率,这一点很有现实意义:报告可能准确引用了提供的材料,却仍然遗漏了相关证据。

可以设置包含四项检查的质量闸门:

  1. 引用有效性:生成的每个引用 ID 都必须存在于本次请求的允许列表中。
  2. 元数据解析:每个 ID 都必须能解析到具体文档、页码和已存储的文本片段。
  3. 证据支持:由人工审核者或独立验证器检查段落是否确实支持附近的论断。
  4. 检索召回:维护一组带标注的问题,其中包含预期文档和页码;每次调整切分方式、向量模型或重排序器后,都重新测量遗漏情况。

除非你的策略明确允许使用外部服务,否则应将模型服务器、索引、对象存储、日志和监控放在同一个信任边界内。对敏感文档关闭请求正文日志,尽可能从链路追踪中脱敏查询内容,并明确上传 PDF 和生成报告的保留期限。

不要把 Ai2 报告的 51.1 秒 Fast 模式数据直接当作本地基准。这个数字描述的是 Asta 流水线端到端的耗时,而自托管部署会改变 GPU、检索系统、批处理方式、提示词长度和网络路径。应分别测量检索、重排序、首 token 延迟、生成耗时和请求总耗时。

按层排查部署问题

现象可能所在层首先检查
服务器能够加载,但生成结果的引用质量很差提示词或证据契约将提示词与官方格式对比,并确认引用 ID 是否稳定
引用指向不存在的内容应用校验拒绝不在本次请求允许列表中的 ID
相关论文没有被检索出来检索在更换模型前,先评估文本切分、混合搜索和重排序器的召回能力
请求耗尽显存服务或上下文拼装降低并发请求数、输出预算或拼装后的上下文规模,然后再重新评估量化
本地延迟异常偏高整个流水线分别统计检索、重排序、排队和生成耗时
私有数据出现在日志中运维检查网关、vLLM、链路追踪、缓存和对象存储的保留设置

按层诊断可以避免把检索遗漏误判为模型故障,也能防止因为提示词格式不匹配,就通过加入更多文档来“修复”问题。

如果你需要一个专用的本地报告生成器,并且愿意自行负责检索质量、来源映射和结果验证,那么 AstaBrief 8B 值得考虑。vLLM 解决的是模型服务问题;它不会替你提供文档搜索、引用溯源或隐私控制。

参考资料