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 + 停用词 ✅ 只保留"熊猫"→ 熊猫文档胜出

停用词( 喜欢 、 吃 、 什么 )被过滤后,"熊猫"这个词的 独特性 充分体现,相似度计算就正确了。

订阅/RSS Feed

Subscribe