RAG的简单流程实现

前言

RAG的简单流程实现。


流程

  • 准备知识库

    规范格式

  • chunking分块/段

    通用分块;父子分块

    分隔符、最大块长度、块重叠长度(连接上下文长度)、…

  • embedding嵌入

    1.embedding嵌入模型

    word2vec

    经济索引(每块10个关键字搜);高质量索引(embedding模型处理搜)

    vector db

  • 检索测试

  • 查询同理,匹配相似度高/向量距离近/数据库相近的几条

    2.rerank检索排序(多路)召回模型

    向量搜索;全文/倒排搜索;混合搜索(向量语义(索引)+关键词(索引))

    分数阈值;topK


缺点和优化

缺点

  • 分块不准
  • 多句没有哪句特别相关

优化

  • graph rag知识图谱rag

    图联系上下文,减少传统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
98
99
100
101
102
103
104
105
106
107
108
# 1.准备知识库————————————————————
def read_knowledge_base() -> str:
with open("knowledge_base.md", "r", encoding="utf-8") as f:
return f.read()


# 2.chunking分块/段————————————————————
def divide_chunks() -> list[str]:
text = read_knowledge_base()
tmp_chunks = text.split("\n\n")

# title不分块,和下一块合并
chunks = []
title = ""
for c in tmp_chunks:
if c.startswith("#"):
title += f"{c}\n" # 记录
else:
chunks.append(f"{title}{c}") # 合并
title = "" # 重置

return chunks


# if __name__ == "__main__":
# chunks = divide_chunks()
# for c in chunks:
# print(c)
# print("---------------")


# 3.embedding嵌入————————————————————
from google import genai

# 获取api密钥:https://aistudio.google.com/apikey(需要魔法)
# 作者已删除该密钥
genai_client = genai.Client(api_key="AIzaSyDOai6QVu_r_fMRbFeLv5-rSyljpqpAhWc")
EMBED_MODEL = "gemini-embedding-exp-03-07"


def embed(text: str, store: bool) -> list[float]: # 模型分为存储和查询模式
result = genai_client.models.embed_content(
model=EMBED_MODEL,
contents=text,
config={"task_type": "RETRIEVAL_DOCUMENT" if store else "RETRIEVAL_QUERY"},
)

assert result.embeddings
assert result.embeddings[0].values
return result.embeddings[0].values


# if __name__ == "__main__":
# chunks = divide_chunks()
# print(embed(chunks[0], store=True))


import chromadb

chromadb_client = chromadb.PersistentClient("./chroma.db") # 库
chromadb_collection = chromadb_client.get_or_create_collection("linghuchong") # 表


def store_db() -> None:
chunks = divide_chunks()

for idx, c in enumerate(chunks):
print(f"Process: {c}")
vec = embed(c, store=True)
chromadb_collection.upsert(ids=str(idx), documents=c, embeddings=vec)


# if __name__ == "__main__":
# store_db() # 可能会因为网络失败


# 4.检索测试
# 5.查询同理,匹配相似度高/向量距离近/数据库相近的几条


def query_db(question: str) -> list[str]:
vec = embed(question, store=False)
result = chromadb_collection.query(query_embeddings=vec, n_results=5)

assert result["documents"]
return result["documents"][0]


LLM_MODEL = "gemini-2.5-flash-preview-05-20"
if __name__ == "__main__":
# store_db()

question = "令狐冲领悟了什么魔法?"
context = query_db(question)

system_prompt = "You are clever\n"
user_prompt = "Please answer user's question according to context\n"
user_prompt += f"Question: {question}\n"
user_prompt += "Context:\n"
for c in context:
user_prompt += f"{c}\n"
user_prompt += "-------------\n"
prompt = system_prompt + user_prompt

result = genai_client.models.generate_content(model=LLM_MODEL, contents=prompt)
print(result)
# 没有继续提取answer了


结果

divide_chunk()

divide_chunk()

embed()

embed()

store_db()

store_db()

query()

query()


参考资料


作者的话

  • 感谢参考资料的作者/博主
  • 作者:夜悊
  • 版权所有,转载请注明出处,谢谢~
  • 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
  • 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
  • 文章在认识上有错误的地方, 敬请批评指正
  • 望读者们都能有所收获