RAG 检索增强生成
RAG 是 Retrieval-Augmented Generation,中文常译为检索增强生成。普通大模型只靠自己参数里的知识回答;RAG 会先去外部知识库、文档、数据库、网页或企业资料里检索相关内容,再把检索到的内容交给大模型生成答案。
RAG 的好处是什么?
可以回答模型训练后才出现的新信息,可以减少胡编,回答更容易引用来源。
1 向量化模型
Embedding Model 又称语义向量模型,被广泛应用于搜索领域,其目的是将自然形式的数据转化为向量(即连续的数字序列),并用向量之间的距离衡量样本的相关性。
1.1 常见的模型
开源的 Embedding 模型可以通过 sentence-transformers 加载。
安装:
1
| pip install sentence-transformers
|
sentence-transformers 常用模型
常见的有:
- all-MiniLM-L6-v2
- paraphrase-multilingual-MiniLM-L12-v2
- multi-qa-MiniLM-L6-cos-v1
BGE 系列
常见的有:
- BAAI/bge-small-zh-v1.5
- BAAI/bge-base-zh-v1.5
- BAAI/bge-large-zh-v1.5
- BAAI/bge-small-en-v1.5
- BAAI/bge-base-en-v1.5
- BAAI/bge-large-en-v1.5
- BAAI/bge-m3
E5 系列
- intfloat/multilingual-e5-small
- intfloat/multilingual-e5-base
- intfloat/multilingual-e5-large
- intfloat/e5-small-v2
- intfloat/e5-base-v2
- intfloat/e5-large-v2
openAI 的需要单独安装:
OpenAI Embeddings 系列
- text-embedding-3-small
- text-embedding-3-large
2 向量数据库
顾名思义,为了存储向量的数据库,著名的有 google 开源的 FAISS。
RAG 所做的内容其实就是从 FAISS 当中检索出相关的资料,再让大模型基于资料去回答。
3 RAG 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| import os import numpy as np import faiss from sentence_transformers import SentenceTransformer from openai import OpenAI
docs = [ "RAG 是 Retrieval-Augmented Generation,中文叫检索增强生成。", "RAG 的核心流程是:先从知识库中检索相关资料,再让大模型基于资料生成答案。", "Embedding 模型可以把文本转换成向量,语义相近的文本向量距离更近。", "FAISS 是一个向量检索库,可以快速查找相似向量。", "在 RAG 中,向量数据库用于保存文档片段的 embedding,并根据用户问题检索相关内容。", "如果知识库中没有相关资料,RAG 系统应该告诉用户资料中没有答案,而不是编造。" ]
embedding_model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
doc_vectors = embedding_model.encode(docs) doc_vectors = np.array(doc_vectors).astype("float32")
dimension = doc_vectors.shape[1] index = faiss.IndexFlatL2(dimension) index.add(doc_vectors)
def retrieve(question, top_k=3): """根据问题检索最相关的文档片段。""" question_vector = embedding_model.encode([question]) question_vector = np.array(question_vector).astype("float32")
distances, ids = index.search(question_vector, top_k)
retrieved = [] for doc_id in ids[0]: retrieved.append(docs[doc_id])
return retrieved
def build_prompt(question, retrieved_docs): """把检索结果和用户问题组合成 prompt。""" context = "\n".join(f"- {doc}" for doc in retrieved_docs)
prompt = f""" 你是一个 RAG 问答助手。
请只根据下面的资料回答问题。 如果资料中没有答案,请回答:资料中没有相关信息。 不要编造资料之外的内容。
资料: {context}
问题: {question} """
return prompt
def ask_openai(prompt): """把 prompt 发给 OpenAI,让大模型生成最终答案。""" client = OpenAI()
response = client.responses.create( model=os.getenv("OPENAI_MODEL", "gpt-4.1-mini"), input=prompt )
return response.output_text
def main(): question = "RAG 为什么需要向量数据库?"
print("用户问题:") print(question)
print("\n第一步:检索相关资料") retrieved_docs = retrieve(question, top_k=3)
for doc in retrieved_docs: print("-", doc)
print("\n第二步:构造 prompt") prompt = build_prompt(question, retrieved_docs) print(prompt)
print("\n第三步:发送给 OpenAI 生成最终回答") answer = ask_openai(prompt)
print("\n最终回答:") print(answer)
if __name__ == "__main__": main()
|