Transformers RAG 模型完全指南:从检索增强架构、RagRetriever 配置到 RAG-Sequence/RAG-Token 生成实现
本篇技术指南基于 Transformers 仓库中的 RAG 模型文档 及其配套源码实现,系统讲解 RAG(Retrieval-Augmented Generation,检索增强生成)在 Transformers 中的完整落地方式:如何组合问题编码器、检索器与生成器三大组件完成推理,如何配置 RagRetriever 的索引与数据集参数,以及 RagSequenceForGeneration 与 RagTokenForGeneration 两种模型在"彻底解码"与"逐 token 边际化"上的源码级差异。读完本文,你可以直接在本地运行 RAG 生成示例、理解 n_docs/max_combined_length/index_name 等关键参数的作用机制,并能区分两种解码策略在 loss 计算与 beam search 上的不同实现路径。
RAG 的核心思想:参数化记忆 + 非参数化记忆
Retrieval-Augmented Generation (RAG) 的核心设计是把预训练语言模型(参数化记忆)与可外部访问的数据源(非参数化记忆)通过一个预训练神经检索器连接起来:模型在推理时先从外部知识库检索相关段落,再基于这些段落条件化地生成答案。官方文档(docs/source/en/model_doc/rag.md)强调这一设计带来两个实际收益:
- 答案更具事实性:生成内容以检索到的段落为条件,减少模型"凭记忆"产生的幻觉;
- 知识可更新:更新知识只需替换/重建索引,而无需重新训练整个模型。
原始 RAG 系列预训练检查点都发布在 AI at Meta(facebook)组织下,仓库文档给出的示例统一使用 facebook/rag-sequence-nq 作为基准模型。
从源码结构看(src/transformers/models/rag/modeling_rag.py),RagPreTrainedModel 的类文档明确写道:RAG 是一个"检索增强模型",封装了三个组件——question encoder(问题编码器)、dataset retriever(数据集检索器)和 generator(生成器);其中编码器与生成器可训练,检索器只是一个带索引的数据集。这与文档描述的概念模型完全对应。
快速上手:使用 RagSequenceForGeneration 生成文本
以下是仓库文档给出的完整推理示例(对应 docs/source/en/model_doc/rag.md 中 AutoModel 用法选项),展示如何用 RagSequenceForGeneration 结合 FlashAttention-2 与自动设备映射完成端到端生成:
from transformers import RagRetriever, RagSequenceForGeneration, RagTokenizer
tokenizer = RagTokenizer.from_pretrained("facebook/rag-sequence-nq")
retriever = RagRetriever.from_pretrained(
"facebook/rag-sequence-nq", dataset="wiki_dpr", index_name="compressed"
)
model = RagSequenceForGeneration.from_pretrained(
"facebook/rag-sequence-nq",
retriever=retriever,
attn_implementation="flash_attention_2",
device_map="auto",
)
inputs = tokenizer("How many people live in Paris?", return_tensors="pt").to(model.device)
generated = model.generate(input_ids=inputs["input_ids"])
print(tokenizer.batch_decode(generated, skip_special_tokens=True)[0])
这段代码值得逐行拆解,因为它覆盖了 RAG 工作流的三大件:
RagTokenizer:不是单一分词器,而是同时持有两个分词器的"容器"。查看 src/transformers/models/rag/tokenization_rag.py 可见,RagTokenizer.__init__接收question_encoder与generator两个分词器,__call__默认转发给current_tokenizer(初始为问题编码器分词器,用于编码问题);而decode/batch_decode始终转发给generator分词器(生成结果要用生成器的词表解码)。from_pretrained时会分别以question_encoder_tokenizer与generator_tokenizer两个子目录加载这两个分词器。RagRetriever:dataset="wiki_dpr"指定索引的语料(约 2100 万条维基段落),index_name="compressed"选择预构建的 FAISS 压缩索引。_build_index的实现(src/transformers/models/rag/retrieval_rag.py)会依据index_name分派:"legacy"走LegacyIndex,"custom"走CustomHFIndex.load_from_disk,其余(如compressed、exact)走CanonicalHFIndex。RagSequenceForGeneration:通过retriever=...把检索器挂载到模型上,之后generate(input_ids=...)即可在单次调用中完成"编码 → 检索 → 生成"全流程。attn_implementation="flash_attention_2"可用,因为RagPreTrainedModel声明了_supports_flash_attn = True与_supports_sdpa = True(src/transformers/models/rag/modeling_rag.py)。
低精度量化:用 BitsAndBytes 4-bit 加载
对于大参数量的 RAG 检查点,文档进一步给出了 bitsandbytes 4-bit 量化加载示例,通过 BitsAndBytesConfig 降低显存占用(支持的量化后端总览见 Quantization):
import torch
from transformers import BitsAndBytesConfig, RagRetriever, RagSequenceForGeneration, RagTokenizer
bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
tokenizer = RagTokenizer.from_pretrained("facebook/rag-sequence-nq")
retriever = RagRetriever.from_pretrained(
"facebook/rag-sequence-nq", dataset="wiki_dpr", index_name="compressed"
)
model = RagSequenceForGeneration.from_pretrained(
"facebook/rag-sequence-nq",
retriever=retriever,
quantization_config=bnb,
device_map="auto",
)
inputs = tokenizer("How many people live in Paris?", return_tensors="pt").to(model.device)
generated = model.generate(input_ids=inputs["input_ids"])
print(tokenizer.batch_decode(generated, skip_special_tokens=True)[0])
RagConfig:所有可调参数的集中地
RagConfig 定义了 RAG 模型与检索器的全部默认行为,源码见 src/transformers/models/rag/configuration_rag.py。有两个结构性细节需要注意:
- 必须同时提供两个子配置:
__post_init__要求构造时kwargs中必须同时包含question_encoder与generator两个子配置,否则抛出ValueError(configuration_rag.py)。两个子配置分别通过AutoConfig.for_model实例化为对应模型类型的配置对象。 - 提供工厂方法:
RagConfig.from_question_encoder_generator_configs(question_encoder_config, generator_config, **kwargs)可以从两个现成的预训练配置直接构造RagConfig(configuration_rag.py)。
下面是源码字段定义(configuration_rag.py)结合文档说明整理的完整参数表:
| 参数 | 默认值 | 说明 |
|---|---|---|
prefix |
None |
传给生成器模型前拼接到每个输入开头的字符串前缀(T5 系模型常用) |
title_sep |
" / " |
检索文档"标题 / 正文"之间的分隔符 |
doc_sep |
" // " |
检索文档正文与原始问题输入之间的分隔符 |
n_docs |
5 |
每个查询检索的文档数量 |
max_combined_length |
300 |
RagRetriever.__call__ 返回的上下文化输入的最大长度 |
retrieval_vector_size |
768 |
索引中文档嵌入的维度 |
retrieval_batch_size |
8 |
并发向 FAISS 索引发起查询的批次大小 |
dataset |
"wiki_dpr" |
被索引数据集在 HuggingFace Datasets 中的标识符 |
dataset_split |
"train" |
加载该数据集的哪个 split |
index_name |
"compressed" |
与 dataset 关联的索引名,可选 "legacy"、"exact"、"compressed" 或 "custom" |
index_path |
None |
磁盘上序列化 FAISS 索引的路径 |
passages_path |
None |
与 FAISS 索引兼容的文本段落路径;使用 LegacyIndex 时必需 |
use_dummy_dataset |
False |
是否加载数据集的"dummy"(测试用假数据)变体 |
reduce_loss |
False |
是否用 torch.Tensor.sum 归约 NLL loss |
label_smoothing |
0.0 |
标签平滑 epsilon,仅当 return_loss=True 时相关;0 表示不平滑 |
do_deduplication |
True |
是否对同一输入来自不同上下文文档的生成结果去重;分布式后端训练时必须设为 False |
exclude_bos_score |
False |
计算 loss 时是否忽略 BOS token 的得分 |
do_marginalize |
False |
是否用 torch.nn.functional.log_softmax 对所有文档做 logits 边际化 |
output_retrieved |
False |
为 True 时额外返回 retrieved_doc_embeds、retrieved_doc_ids、context_input_ids、context_attention_mask |
dataset_revision |
None |
检索所用 HuggingFace 数据集的 revision(commit hash、tag 或分支) |
这些参数不是摆设:例如 n_docs 会被 RagModel.forward 用来断言 doc_scores 维度关系、do_deduplication 直接控制 RagSequenceForGeneration.generate 内部是否对生成假设做集合去重(详见下文"RAG-Sequence 的彻底解码"一节)。
RagRetriever:四类索引与检索调用链
RagRetriever 是"从向量查询到文档"的组件,它同时检索文档嵌入与文档内容,并把它们格式化为可供 RagModel 使用的上下文。实现位于 src/transformers/models/rag/retrieval_rag.py,继承体系为 Index(抽象基类)→ LegacyIndex / HFIndexBase → CanonicalHFIndex / CustomHFIndex。
三种标准索引 + 自定义索引
RagRetriever._build_index(retrieval_rag.py)的分派逻辑与文档中四个加载示例一一对应:
-
index_name="compressed"(或"exact")—— CanonicalHFIndex:从 HuggingFace Datasets 加载带 FAISS 索引的标准数据集,默认即wiki_dpr约 2100 万条段落。文档给出的加载方式:from transformers import RagRetriever # 加载默认的 "wiki_dpr" 数据集(21M 维基段落,索引名 'compressed' 或 'exact') retriever = RagRetriever.from_pretrained( "facebook/rag-sequence-nq", dataset="wiki_dpr", index_name="compressed" )CanonicalHFIndex.init_index支持两条路径:若设置了index_path则用dataset.load_faiss_index("embeddings", file=...)从磁盘加载;否则重新load_dataset(..., with_index=True, index_name=...)加载远端预构建索引(retrieval_rag.py)。 -
indexed_dataset=dataset——CustomHFIndex(内存中的自定义数据集):文档示例要求数据集必须包含title、text、embeddings三列且带有受支持的索引:from transformers import RagRetriever # dataset 必须是 datasets.Dataset 对象,含 "title"、"text"、"embeddings" 列 # 且带有支持的索引(如 Faiss 索引) retriever = RagRetriever.from_pretrained("facebook/rag-sequence-nq", indexed_dataset=dataset)源码中
from_pretrained收到indexed_dataset时会自动把config.index_name改写为"custom"并构造CustomHFIndex(retrieval_rag.py)。格式校验在HFIndexBase._check_dataset_format中完成:缺少title/text/embeddings列直接抛ValueError(retrieval_rag.py)。 -
index_name="custom"且落盘——CustomHFIndex.load_from_disk:自定义数据集先dataset.save_to_disk(...)、索引再dataset.get_index("embeddings").save(...),之后:from transformers import RagRetriever dataset_path = "path/to/my/dataset" # dataset.save_to_disk(...) 保存的位置 index_path = "path/to/my/index" # dataset.get_index("embeddings").save(...) 保存的位置 retriever = RagRetriever.from_pretrained( "facebook/rag-sequence-nq", index_name="custom", passages_path=dataset_path, index_path=index_path, ) -
index_name="legacy"—— LegacyIndex:反序列化 DPR 论文构建的旧格式索引文件:from transformers import RagRetriever retriever = RagRetriever.from_pretrained("facebook/rag-sequence-nq", index_name="legacy")注意:
LegacyIndex会pickle.load段落文件与索引元数据,出于安全考虑源码要求显式设置环境变量TRUST_REMOTE_CODE=True才允许执行,否则抛出ValueError提示 pickle 反序列化风险(retrieval_rag.py)。这是使用 legacy 索引时最容易踩的坑。
检索调用链与上下文拼接格式
RagRetriever.__call__ 是整个检索子系统的入口,返回一个 BatchEncoding,字段包括 context_input_ids、context_attention_mask、retrieved_doc_embeds、doc_ids(若启用了 set_ctx_encoder_tokenizer 还会附带 tokenized_doc_ids 等,供端到端检索器训练使用)。其内部流程(retrieval_rag.py):
- 按
config.retrieval_batch_size把question_hidden_states分块,逐块调用index.get_top_docs得到doc_ids与文档嵌入; - 用问题编码器分词器把
question_input_ids解码回文本; - 调用
postprocess_docs把每篇文档与问题拼接并重新分词。
拼接格式由 postprocess_docs 内的 cat_input_and_doc 定义(retrieval_rag.py):
{prefix}{doc_title} / {doc_text} // {input_string}
其中 / 来自 config.title_sep、// 来自 config.doc_sep,标题两侧的引号会被 removeprefix('"')/removesuffix('"') 剥离,连续双空格被压缩为单空格。拼接结果用 generator_tokenizer 以 max_length=config.max_combined_length、padding="max_length"、truncation=True 编码——这解释了为什么 max_combined_length 默认 300:它是每条"文档+问题"上下文的截断上限。
RagModel.forward:一次前向中的三段式流水线
RagModel(modeling_rag.py)是纯"组装层",其 forward 展示了 RAG 前向的完整数据流:
- 判定是否需要检索:
has_to_retrieve为真的条件是模型挂载了retriever且context_input_ids/context_attention_mask/doc_scores未显式传入、也没有预计算的encoder_outputs。这意味着你可以选择"模型内一体化检索"或"手动三步走"。 - 编码:
question_encoder(input_ids, attention_mask=...)产出question_encoder_last_hidden_state。 - 检索:把隐状态
.detach().to(device="cpu", dtype=torch.float32).numpy()后传入self.retriever(...),得到context_input_ids、context_attention_mask、retrieved_doc_embeds、doc_ids。 - 计算文档分数:
doc_scores = torch.bmm(question_hidden_states.unsqueeze(1), retrieved_doc_embeds.transpose(1, 2)).squeeze(1),即问题隐状态与每个文档嵌入的点积,形状(batch_size, n_docs)。 - 喂给生成器:
context_input_ids的形状是(batch_size * n_docs, max_combined_length)——每个问题展开为n_docs份上下文并行送入 generator;decoder_input_ids(若提供)会repeat_interleave(n_docs, dim=0)与之对齐(modeling_rag.py)。 - 输出:返回
RetrievAugLMOutput,包含logits、doc_scores、past_key_values以及问题/生成器两侧的 hidden states 与 attentions(modeling_rag.py)。
如果模型没有挂载 retriever,则必须手动传入 context_input_ids、context_attention_mask 与 doc_scores,源码中三处断言会明确提示可以用 set_retriever(...) 补挂检索器(modeling_rag.py)。文档示例给出了这种"分离式"用法(来自 RagSequenceForGeneration.forward 的 docstring):
>>> from transformers import AutoTokenizer, RagRetriever, RagSequenceForGeneration
>>> import torch
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/rag-sequence-nq")
>>> retriever = RagRetriever.from_pretrained(
... "facebook/rag-sequence-nq", index_name="exact", use_dummy_dataset=True
... )
>>> # 方式一:挂载 retriever,一次 forward 完成全部工作
>>> model = RagSequenceForGeneration.from_pretrained("facebook/rag-token-nq", retriever=retriever)
>>> inputs = tokenizer("How many people live in Paris?", return_tensors="pt")
>>> targets = tokenizer(text_target="In Paris, there are 10 million people.", return_tensors="pt")
>>> input_ids = inputs["input_ids"]
>>> labels = targets["input_ids"]
>>> outputs = model(input_ids=input_ids, labels=labels)
>>> # 方式二:手动分步
>>> model = RagSequenceForGeneration.from_pretrained("facebook/rag-sequence-nq", use_dummy_dataset=True)
>>> # 1. 编码
>>> question_hidden_states = model.question_encoder(input_ids)[0]
>>> # 2. 检索
>>> docs_dict = retriever(input_ids.numpy(), question_hidden_states.detach().numpy(), return_tensors="pt")
>>> doc_scores = torch.bmm(
... question_hidden_states.unsqueeze(1), docs_dict["retrieved_doc_embeds"].float().transpose(1, 2)
... ).squeeze(1)
>>> # 3. 送入生成器
>>> outputs = model(
... context_input_ids=docs_dict["context_input_ids"],
... context_attention_mask=docs_dict["context_attention_mask"],
... doc_scores=doc_scores,
... decoder_input_ids=labels,
... )
其中 use_dummy_dataset=True 加载的是测试用假数据变体(对应 RagConfig.use_dummy_dataset),适合本地调试而不下 21M 段落的完整索引。
此外,RagPreTrainedModel.from_pretrained_question_encoder_generator 提供了"从零拼装"的构造方式:分别给出 question encoder 与 generator 的预训练模型路径,自动构建二者与 RagConfig(modeling_rag.py)。文档中给出的示例是 RagModel.from_pretrained_question_encoder_generator("facebook/dpr-question_encoder-single-nq-base", "google-t5/t5-small"),还支持用 question_encoder_* / generator_* 前缀的 kwargs 分别覆盖两个子模型的配置。
RAG-Sequence:在生成后做"彻底"边际化
RagSequenceForGeneration(modeling_rag.py)对应 RAG-sequence 模型。它的 forward 在 RagModel 输出之上调用 get_nll 计算带文档边际化的 NLL loss;而真正体现 RAG-sequence 思想的是其 generate 实现——注释中称其为"thorough decoding(彻底解码)"(modeling_rag.py)。
generate 的解码流程
- 一次性检索:若挂载了 retriever 且未传
context_input_ids,先用 question encoder 编码问题、调用 retriever 得到context_input_ids(与上文 RagModel 路径一致)。 - 对每个文档分别 beam 搜索:把
context_input_ids按n_docs切片(形状(n_docs, max_len)),整体送入self.generator.generate(...),得到n_docs * num_beams条候选序列。 - 可选去重:
do_deduplication=True(默认,来自RagConfig.do_deduplication)时用torch.stack(list({str(k.tolist()): k for k in output_sequences}.values()))把完全重复的候选序列合并——这正是文档标注"分布式训练时必须设False"的参数在代码里的落点。 - 打分排序:把候选序列作为
labels重新做一次前向得到 NLL loss,取(-loss).topk(num_return_sequences)选出最优假设。 - 拼接输出:
_cat_and_pad将各 batch 的假设按generator.pad_token_id填充对齐后返回。
RAG-sequence 的边际化 loss
get_nll(modeling_rag.py)实现了对所有文档的边际化:先把 seq_logits 的 log-softmax 按 (batch, n_docs, tgt_len, vocab) 分块,把 doc_scores 的 log-softmax 作为文档先验,按 RAG 论文的特殊方式拼合——首个 token 只取序列概率,第二个 token 起叠加 doc_logprobs,再对文档维做 logsumexp。与 RagConfig 中 exclude_bos_score、label_smoothing、reduce_loss 三个参数一一对应:BOS 位置可选跳过、平滑项按 epsilon / vocab_size 计算、reduce_loss=True 时对最终 loss 求和。
RAG-Token:在解码每一步做边际化
RagTokenForGeneration(modeling_rag.py)是另一种解码策略的实现,它与 GenerationMixin 组合,直接继承标准生成循环。核心差异在 marginalize 方法(modeling_rag.py):
def marginalize(self, seq_logits, doc_scores, n_docs=None):
n_docs = n_docs if n_docs is not None else self.config.n_docs
# RAG-token 边际化
seq_logprobs = nn.functional.log_softmax(seq_logits, dim=-1).view(
seq_logits.shape[0] // n_docs, n_docs, -1, seq_logits.size(-1)
)
doc_logprobs = torch.log_softmax(doc_scores, dim=1)
log_prob_sum = seq_logprobs + doc_logprobs.unsqueeze(-1).unsqueeze(-1)
return torch.logsumexp(log_prob_sum, dim=1)
即每个解码步都把 n_docs 份上下文的 token 概率与文档分数做 log 域加和后再 logsumexp,让 beam search 每一步看到的都是文档边际化后的分布;forward 中当 do_marginalize=True(RagConfig.do_marginalize)时对输出 logits 应用该操作(modeling_rag.py)。
其 generate 是完整定制的解码循环,几个值得注意的实现细节:
- 支持四种生成模式:
SAMPLE、GREEDY_SEARCH、BEAM_SEARCH、BEAM_SAMPLE,其他模式会抛ValueError(modeling_rag.py); - 编码器只做一次:
generate里先单独跑self.rag.generator.get_encoder()编码全部context_input_ids,再用extend_enc_output把last_hidden_state与attention_mask沿num_beams维度扩展,避免每步重复编码; - beam search 的 cache 重排:
_reorder_cache是 BART 风格的改写,额外处理了"文档维"带来的 batch 展开——通过hidden_states.shape[0] // new_order.shape[0]反推n_docs再view(-1, n_docs, ...)重排(modeling_rag.py);_temporary_reorder_cache的注释说明 RAG 因内部按文档展开输入,始终走 legacy cache 重排路径; prepare_inputs_for_generation显式注入do_marginalize=True、doc_scores与n_docs,保证每一步的 forward 都在做边际化(modeling_rag.py)。
其 docstring 给出的三种使用方式(一体化挂载 retriever / 手动三步前向 / 用 context_input_ids 直接 generate)与 RAG-sequence 的示例同构,此处不再重复;get_nll 则直接复用 marginalize 的结果计算带平滑的 NLL loss。
两种模型的对照可以总结为:
| 维度 | RagSequenceForGeneration | RagTokenForGeneration |
|---|---|---|
| 边际化时机 | 生成完整候选后统一打分(thorough decoding) | 每个解码步对 logits 边际化 |
| 生成入口 | 自定义 generate:逐文档 beam + 重打分 + 去重 |
继承 GenerationMixin 标准循环 + 定制 prepare_inputs_for_generation |
| 文档分数用途 | 进入边际化 loss,间接影响候选排序 | 直接进入每步 marginalize 的 log 加和 |
| 关键配置 | do_deduplication、exclude_bos_score |
do_marginalize、n_docs |
输出结构与检索相关张量
RAG 专用的两个输出 dataclass 定义在 src/transformers/models/rag/modeling_rag.py:
RetrievAugLMOutput(RagModel返回):核心字段为logits(形状(batch_size, sequence_length, vocab_size))、doc_scores(形状(batch_size, n_docs),定义为"每个检索文档嵌入与question_encoder_last_hidden_state之间的分数")、past_key_values,以及output_retrieved=True时的retrieved_doc_embeds、retrieved_doc_ids、context_input_ids、context_attention_mask;还包含问题编码器与生成器两侧的 hidden states / attentions / cross-attentions 可选字段。RetrievAugLMMarginOutput(两个 ForGeneration 模型返回):在上述基础上增加loss(提供labels时返回),且logits"可能已经对所有文档做过边际化"。
context_input_ids 的默认形状为 (batch_size * n_docs, max_combined_length)——这也解释了源码中多处 assert context_input_ids.shape[0] % n_docs == 0 的断言来源。
工程实践:构建自定义索引与测试验证
如果你想把 RAG 用到自己的知识库,文档与源码共同给出的路径是:用 HuggingFace Datasets 构建含 title/text/embeddings 三列的数据集 → 用 dataset.add_faiss_index(...) 建索引(或保存已有索引)→ 通过 RagRetriever.from_pretrained(..., indexed_dataset=dataset)(内存中)或 index_name="custom", passages_path=..., index_path=...(落盘)接入。save_pretrained 对自定义索引也有配套处理:CustomHFIndex 场景下会自动把索引保存为 hf_dataset_index.faiss、段落保存为 hf_dataset/ 目录并回写 config.index_path / config.passages_path(retrieval_rag.py)。
仓库内的测试用例为这套实现提供了可验证的行为基线:
- tests/models/rag/test_modeling_rag.py:覆盖
RagModel/RagSequenceForGeneration/RagTokenForGeneration的前向、生成与 loss(测试中直接复用 DPR question encoder 与 T5 generator 的 tester,也印证了三组件的默认组合形态); - tests/models/rag/test_retrieval_rag.py:验证
RagRetriever各索引类型的构建与检索; - tests/models/rag/test_tokenization_rag.py:验证
RagTokenizer的双分词器行为。
总结
Transformers 中的 RAG 实现以"question encoder + retriever + generator"三组件为核心:RagConfig 集中了从 n_docs、max_combined_length 到 index_name、dataset 的全部参数并强制双子配置结构;RagRetriever 以四类索引(canonical/custom/legacy/内存数据集)封装 FAISS 检索,并用 title_sep/doc_sep 把文档与问题拼成上下文;RagModel 负责"编码 → 检索 → doc_scores → 生成器"的一体化前向;RagSequenceForGeneration 与 RagTokenForGeneration 则分别以"生成后彻底解码 + 去重排序"和"逐 token 边际化 + 标准生成循环"实现了 RAG 论文的两种解码范式。配合文档给出的 FlashAttention-2 加载示例与 bitsandbytes 4-bit 量化示例,你可以在单卡 GPU 上完整跑通检索增强生成,并通过 output_retrieved=True 检查检索到的段落来诊断答案质量。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00