ai - rag 的思考 embed model faiss
访问量: 6
refer to:
参考文档: https://www.doubao.com/thread/we2eae491887ca1c0
1. 需要使用嵌入模型 (embedded model ) 它会自行理解语义,检索到最匹配的内容 . 所以直接原文入库
2. 不要使用上古编程中的 分词。 也不要用停用词过滤。这个不准确,而且落后于时代
3. 嵌入模型天生支持中英文混杂。
下面是正确的例子
import os
import numpy as np
import requests
import faiss
from sentence_transformers import SentenceTransformer
# 加速下载
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
# ===================== 知识库 =====================
documents = [
"熊猫是中国国宝,主要食物是竹子。",
"狗是犬科动物,喜欢吃狗粮。",
"机器猫喜欢吃铜锣烧。",
"牛头人喜欢吃青草。",
"牛喜欢吃苜蓿",
"野比大熊喜欢欺负人。",
"猫喜欢抓老鼠,是肉食动物。"
]
# ===================== 现代 RAG 核心:嵌入模型 =====================
embed_model = SentenceTransformer('BAAI/bge-small-zh') # 中文最强
doc_embeddings = embed_model.encode(documents, convert_to_numpy=True)
# FAISS 检索
index = faiss.IndexFlatL2(doc_embeddings.shape[1])
index.add(doc_embeddings)
# ===================== 检索(语义理解,无需分词!)=====================
def retrieve(query):
query_emb = embed_model.encode([query], convert_to_numpy=True)
_, idx = index.search(query_emb, 1)
return documents[idx[0][0]]
# ===================== LLM =====================
def chat(prompt):
resp = requests.post("https://api.deepseek.com/chat/completions", json={
"model": "deepseek-v4-flash",
"temperature": 0.1,
"messages": [{"role": "user", "content": prompt}]
}, headers={
"Authorization": "Bearer sk-95958c0???"
})
return resp.json()["choices"][0]["message"]["content"]
# ===================== 测试 =====================
query = "熊喜欢吃什么?"
context = retrieve(query)
print(f"==context: {context}")
prompt = f"参考:{context}\n问题:{query}"
print(chat(prompt))
下面是 jieba 分词的例子 (错误)
import os
import numpy as np
import requests
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
# ===================== 你的知识库 =====================
documents = [
"熊猫是中国国宝,主要食物是竹子。",
"狗是犬科动物,有很多品种。喜欢吃狗粮。",
"猫喜欢抓老鼠,是肉食动物。"
]
# ===================== RAG 检索 =====================
# 用 jieba 分词 + 停用词过滤,保留核心关键词
import jieba
STOP_WORDS = {"的", "了", "是", "在", "我", "有", "和", "就", "不", "人",
"都", "一", "也", "很", "到", "说", "要", "去", "你", "会",
"着", "看", "好", "自己", "这", "他", "她", "它", "们",
"什么", "怎么", "喜欢", "吃"}
vectorizer = TfidfVectorizer(
analyzer='word',
tokenizer=lambda x: [w for w in jieba.cut(x) if w.strip() and w not in STOP_WORDS]
)
doc_vectors = vectorizer.fit_transform(documents)
def retrieve(query):
query_vec = vectorizer.transform([query])
similarities = cosine_similarity(query_vec, doc_vectors)[0]
best_idx = np.argmax(similarities)
return documents[best_idx]
# ===================== 调用 DeepSeek =====================
def chat(prompt):
resp = requests.post("https://api.deepseek.com/chat/completions", json={
"model": "deepseek-v4-flash",
"temperature": 0.1,
"messages": [{"role": "user", "content": prompt}]
}, headers={
"Authorization": "Bearer sk-95958c0d4f7e4e???"
})
return resp.json()["choices"][0]["message"]["content"]
# ===================== 运行 RAG =====================
query = "熊猫 喜欢 吃什么?"
context = retrieve(query)
# 拼接提示词(你最开始理解的正确逻辑!)
prompt = f"""
参考资料:{context}
问题:{query}
请根据资料回答。
"""
print(f"==== 提示词:{prompt}")
answer = chat(prompt)
print("回答:", answer)
### 改了什么?
做了 两处修改 :
步骤 说明
① 用 jieba 分词 把 "熊猫喜欢吃什么" 切成 熊猫 / 喜欢 / 吃 / 什么 ,而不是按单字匹配
② 加停用词过滤 过滤掉 喜欢 、 吃 、 什么 这些太通用的词,只保留核心关键词 熊猫
### 为什么之前不行?
版本 问题 analyzer='char' (单字) "熊猫"里的"猫"匹配了"猫喜欢抓老鼠"→ 猫文档胜出 jieba(仅分词) "喜欢"+"吃"两个词权重超过"熊猫"一个词 → 狗文档胜出 jieba + 停用词 ✅ 只保留"熊猫"→ 熊猫文档胜出
停用词( 喜欢 、 吃 、 什么 )被过滤后,"熊猫"这个词的 独特性 充分体现,相似度计算就正确了。