mcpField
R
rag-architect

rag-architect

github.com/farmage数据与数据库223289 次安装5 周前更新
代码仓库

关于 rag-architect

rag-architect 是用于设计检索增强生成系统的技能,涵盖数据切分、向量存储、检索流程、评估与迭代。

主要功能

  1. 01分析检索需求
  2. 02设计向量存储与数据结构
  3. 03制定文档切分策略
  4. 04混合检索与重排
  5. 05检索评估与迭代

适用场景

  1. 01规划 RAG 架构
  2. 02选择向量数据库
  3. 03改进文档检索
  4. 04评估检索质量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/farmage/opencode-skills --skill rag-architect

安装后在 Claude Code 中输入/rag-architect确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
chunking-strategies.md
embedding-models.md
rag-evaluation.md
retrieval-optimization.md
vector-databases.md

详细介绍

RAG 架构师

核心工作流

  1. 需求分析 — 明确检索需求、延迟限制、准确性要求和规模
  2. 向量存储设计 — 选择数据库,设计架构,制定索引策略和分片方案
  3. 分块策略 — 拆分文档、设置重叠、划定语义边界、丰富元数据
  4. 检索管线 — 选择嵌入模型、转换查询、进行混合搜索和重排序
  5. 评估与迭代 — 跟踪指标、调试检索、持续优化

每个步骤完成后都要先验证,再进入下一步(参见下方检查点)。

参考指南

根据上下文加载详细指南:

主题参考资料加载时机
向量数据库references/vector-databases.md比较 Pinecone、Weaviate、Chroma、pgvector、Qdrant 时
嵌入模型references/embedding-models.md选择或微调嵌入模型、权衡向量维度时
分块策略references/chunking-strategies.md拆分文档、设置重叠或进行语义分块时
检索优化references/retrieval-optimization.md进行混合搜索、重排序、查询扩展或筛选时
RAG 评估references/rag-evaluation.md评估指标、评估框架或检索调试时

实现示例

1. 文档分块
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Evaluate chunk_size on your domain data — never use 512 blindly
splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,
    chunk_overlap=100,
    separators=["\n\n", "\n", ". ", " "],
)

chunks = splitter.create_documents(
    texts=[doc.page_content for doc in raw_docs],
    metadatas=[{"source": doc.metadata["source"], "timestamp": doc.metadata.get("timestamp")} for doc in raw_docs],
)

检查点: assert all(c.metadata.get("source") for c in chunks), "Missing source metadata"

2. 生成嵌入并建立索引
from openai import OpenAI
import qdrant_client
from qdrant_client.models import VectorParams, Distance, PointStruct

client = OpenAI()
qdrant = qdrant_client.QdrantClient("localhost", port=6333)

# Create collection
qdrant.recreate_collection(
    collection_name="knowledge_base",
    vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)

def embed_chunks(chunks: list[str], model: str = "text-embedding-3-small") -> list[list[float]]:
    response = client.embeddings.create(input=chunks, model=model)
    return [r.embedding for r in response.data]

# Idempotent upsert with deduplication via deterministic IDs
import hashlib, uuid

points = []
for i, chunk in enumerate(chunks):
    doc_id = str(uuid.UUID(hashlib.md5(chunk.page_content.encode()).hexdigest()))
    embedding = embed_chunks([chunk.page_content])[0]
    points.append(PointStruct(id=doc_id, vector=embedding, payload=chunk.metadata))

qdrant.upsert(collection_name="knowledge_base", points=points)

检查点: assert qdrant.count("knowledge_base").count == len(set(p.id for p in points)), "Deduplication failed"

3. 混合搜索(向量 + BM25)
from qdrant_client.models import Filter, FieldCondition, MatchValue, SparseVector
from rank_bm25 import BM25Okapi

def hybrid_search(query: str, tenant_id: str, top_k: int = 20) -> list:
    # Dense retrieval
    query_embedding = embed_chunks([query])[0]
    tenant_filter = Filter(must=[FieldCondition(key="tenant_id", match=MatchValue(value=tenant_id))])
    dense_results = qdrant.search(
        collection_name="knowledge_base",
        query_vector=query_embedding,
        query_filter=tenant_filter,
        limit=top_k,
    )

    # Sparse retrieval (BM25)
    corpus = [r.payload.get("text", "") for r in dense_results]
    bm25 = BM25Okapi([doc.split() for doc in corpus])
    bm25_scores = bm25.get_scores(query.split())

    # Reciprocal Rank Fusion
    ranked = sorted(
        zip(dense_results, bm25_scores),
        key=lambda x: 0.6 * x[0].score + 0.4 * x[1],
        reverse=True,
    )
    return [r for r, _ in ranked[:top_k]]

检查点: assert len(hybrid_search("test query", tenant_id="demo")) > 0, "Hybrid search returned no results"

4. 对 Top-K 结果进行重排序

从环境变量或机密管理器中加载提供商 API 密钥;切勿将其提交到源代码中。

import os

import cohere

co = cohere.Client(os.environ["COHERE_API_KEY"])

def rerank(query: str, results: list, top_n: int = 5) -> list:
    docs = [r.payload.get("text", "") for r in results]
    reranked = co.rerank(query=query, documents=docs, top_n=top_n, model="rerank-english-v3.0")
    return [results[r.index] for r in reranked.results]
5. 检索评估
# Run precision@k and recall@k against a labeled evaluation set
# python evaluate.py --metrics precision@10 recall@10 mrr --collection knowledge_base

from ragas import evaluate
from ragas.metrics import context_precision, context_recall, faithfulness, answer_relevancy
from datasets import Dataset

eval_dataset = Dataset.from_dict({
    "question": questions,
    "contexts": retrieved_contexts,
    "answer": generated_answers,
    "ground_truth": ground_truth_answers,
})

results = evaluate(eval_dataset, metrics=[context_precision, context_recall, faithfulness, answer_relevancy])
print(results)

检查点: 在接入大模型之前,确保 context_precision >= 0.7 且 context_recall >= 0.6。

约束

必须做到
  • 在确定使用某个嵌入模型之前,先用领域数据评估多个模型
  • 在生产系统中实现混合搜索(向量 + 关键词)
  • 为多租户或特定领域的检索添加元数据筛选
  • 衡量检索指标(precision@k、recall@k、MRR、NDCG)
  • 将上下文传递给大模型之前,对 Top-K 结果进行重排序
  • 实现支持去重的幂等数据导入(确定性 ID)
  • 持续监控检索延迟和质量
  • 对嵌入进行版本管理,并规划模型迁移
绝不能做
  • 未使用领域数据评估,就采用默认分块大小(512)
  • 跳过元数据补充(来源、时间戳、章节)
  • 忽略检索质量指标,而只关注大模型输出质量
  • 未经预处理或清理就存储原始文档
  • 在复杂的多领域检索中仅使用余弦相似度
  • 未在接近生产环境的数据量上测试就部署
  • 忽略边缘情况(结果为空、文档格式错误)
  • 让嵌入模型与应用代码紧密耦合

输出模板

设计 RAG 架构时,需交付:

  1. 系统架构图(数据导入 + 检索管线)
  2. 向量数据库选型及权衡分析
  3. 分块策略、示例及理由
  4. 检索管线设计(查询 → 结果流程)
  5. 评估计划,包含指标、基准和通过/不通过阈值

文档

评论

支持 Markdown