自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

沒有捷徑:RAG入門不推薦直接使用成熟框架

人工智能
我花了半天時(shí)間重構(gòu)了遍代碼,相比上一版多了600行,也是敲到手酸。這個(gè)進(jìn)階版屬于更符合 RAG 系統(tǒng)最佳實(shí)踐的完整版本,一共有10 個(gè)大類的優(yōu)化要點(diǎn),下述展示會(huì)按照對(duì)最終回答質(zhì)量的影響程度排序。

春節(jié)期間我在 Github 開源的 RAG 項(xiàng)目目前已經(jīng)攢了 134 個(gè) Star,盲猜可能也是因?yàn)樽铋_始用的就是 Ollama 本地部署 DeepSeek-r1:7b 的方案,年后當(dāng)本地部署知識(shí)庫和 deepseek火了起來之后,被動(dòng)蹭了一波流量。

圖片

1、為什么重復(fù)造輪子?

但是,在過去的一個(gè)月時(shí)間里也收到了很多網(wǎng)友的私信,詢問關(guān)于為什么市面上已經(jīng)有了類似 AnythingLLM、Cherry Studio、Dify、RAGFlow 等成熟的開源框架,還要重復(fù)造輪子去編一個(gè)不是很好用的 RAG 項(xiàng)目。

當(dāng)然與此同時(shí),也有很多網(wǎng)友在私信或者評(píng)論區(qū)中反饋上手調(diào)試過我這個(gè)簡(jiǎn)單的開源項(xiàng)目后,再去用其他框架更加得心應(yīng)手了。

1.1 開箱即用的”不友好“

其實(shí)我從 24 年 6 月份開始,就逐一深度試用了上述常見的幾個(gè)開源項(xiàng)目,但一段時(shí)間之后明顯發(fā)現(xiàn),作為一個(gè)剛?cè)腴T的人來說,雖然 AnyThingLLM、RAGFlow 等成熟框架提供了便捷的"開箱即用"體驗(yàn),但直接使用這些工具會(huì)讓人陷入"知其然,而不知其所以然"的困境。

1.2 從零構(gòu)建再到框架應(yīng)用

換句話說,就像學(xué)編程不應(yīng)該從框架開始,而是應(yīng)該從基礎(chǔ)語法入手一樣。學(xué)習(xí) RAG 技術(shù)實(shí)測(cè)也同樣適合先構(gòu)建基礎(chǔ)認(rèn)知框架,再應(yīng)用封裝工具。這不僅是技能學(xué)習(xí)的路徑,更多也是培養(yǎng)解決問題能力的過程。

2、項(xiàng)目特點(diǎn)與局限性

2.1 項(xiàng)目優(yōu)勢(shì)

我這個(gè)開源項(xiàng)目采用簡(jiǎn)潔的代碼展示了 RAG 的完整流程,通過親手調(diào)試這些組件,可以:

圖片

更有助于建立具象認(rèn)知

比如直觀理解文本分塊如何影響語義完整性,檢索策略如何決定召回質(zhì)量,以及重排序如何提升最終回答準(zhǔn)確度

掌握核心決策點(diǎn)

親身體驗(yàn)不同 chunk_size 對(duì)檢索效果的影響,感受不同嵌入模型的語義表達(dá)差異,理解為什么相同的 RAG 系統(tǒng)在不同場(chǎng)景下表現(xiàn)迥異

培養(yǎng)調(diào)試直覺

當(dāng)回答質(zhì)量不理想時(shí),可以通過控制變量法能相對(duì)準(zhǔn)確判斷是分塊策略不當(dāng),還是檢索精度不足,或是提示工程欠缺

掌握這些基礎(chǔ)后,再轉(zhuǎn)向 RAGFlow 或其他框架時(shí),眾多的配置選項(xiàng)就不再是很抽象的參數(shù),再做 API 調(diào)優(yōu)或者二次開發(fā)也會(huì)變得有的放矢。從而深度適配業(yè)務(wù)場(chǎng)景時(shí),也就可以針對(duì)性地做調(diào)整框架配置,而不是非盲目嘗試。

2.2 項(xiàng)目局限性

分塊策略

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=20
)
chunks = text_splitter.split_text(text)

使用 LangChain 的 RecursiveCharacterTextSplitter

塊大?。好繅K 200 字符(較小,一個(gè)字符相當(dāng)于 1 個(gè)漢字)

重疊度:20 字符

特點(diǎn):小塊大小有利于精準(zhǔn)定位信息,但可能損失上下文連貫性

檢索策略

results = COLLECTION.query(
    query_embeddings=query_embedding,
    n_results=5,
    include=['documents', 'metadatas']
)

純語義檢索(沒有混合 BM25 等關(guān)鍵詞檢索)

未使用過濾條件或高級(jí)查詢功能

重排策略

代碼中沒有顯式的重排序步驟,但設(shè)計(jì)了一些相關(guān)邏輯:

# 檢測(cè)矛盾
conflict_detected = detect_conflicts(sources_for_conflict_detection)


# 獲取可信源
if conflict_detected:
    credible_sources = [s for s in sources_for_conflict_detection 
                      if s['type'] == 'web' and evaluate_source_credibility(s) > 0.7]

通過 evaluate_source_credibility 函數(shù)對(duì)信息源進(jìn)行可信度評(píng)分

在檢測(cè)到?jīng)_突時(shí),優(yōu)先考慮可信度高的來源

3、進(jìn)階版本

前幾天開通知識(shí)星球后,有些有一定實(shí)踐經(jīng)驗(yàn)的網(wǎng)友過來交流一些技術(shù)細(xì)節(jié)時(shí)發(fā)現(xiàn),基礎(chǔ)版本的開源項(xiàng)目已經(jīng)不能滿足他們當(dāng)前的需求。

圖片

我花了半天時(shí)間重構(gòu)了遍代碼,相比上一版多了600行,也是敲到手酸。這個(gè)進(jìn)階版屬于更符合 RAG 系統(tǒng)最佳實(shí)踐的完整版本,一共有10 個(gè)大類的優(yōu)化要點(diǎn),下述展示會(huì)按照對(duì)最終回答質(zhì)量的影響程度排序。需要說明的是,優(yōu)先實(shí)施以下前 3-5 項(xiàng)將能帶來最顯著的效果提升。

注:下述代碼優(yōu)化示例是針對(duì)前述我提到的自己開源項(xiàng)目而言

3.1 分塊策略優(yōu)化(最高優(yōu)先級(jí))

200 字符的塊過小,無法包含足夠上下文

可能導(dǎo)致語義割裂和信息碎片化

改進(jìn)方案:

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,        # 增大到800-1000字符
    chunk_overlap=150,     # 增加重疊以保持連貫性
    separators=["\n\n", "\n", "。", ",", " "] # 優(yōu)先在自然段落分割
)

預(yù)期效果:更連貫的上下文,減少信息丟失,提高回答質(zhì)量和相關(guān)性。

3.2 混合檢索策略

當(dāng)前問題:

純語義檢索可能忽略關(guān)鍵詞匹配

容易出現(xiàn)語義漂移

改進(jìn)方案:

# 引入BM25關(guān)鍵詞檢索
from rank_bm25 import BM25Okapi
tokenized_corpus = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)


# 混合檢索結(jié)果
semantic_results = COLLECTION.query(query_embeddings, n_results=7)
bm25_results = bm25.get_top_n(query.split(), corpus, n=7)
combined_results = hybrid_merge(semantic_results, bm25_results)

預(yù)期效果:提高檢索準(zhǔn)確性,尤其對(duì)事實(shí)性和專業(yè)術(shù)語的問題。

3.3 重排序機(jī)制

當(dāng)前問題:

缺乏真正的重排序機(jī)制

相關(guān)度評(píng)分單一依賴向量相似度

改進(jìn)方案:

# 方案A: 使用交叉編碼器重排序
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
candidate_pairs = [[query, doc] for doc in retrieved_docs]
scores = reranker.predict(candidate_pairs)
reranked_results = [doc for _, doc in sorted(zip(scores, retrieved_docs), reverse=True)]


# 方案B: 使用LLM進(jìn)行相關(guān)性評(píng)分
def llm_rerank(query, docs, llm_client):
    results = []
    for doc in docs:
        prompt = f"問題: {query}\n文檔: {doc}\n這個(gè)文檔與問題的相關(guān)性是否高? 0-10分打分:"
        score = float(llm_client.generate(prompt).strip())
        results.append((score, doc))
    return [doc for _, doc in sorted(results, reverse=True)]

預(yù)期效果:更精準(zhǔn)的結(jié)果排序,將最相關(guān)的內(nèi)容放在前面,顯著提高答案質(zhì)量。

3.4 遞歸檢索與迭代查詢

當(dāng)前問題:

單次檢索可能不足以回答復(fù)雜問題

缺乏根據(jù)初步檢索結(jié)果調(diào)整查詢的機(jī)制

改進(jìn)方案:

def recursive_retrieval(initial_query, max_iteratinotallow=3):
    query = initial_query
    all_contexts = []
    
    for i in range(max_iterations):
        # 當(dāng)前查詢的檢索結(jié)果
        current_results = retrieve_documents(query)
        all_contexts.extend(current_results)
        
        # 使用LLM分析還需要查詢什么
        next_query_prompt = f"""
        基于原始問題: {initial_query}
        以及已檢索信息: {summarize(current_results)}
        是否需要進(jìn)一步查詢? 如果需要,請(qǐng)?zhí)峁┬碌牟樵儐栴}:
        """
        
        next_query = llm_client.generate(next_query_prompt)
        if "不需要" in next_query or i == max_iterations-1:
            break
            
        query = next_query
        
    return all_contexts

預(yù)期效果:能夠處理多跳推理問題,循序漸進(jìn)獲取所需信息。

3.5 上下文壓縮與總結(jié)

當(dāng)前問題:

檢索文檔過長時(shí)浪費(fèi) token

包含過多無關(guān)信息

改進(jìn)方案:

def compress_context(query, documents, max_tokens=2000):
    compressed_docs = []
    
    for doc in documents:
        # 方案A: 使用map-reduce模式總結(jié)
        summary_prompt = f"原文: {doc}\n請(qǐng)?zhí)崛∨c問題'{query}'最相關(guān)的信息,總結(jié)在100詞以內(nèi):"
        compressed = llm_client.generate(summary_prompt)
        compressed_docs.append(compressed)
        
        # 方案B: 使用抽取式摘要選擇關(guān)鍵句子
        # sentences = split_into_sentences(doc)
        # scores = sentence_similarity(query, sentences)
        # top_sentences = [s for s, _ in sorted(zip(sentences, scores), key=lambda x: x[1], reverse=True)[:5]]
        # compressed_docs.append(" ".join(top_sentences))
    
    return compressed_docs

預(yù)期效果:減少無關(guān)信息干擾,降低 token 消耗,提高模型對(duì)關(guān)鍵信息的關(guān)注度。

3.6 提示工程優(yōu)化

當(dāng)前問題:

現(xiàn)有提示模板相對(duì)簡(jiǎn)單

缺乏針對(duì)不同問題類型的專門指導(dǎo)

改進(jìn)方案:

def create_advanced_prompt(query, context, question_type):
    if question_type == "factual":
        template = """
        你是一個(gè)精確的事實(shí)回答助手。以下是與問題相關(guān)的信息:
        {context}
        
        問題: {query}
        請(qǐng)基于以上信息提供精確的事實(shí)回答。如信息不足,請(qǐng)明確指出。請(qǐng)?jiān)诨卮鹉┪矘?biāo)明信息來源。
        """
    elif question_type == "analytical":
        template = """
        你是一個(gè)分析型助手。以下是相關(guān)參考信息:
        {context}
        
        問題: {query}
        請(qǐng)分析以上信息,提供深入見解。注意分析信息的一致性與可靠性,標(biāo)明不同來源間的差異。最后給出綜合結(jié)論并注明信息來源。
        """
    # 更多問題類型...
    
    # 添加思維鏈指導(dǎo)
    template += """
    思考步驟:
    1. 提取問題關(guān)鍵點(diǎn)
    2. 識(shí)別相關(guān)文檔中最有價(jià)值的信息
    3. 對(duì)比不同來源信息
    4. 形成清晰、全面的回答
    """
    
    return template.format(cnotallow=context, query=query)

預(yù)期效果:更加結(jié)構(gòu)化和針對(duì)性的回答,提高回答質(zhì)量和可信度。

3.7 元數(shù)據(jù)增強(qiáng)與過濾

當(dāng)前問題:

元數(shù)據(jù)利用不足

缺乏基于元數(shù)據(jù)的預(yù)過濾和后過濾

改進(jìn)方案:

# 豐富元數(shù)據(jù)
metadatas = [{
    "source": file_name,
    "doc_id": doc_id,
    "date_processed": datetime.now().isoformat(),
    "chunk_index": i,
    "total_chunks": len(chunks),
    "document_type": detect_document_type(text),
    "language": detect_language(chunk),
    "entities": extract_entities(chunk)
} for i, chunk in enumerate(chunks)]


# 檢索時(shí)使用元數(shù)據(jù)過濾
results = COLLECTION.query(
    query_embeddings=query_embedding,
    n_results=10,
    where={"document_type": {"$in": ["report", "research_paper"]}},
    include=['documents', 'metadatas']
)

預(yù)期效果:更精準(zhǔn)的檢索結(jié)果篩選,減少噪音,提高答案質(zhì)量。

3.8 向量化模型升級(jí)

當(dāng)前問題:

all-MiniLM-L6-v2 維度較低(384 維)

中文表示能力有限

改進(jìn)方案:

# 升級(jí)為更強(qiáng)大的雙語模型
from sentence_transformers import SentenceTransformer
EMBED_MODEL = SentenceTransformer('BAAI/bge-large-zh-v1.5') # 1024維,中文效果更好


# 或考慮OpenAI嵌入模型
import openai
embeddings = openai.Embedding.create(
    input=chunks, 
    model="text-embedding-ada-002"
)

預(yù)期效果:提高語義理解能力和檢索精度,尤其是中文文檔。

3.9 評(píng)估與反饋機(jī)制

當(dāng)前問題:

缺乏回答質(zhì)量評(píng)估

無法迭代改進(jìn)

改進(jìn)方案:

def evaluate_response(query, response, retrieved_docs):
    # LLM自評(píng)估
    evaluation_prompt = f"""
    問題: {query}
    回答: {response}
    請(qǐng)?jiān)u估這個(gè)回答的質(zhì)量(1-10分),考慮以下標(biāo)準(zhǔn):
    1. 準(zhǔn)確性: 回答是否符合檢索文檔的事實(shí)?
    2. 完整性: 回答是否全面覆蓋問題的各個(gè)方面?
    3. 相關(guān)性: 回答是否切中問題要點(diǎn)?
    4. 一致性: 回答內(nèi)部是否存在矛盾?
    請(qǐng)?jiān)敿?xì)說明評(píng)分理由。
    """
    
    feedback = llm_client.generate(evaluation_prompt)
    
    # 存儲(chǔ)評(píng)估結(jié)果用于系統(tǒng)優(yōu)化
    save_evaluation_result(query, response, retrieved_docs, feedback)
    
    return feedback

預(yù)期效果:建立持續(xù)評(píng)估和改進(jìn)機(jī)制,累積數(shù)據(jù)用于系統(tǒng)優(yōu)化。

3.10 緩存與預(yù)計(jì)算策略

當(dāng)前問題:

重復(fù)問題重復(fù)計(jì)算

實(shí)時(shí)響應(yīng)不夠快

改進(jìn)方案:

# 問題-檢索結(jié)果緩存
import hashlib
import pickle
from functools import lru_cache


@lru_cache(maxsize=100)
def cached_retrieval(query):
    # 計(jì)算查詢哈希
    query_hash = hashlib.md5(query.encode()).hexdigest()
    cache_file = f"cache/{query_hash}.pkl"
    
    # 檢查緩存
    try:
        with open(cache_file, 'rb') as f:
            return pickle.load(f)
    except FileNotFoundError:
        # 執(zhí)行檢索
        results = perform_retrieval(query)
        # 保存到緩存
        os.makedirs("cache", exist_ok=True)
        with open(cache_file, 'wb') as f:
            pickle.dump(results, f)
        return results

4、寫在最后

升級(jí)版本的項(xiàng)目源碼在目前開源版本的基礎(chǔ)上,主要完成了前三個(gè)方面(分塊策略、混合檢索策略、重排序機(jī)制)的代碼升級(jí),源碼發(fā)布在了知識(shí)星球內(nèi),供有一定實(shí)踐經(jīng)驗(yàn)的盆友測(cè)試。剩余其他 7 個(gè)維度的示例代碼,后續(xù)會(huì)持續(xù)發(fā)布,并結(jié)合真實(shí)案例進(jìn)行演示。

圖片

另外有個(gè)彩蛋是,為了讓大家更加可視化的了解整個(gè)調(diào)優(yōu)過程,我在代碼升級(jí)的同時(shí)做了 UI 優(yōu)化,相比開源項(xiàng)目新增了一個(gè)”分塊可視化“的選項(xiàng)卡,其中直觀展示了當(dāng)前代碼中的核心模型和方法,以及分塊之后的實(shí)際內(nèi)容預(yù)覽,對(duì)調(diào)試過程會(huì)更加便利些。

責(zé)任編輯:龐桂玉 來源: 韋東東
相關(guān)推薦

2011-06-21 16:38:34

SEO

2025-03-10 09:20:00

2011-06-09 10:36:51

IPv6IPv6部署

2024-10-17 09:09:04

2012-04-16 09:50:08

2009-06-25 13:37:54

2024-11-29 08:20:22

Autowired場(chǎng)景項(xiàng)目

2015-05-28 10:28:49

xUtils

2024-11-12 10:30:54

Docker部署數(shù)據(jù)庫

2024-06-04 00:10:00

開發(fā)拷貝

2024-09-12 08:32:42

2017-02-09 15:54:26

編程奇葩程序員

2011-07-12 09:25:45

HTML 5

2017-02-08 14:23:46

編程冒牌程序員

2025-01-02 11:54:01

2025-02-06 11:20:00

開發(fā)工具AI

2010-05-04 08:44:42

Java并發(fā)模型

2023-11-06 13:04:59

Python日志庫

2021-08-23 13:02:50

MySQLJOIN數(shù)據(jù)庫

2021-08-04 17:20:30

阿里巴巴AsyncJava
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)