偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RAG—Chunking策略實(shí)戰(zhàn)

人工智能
在 RAG 系統(tǒng)中,即便采用性能卓越的 LLM 并反復(fù)打磨 Prompt,問答仍可能出現(xiàn)上下文缺失、事實(shí)性錯(cuò)誤或拼接不連貫等問題。多數(shù)團(tuán)隊(duì)會(huì)頻繁更換檢索算法與 Embedding模型,但收益常常有限。

一、背景

二、什么是分塊(Chunking)

三、為何要對(duì)內(nèi)容做分塊處理

四、分塊策略詳解

    1. 基礎(chǔ)分塊

    2. 結(jié)構(gòu)感知分塊

    3. 語義與主題分塊

    4. 高級(jí)分塊

    5. 混合分塊

五、結(jié)論

一、背 景

在 RAG 系統(tǒng)中,即便采用性能卓越的 LLM 并反復(fù)打磨 Prompt,問答仍可能出現(xiàn)上下文缺失、事實(shí)性錯(cuò)誤或拼接不連貫等問題。多數(shù)團(tuán)隊(duì)會(huì)頻繁更換檢索算法與 Embedding模型,但收益常常有限。真正的瓶頸,往往潛伏在數(shù)據(jù)入庫之前的一個(gè)細(xì)節(jié)——文檔分塊(chunking)。不當(dāng)?shù)姆謮K會(huì)破壞語義邊界,拆散關(guān)鍵線索并與噪聲糾纏,使被檢索的片段呈現(xiàn)“順序錯(cuò)亂、信息殘缺”的面貌。在這樣的輸入下,再?gòu)?qiáng)大的模型也難以基于支離破碎的知識(shí)推理出完整、可靠的答案。某種意義上,分塊質(zhì)量幾乎決定了RAG的性能上限——它決定知識(shí)是以連貫的上下文呈現(xiàn),還是退化為無法拼合的碎片。

在實(shí)際場(chǎng)景中,最常見的錯(cuò)誤是按固定長(zhǎng)度生硬切割,忽略文檔的結(jié)構(gòu)與語義:定義與信息被切開、表頭與數(shù)據(jù)分離、步驟說明被截?cái)唷⒋a與注釋脫節(jié),結(jié)果就是召回命中卻無法支撐結(jié)論,甚至誘發(fā)幻覺與錯(cuò)誤引用。相反,高質(zhì)量的分塊應(yīng)盡量貼合自然邊界(標(biāo)題、段落、列表、表格、代碼塊等),以適度重疊保持上下文連續(xù),并保留必要的來源與章節(jié)元數(shù)據(jù),確保可追溯與重排可用。當(dāng)分塊尊重文檔的敘事與結(jié)構(gòu)時(shí),檢索的相關(guān)性與答案的事實(shí)一致性往往顯著提升,遠(yuǎn)勝于一味更換向量模型或調(diào)參;換言之,想要真正改善 RAG 的穩(wěn)健性與上限,首先要把“知識(shí)如何被切開并呈現(xiàn)給模型”這件事做好。

PS:本文主要是針對(duì)中文文檔類型的嵌入進(jìn)行實(shí)戰(zhàn)。

二、什么是分塊(Chunking)

分塊是將大塊文本分解成較小段落的過程,這使得文本數(shù)據(jù)更易于管理和處理。通過分塊,我們能夠更高效地進(jìn)行內(nèi)容嵌入(embedding),并顯著提升從向量數(shù)據(jù)庫中召回內(nèi)容的相關(guān)性和準(zhǔn)確性。

在實(shí)際操作中,分塊的好處是多方面的。首先,它能夠提高模型處理的效率,因?yàn)檩^小的文本段落更容易進(jìn)行嵌入和檢索。

其次,分塊后的文本能夠更精確地匹配用戶查詢,從而提供更相關(guān)的搜索結(jié)果。這對(duì)于需要高精度信息檢索和內(nèi)容生成的應(yīng)用程序尤為重要。

通過優(yōu)化內(nèi)容的分塊和嵌入策略,我們可以最大化LLM在各種應(yīng)用場(chǎng)景中的性能。分塊技術(shù)不僅提高了內(nèi)容召回的準(zhǔn)確性,還提升了整體系統(tǒng)的響應(yīng)速度和用戶體驗(yàn)。

因此,在構(gòu)建和優(yōu)化基于LLM的應(yīng)用程序時(shí),理解和應(yīng)用分塊技術(shù)是不可或缺的步驟。

分塊過程中主要的兩個(gè)概念:chunk_size塊的大小,chunk_overlap重疊窗口。

圖片圖片

三、為何要對(duì)內(nèi)容做分塊處理

  • 模型上下文窗口限制:LLM無法一次處理超長(zhǎng)文本。分塊的目的在于將長(zhǎng)文檔切成模型可穩(wěn)定處理的中等粒度片段,并盡量對(duì)齊自然語義邊界(如標(biāo)題、段落、句子、代碼塊),避免硬切導(dǎo)致關(guān)鍵信息被截?cái)嗷蛘Z義漂移。即便使用長(zhǎng)上下文模型,過長(zhǎng)輸入也會(huì)推高成本并稀釋信息密度,合理分塊仍是必需的前置約束。
  • 檢索的信噪比:塊過大時(shí)無關(guān)內(nèi)容會(huì)稀釋信號(hào)、降低相似度判別力;塊過小時(shí)語境不足、容易“只命中詞不命中義”。合適的塊粒度可在召回與精度間取得更好平衡,既覆蓋用戶意圖,又不引入多余噪聲。在一定程度上提升檢索相關(guān)性的同時(shí)又能保證結(jié)果穩(wěn)定性。
  • 語義連續(xù)性:跨段落或跨章節(jié)的語義關(guān)系常在邊界處被切斷。通過設(shè)置適度的 chunk_overlap,可保留跨塊線索、減少關(guān)鍵定義/條件被“切開”的風(fēng)險(xiǎn)。對(duì)于強(qiáng)結(jié)構(gòu)文檔,優(yōu)先讓邊界貼合標(biāo)題層級(jí)與句子斷點(diǎn);必要時(shí)在檢索階段做輕量鄰近擴(kuò)展,以提升答案的連貫性與可追溯性,同時(shí)避免重復(fù)內(nèi)容擠占上下文預(yù)算。

總之理想的分塊是在“上下文完整性”和“信息密度”之間取得動(dòng)態(tài)平衡:chunk_size決定信息承載量,chunk_overlap 用于彌補(bǔ)邊界斷裂并維持語義連續(xù)。只要邊界對(duì)齊語義、粒度貼合內(nèi)容,檢索與生成的質(zhì)量就能提升。

圖片圖片

四、分塊策略詳解

基礎(chǔ)分塊

基于固定長(zhǎng)度分塊

  • 分塊策略:按預(yù)設(shè)字符數(shù) chunk_size 直接切分,不考慮文本結(jié)構(gòu)。
  • 優(yōu)點(diǎn):實(shí)現(xiàn)最簡(jiǎn)單、速度快、對(duì)任意文本通用。
  • 缺點(diǎn):容易破壞語義邊界;塊過大容易引入較多噪聲,過小則會(huì)導(dǎo)致上下文不足。
  • 適用場(chǎng)景:結(jié)構(gòu)性弱的純文本,或數(shù)據(jù)預(yù)處理初期的基線方案。
from langchain_text_splitters import CharacterTextSplitter


splitter = CharacterTextSplitter(
    separator="",        # 純按長(zhǎng)度切
    chunk_size=600,      # 依據(jù)實(shí)驗(yàn)與模型上限調(diào)整
    chunk_overlap=90,    # 15% 重疊
)
chunks = splitter.split_text(text)
  • 參數(shù)建議(僅限中文語料建議):

chunk_size:300–800 字優(yōu)先嘗試;若嵌入模型最佳輸入為 512/1024 tokens,可折算為約 350/700 中文字符起步。

chunk_overlap:10%–20% 起步;超過 30% 通常導(dǎo)致索引體積與檢索開銷顯著上升,對(duì)實(shí)際性能起負(fù)作用,最后的效果并不會(huì)得到明顯提升。

基于句子的分塊

  • 分塊策略:先按句子切分,再將若干句子聚合成滿足chunk_size的塊;保證最基本的語義完整性。
  • 優(yōu)點(diǎn):句子級(jí)完整性最好。對(duì)問句/答句映射友好。便于高質(zhì)量引用。
  • 缺點(diǎn):中文分句需特別處理。僅句子級(jí)切分可能導(dǎo)致塊過短,需后續(xù)聚合。
  • 適用場(chǎng)景:法律法規(guī)、新聞、公告、FAQ 等以句子為主的文本。
  • 中文分句注意事項(xiàng):

不要直接用 NLTK 英文 Punkt:無法識(shí)別中文標(biāo)點(diǎn),分句會(huì)失敗或異常。

可以直接使用以下內(nèi)容進(jìn)行分句:

1)基于中文標(biāo)點(diǎn)的正則:按“。???;”等切分,保留引號(hào)與省略號(hào)等邊界。

2)使用支持中文的 NLP 庫進(jìn)行更精細(xì)的分句:

3)HanLP(推薦,工業(yè)級(jí),支持繁多語言學(xué)特性)Stanza(清華/斯坦福合作,中文支持較好)spaCy + pkuseg 插件(或 zh-core-web-sm/med/lg 生態(tài))

  • 示例(適配常見中文標(biāo)點(diǎn),基于正則的分句):
import re


def split_sentences_zh(text: str):
    # 在句末標(biāo)點(diǎn)(。!?;)后面帶可選引號(hào)的場(chǎng)景斷句
    pattern = re.compile(r'([^。?。?;]*[。?。?;]+|[^。?。?;]+$)')
    sentences = [m.group(0).strip() for m in pattern.finditer(text) if m.group(0).strip()]
    return sentences


def sentence_chunk(text: str, chunk_size=600, overlap=80):
    sents = split_sentences_zh(text)
    chunks, buf = [], ""
    for s in sents:
        if len(buf) + len(s) <= chunk_size:
            buf += s
        else:
            if buf:
                chunks.append(buf)
            # 簡(jiǎn)單重疊:從當(dāng)前塊尾部截取 overlap 字符與下一句拼接
            buf = (buf[-overlap:] if overlap > 0 and len(buf) > overlap else "") + s
    if buf:
        chunks.append(buf)
    return chunks


chunks = sentence_chunk(text, chunk_size=600, overlap=90)

HanLP 分句示例:

from hanlp_common.constant import ROOT
import hanlp


tokenizer = hanlp.load('PKU_NAME_MERGED_SIX_MONTHS_CONVSEG')  # 或句法/句子級(jí)管線
# HanLP 高層 API 通常通過句法/語料管線獲得句子邊界,具體以所用版本 API 為準(zhǔn)
# 將句子列表再做聚合為 chunk_size

基于遞歸字符分塊

  • 分塊策略:給定一組由“粗到細(xì)”的分隔符(如段落→換行→空格→字符),自上而下遞歸切分,在不超出 chunk_size 的前提下盡量保留自然語義邊界。
  • 優(yōu)點(diǎn):在“保持語義邊界”和“控制塊大小”之間取得穩(wěn)健平衡,對(duì)大多數(shù)文本即插即用。
  • 缺點(diǎn):分隔符配置不當(dāng)會(huì)導(dǎo)致塊粒度失衡,極度格式化文本(表格/代碼)效果一般。
  • 適用場(chǎng)景:綜合性語料、說明文檔、報(bào)告、知識(shí)庫條目。
import re
from langchain_text_splitters import RecursiveCharacterTextSplitter


separators = [
    r"\n#{1,6}\s",                 # 標(biāo)題
    r"\n\d+(?:\.\d+)*\s",          # 數(shù)字編號(hào)標(biāo)題 1. / 2.3. 等
    "\n\n",                        # 段落
    "\n",                          # 行
    " ",                           # 空格
    "",                            # 兜底字符級(jí)
]
splitter = RecursiveCharacterTextSplitter(
    separators=separators,
    chunk_size=700,
    chunk_overlap=100,
    is_separator_regex=True,       # 告訴分割器上面包含正則
)
chunks = splitter.split_text(text)
  • 參數(shù)與分隔符建議(僅中文文檔建議):

chunk_size:400–800 字符;如果內(nèi)容更技術(shù)化、長(zhǎng)句多時(shí)可適當(dāng)上調(diào)該數(shù)值。

chunk_overlap:10%–20%。

separators(由粗到細(xì),按需裁剪):

1)章節(jié)/標(biāo)題:正則 r"^#{1,6}\s"(Markdown 標(biāo)題)、r"^\d+(.\d+)*\s"(編號(hào)標(biāo)題)

2)段落:"\n\n"

3)換行:"\n"

4)空格:" "

5)兜底:""

總結(jié)

  • 調(diào)優(yōu)流程:

固定檢索與重排,只動(dòng)分塊參數(shù)。

用驗(yàn)證集計(jì)算 Recall@k、nDCG、MRR、來源命中文檔覆蓋率、答案事實(shí)性(faithfulness)。

觀察塊長(zhǎng)分布:若長(zhǎng)尾太長(zhǎng),適當(dāng)收緊chunk_size 或增加粗粒度分隔符;若過短,放寬chunk_size 或降低分隔符優(yōu)先級(jí)。

  • 重疊的成本與收益:

收益:緩解邊界斷裂,提升答案連貫性與可追溯性。

成本:索引尺寸增長(zhǎng)、召回重復(fù)塊增多、rerank 負(fù)載提升。通常不建議超過 20%–25%。

  • 組合技巧:

先遞歸分塊,再對(duì)“異常長(zhǎng)句”或“跨段引用”場(chǎng)景加一點(diǎn)點(diǎn)額外 overlap。

對(duì)標(biāo)題塊注入父級(jí)標(biāo)題上下文,提高定位能力與可解釋性。

  • 何時(shí)切換策略:

若問答頻繁丟上下文或引用斷裂:增大overlap或改用句子/結(jié)構(gòu)感知策略。

若召回含噪過多:減小 chunk_size 或引入更強(qiáng)的結(jié)構(gòu)分隔符。

結(jié)構(gòu)感知分塊

利用文檔固有結(jié)構(gòu)(標(biāo)題層級(jí)、列表、代碼塊、表格、對(duì)話輪次)作為分塊邊界,邏輯清晰、可追溯性強(qiáng),能在保證上下文完整性的同時(shí)提升檢索信噪比。

結(jié)構(gòu)化文本分塊
  • 分塊策略以標(biāo)題層級(jí)(H1–H6、編號(hào)標(biāo)題)或語義塊(段落、列表、表格、代碼塊)為此類型文檔的天然邊界,對(duì)過長(zhǎng)的結(jié)構(gòu)塊再做二次細(xì)分,對(duì)過短的進(jìn)行相鄰合并。
  • 實(shí)施步驟

解析結(jié)構(gòu):Markdown 用解析器remark/markdown-it-py或正則識(shí)別標(biāo)題與語塊;HTML用 DOMBeautifulSoup/Cheerio遍歷 Hx、p、li、pre、table 等。

生成章節(jié):以標(biāo)題為父節(jié)點(diǎn),將其后的連續(xù)兄弟節(jié)點(diǎn)納入該章節(jié),直至遇到同級(jí)或更高層級(jí)標(biāo)題。

二次切分:章節(jié)超出 chunk_size時(shí),優(yōu)先按子標(biāo)題/段落切,再不足時(shí)按句子或遞歸字符切分。

合并短塊:低于 min_chunk_chars 的塊與相鄰塊合并,優(yōu)先與同一父標(biāo)題下的前后塊。

上下文重疊:優(yōu)先用“結(jié)構(gòu)重疊”(父級(jí)標(biāo)題路徑、前一小節(jié)標(biāo)題+摘要),再輔以小比例字符overlap(10%–15%)。

寫入 metadata。

  • 示例代碼
import re
from typing import List, Dict


heading_pat = re.compile(r'^(#{1,6})\s+(.*)$')  # 標(biāo)題
fence_pat = re.compile(r'^```')                 # fenced code fence


def split_markdown_structure(text: str, chunk_size=900, min_chunk=250, overlap_ratio=0.1) -> List[Dict]:
    lines = text.splitlines()
    sections = []
    in_code = False
    current = {"level": 0, "title": "", "content": [], "path": []}
    
    path_stack = []  # [(level, title)]
    
    for ln in lines:
        if fence_pat.match(ln):
            in_code = not in_code
        m = heading_pat.match(ln) if not in_code else None
        if m:
            if current["content"]:
                sections.append(current)
            level = len(m.group(1))
            title = m.group(2).strip()


            while path_stack and path_stack[-1][0] >= level:
                path_stack.pop()
            path_stack.append((level, title))
            breadcrumbs = [t for _, t in path_stack]
            current = {"level": level, "title": title, "content": [], "path": breadcrumbs}
        else:
            current["content"].append(ln)
    
    if current["content"]:
        sections.append(current)
    
    # 通過二次拆分/合并將部分平鋪成塊
    chunks = []
    def emit_chunk(text_block: str, path: List[str], level: int):
        chunks.append({
            "text": text_block.strip(),
            "meta": {
                "section_title": path[-1] if path else "",
                "breadcrumbs": path,
                "section_level": level,
            }
        })
    
    for sec in sections:
        raw = "\n".join(sec["content"]).strip()
        if not raw:
            continue
        if len(raw) <= chunk_size:
            emit_chunk(raw, sec["path"], sec["level"])
        else:
            paras = [p.strip() for p in raw.split("\n\n") if p.strip()]
            buf = ""
            for p in paras:
                if len(buf) + len(p) + 2 <= chunk_size:
                    buf += (("\n\n" + p) if buf else p)
                else:
                    if buf:
                        emit_chunk(buf, sec["path"], sec["level"])
                    buf = p
            if buf:
                emit_chunk(buf, sec["path"], sec["level"])
    
    merged = []
    for ch in chunks:
        if not merged:
            merged.append(ch)
            continue
        if len(ch["text"]) < min_chunk and merged[-1]["meta"]["breadcrumbs"] == ch["meta"]["breadcrumbs"]:
            merged[-1]["text"] += "\n\n" + ch["text"]
        else:
            merged.append(ch)
    
    overlap = int(chunk_size * overlap_ratio)
    for ch in merged:
        bc = " > ".join(ch["meta"]["breadcrumbs"][-3:])
        prefix = f"[{bc}]\n" if bc else ""
        if prefix and not ch["text"].startswith(prefix):
            ch["text"] = prefix + ch["text"]
        # optional character overlap can在檢索階段用鄰接聚合替代,這里略
    
    return merged
  • 參數(shù)建議(中文文檔)

chunk_size:600–1000 字;技術(shù)文/長(zhǎng)段落可取上限,繼續(xù)適當(dāng)增加。

min_chunk_chars:200–300 字(小于則合并)。

chunk_overlap:10%–15%;若使用“父級(jí)標(biāo)題路徑 + 摘要”作為結(jié)構(gòu)重疊,可降至 5%–10%。

對(duì)話式分塊

  • 分塊策略

以“輪次/說話人”為邊界,優(yōu)先按對(duì)話鄰接對(duì)和小段話題窗口聚合。重疊采用“輪次重疊”而非單純字符重疊,保證上下文流暢。

  • 適用場(chǎng)景

客服對(duì)話、訪談、會(huì)議紀(jì)要、技術(shù)支持工單等多輪交流。

  • 檢索期鄰

接聚合在檢索階段對(duì)對(duì)話塊做“鄰接擴(kuò)展”:取被召回塊前后各 1–2 輪上下文(或相鄰塊拼接)作為最終送審上下文,以提高回答連貫性與可追溯性。

  • 與重排協(xié)同

可提升對(duì)“誰說的、在哪段說的”的判斷力。

  • 示例代碼:(按輪次滑動(dòng)窗口分塊)
from typing import List, Dict


def chunk_dialogue(turns: List[Dict], max_turns=10, max_chars=900, overlap_turns=2):
    """
    turns: [{"speaker":"User","text":"..." , "ts_start":123, "ts_end":130}, ...]
    """
    chunks = []
    i = 0
    while i < len(turns):
        j = i
        char_count = 0
        speakers = set()
        while j < len(turns):
            t = turns[j]
            uttr_len = len(t["text"])
            # 若單條超長(zhǎng),允許在句級(jí)二次切分(此處略),但不跨 speaker
            if (j - i + 1) > max_turns or (char_count + uttr_len) > max_chars:
                break
            char_count += uttr_len
            speakers.add(t["speaker"])
            j += 1
        
        if j > i:
            window = turns[i:j]
        elif i < len(turns):
            window = [turns[i]]
        else:
            break
        text = "\n".join([f'{t["speaker"]}: {t["text"]}' for t in window])
        meta = {
            "speakers": list(speakers),
            "turns_range": (i, j - 1),
            "ts_start": window[0].get("ts_start"),
            "ts_end": window[-1].get("ts_end"),
        }
        chunks.append({"text": text, "meta": meta})
        
        # 按輪次重疊回退
        if j >= len(turns):
            break
        next_start = i + len(window) - overlap_turns
        i = max(next_start, i + 1)  # 確保至少前進(jìn)1步
    return chunks
  • 參數(shù)建議

max_turns_per_chunk:6–12 輪起步;語速快信息密度高可取 8–10。

max_chars_per_chunk:600–1000 字;若存在長(zhǎng)段獨(dú)白,優(yōu)先句級(jí)再切,不跨說話人。

overlap_turns:1–2 輪;保證上一問下一答的連續(xù)性。

keep_pairing:不要拆開明顯的問答對(duì);若 chunk 臨界,寧可擴(kuò)一輪或后移切分點(diǎn)。

總結(jié)

  • 首選用結(jié)構(gòu)邊界做第一次切分,再用句級(jí)/遞歸策略做二次細(xì)分。
  • 優(yōu)先使用“結(jié)構(gòu)重疊”(父標(biāo)題路徑、上段標(biāo)題+摘要、相鄰發(fā)言)替代大比例字符重疊。
  • 為每個(gè)塊寫好 metadata,可顯著提升檢索質(zhì)量與可解釋性。
  • 對(duì) PDF/HTML 先去噪(頁眉頁腳、導(dǎo)航、廣告等),避免把噪聲索引進(jìn)庫。

語義與主題分塊

該方法不依賴文檔的物理結(jié)構(gòu),而是依據(jù)語義連續(xù)性與話題轉(zhuǎn)移來決定切分點(diǎn),尤其適合希望“塊內(nèi)高度內(nèi)聚、塊間清晰分界”的知識(shí)庫與研究類文本。

語義分塊

  • 分塊策略

對(duì)文本先做句級(jí)切分,計(jì)算句子或短段的向量表示;

當(dāng)相鄰語義的相似度顯著下降(發(fā)生“語義突變”)時(shí)設(shè)為切分點(diǎn)。

  • 適用場(chǎng)景

專題化、論證結(jié)構(gòu)明顯的文檔:

白皮書、論文、技術(shù)手冊(cè)、FAQ 聚合頁;

需要高內(nèi)聚檢索與高可追溯性。

  • 使用流程

句級(jí)切分:先用中文分句(標(biāo)點(diǎn)/中文分句模型)得到句子序列。

向量化:對(duì)每個(gè)句子編碼,開啟歸一化(normalize)以便用余弦相似度。

突變檢測(cè):

1)簡(jiǎn)單粗暴的方法:sim(i, i-1) 低于閾值則切分。

2)穩(wěn)健的方法:與“前后窗口的均值向量”比較,計(jì)算新穎度 novelty = 1 - cos(emb_i, mean_emb_window),新穎度高于閾值則切分。

3)平滑的方法:對(duì)相似度/新穎度做移動(dòng)平均,降低抖動(dòng)。

約束與修正:設(shè)置最小/最大塊長(zhǎng),避免過碎或過長(zhǎng),必要時(shí)進(jìn)行相鄰塊合并。

  • 與檢索/重排的協(xié)同召回時(shí)可做“鄰接擴(kuò)展”(把被命中的塊前后各追加一兩句),再做重排序。語義分塊的高內(nèi)聚可讓 重排序更精準(zhǔn)地區(qū)分相近候選。
  • 代碼示例
from typing import List, Dict, Tuple
import numpy as np
from sentence_transformers import SentenceTransformer
import re


def split_sentences_zh(text: str) -> List[str]:
    # 簡(jiǎn)易中文分句,可替換為 HanLP/Stanza 更穩(wěn)健的實(shí)現(xiàn)
    pattern = re.compile(r'([^。?。?;]*[。!?;]+|[^。???;]+$)')
    return [m.group(0).strip() for m in pattern.finditer(text) if m.group(0).strip()]


def rolling_mean(vecs: np.ndarray, i: int, w: int) -> np.ndarray:
    s = max(0, i - w)
    e = min(len(vecs), i + w + 1)
    return vecs[s:e].mean(axis=0)


def semantic_chunk(
    text: str,
    model_name: str = "BAAI/bge-m3",
    window_size: int = 2,
    min_chars: int = 350,
    max_chars: int = 1100,
    lambda_std: float = 0.8,
    overlap_chars: int = 80,
) -> List[Dict]:
    sents = split_sentences_zh(text)
    if not sents:
        return []
    
    model = SentenceTransformer(model_name)
    emb = model.encode(sents, normalize_embeddings=True, batch_size=64, show_progress_bar=False)
    emb = np.asarray(emb)
    
    # 基于窗口均值的“新穎度”分?jǐn)?shù)
    novelties = []
    for i in range(len(sents)):
        ref = rolling_mean(emb, i-1, window_size) if i > 0 else emb[0]
        ref = ref / (np.linalg.norm(ref) + 1e-8)
        novelty = 1.0 - float(np.dot(emb[i], ref))
        novelties.append(novelty)
    novelties = np.array(novelties)
    
    # 相對(duì)閾值:μ + λσ
    mu, sigma = float(novelties.mean()), float(novelties.std() + 1e-8)
    threshold = mu + lambda_std * sigma
    
    chunks, buf, start_idx = [], "", 0
    def flush(end_idx: int):
        nonlocal buf, start_idx
        if buf.strip():
            chunks.append({
                "text": buf.strip(),
                "meta": {"start_sent": start_idx, "end_sent": end_idx-1}
            })
        buf, start_idx = "", end_idx
    
    for i, s in enumerate(sents):
        # 若超長(zhǎng)則先沖洗
        if len(buf) + len(s) > max_chars and len(buf) >= min_chars:
            flush(i)
            # 結(jié)構(gòu)化重疊:附加上一個(gè)塊的尾部
            if overlap_chars > 0 and len(s) < overlap_chars:
                buf = s
                continue
        
        buf += s
        
        # 達(dá)到最小長(zhǎng)度后遇到突變則切分
        if len(buf) >= min_chars and novelties[i] > threshold:
            flush(i + 1)
    
    if buf:
        flush(len(sents))
    
    return chunks
  • 參數(shù)調(diào)優(yōu)說明(僅作參考)

閾值的含義:語義變化敏感度控制器,越低越容易切、越高越保守。

設(shè)定方式:

1)絕對(duì)閾值:例如使用余弦相似度,若 sim < 0.75 則切分(需按語料校準(zhǔn))。

2)相對(duì)閾值:對(duì)全篇的相似度/新穎度分布估計(jì)均值μ與標(biāo)準(zhǔn)差σ,使用 μ ± λσ 作為閾值,更穩(wěn)健。

初始的配置建議(僅限于中文技術(shù)/說明文檔):

       1)窗口大小 window_size:2–4 句

       2)最小/最大塊長(zhǎng):min_chunk_chars=300–400,max_chunk_chars=1000–1200

       3)閾值策略:novelty > μ + 0.8σ 或相似度 < μ - 0.8σ(先粗調(diào)后微調(diào))

       4)overlap:10% 左右或按“附加上一句”做輕量輪次重疊

主題的分塊

  • 分塊策略

利用主題模型或聚類算法在“宏觀話題”發(fā)生切換時(shí)進(jìn)行切分,更多的關(guān)注章節(jié)級(jí)、段落級(jí)的主題邊界。該類分塊策略主要適合長(zhǎng)篇、多主題材料。

  • 適用場(chǎng)景

報(bào)告、書籍、長(zhǎng)調(diào)研文檔、綜合評(píng)審;

當(dāng)文檔內(nèi)部確有較穩(wěn)定的“話題塊”。

  • 使用流程(最好用“句向量 + 聚類 + 序列平滑”而非純 LDA)

句級(jí)切分并編碼:首先通過向量模型得到句向量,normalize。

文檔內(nèi)或語料級(jí)聚類:

1)文檔內(nèi)小規(guī)模:MiniBatchKMeans(k=3–8 先驗(yàn))或 SpectralClustering。

2)語料級(jí)統(tǒng)一主題:在大量文檔上聚類(或用 HDBSCAN+UMAP),再將每篇文檔的句子映射到最近主題中心。

序列平滑與解碼:

      1) 對(duì)句子的主題標(biāo)簽做滑窗多數(shù)投票或一階馬爾可夫平滑,避免頻繁抖動(dòng)。

      2)當(dāng)主題標(biāo)簽穩(wěn)定變化并滿足最小塊長(zhǎng)時(shí),設(shè)為切分點(diǎn)。

主題命名:用 KeyBERT/TF-IDF 在每個(gè)塊內(nèi)抽關(guān)鍵詞,或用小模型生成一句話主題摘要,寫入 metadata。

約束:min/max_chars,保留代碼/表格等原子塊,必要時(shí)與結(jié)構(gòu)邊界結(jié)合使用。

  • 代碼示例(KMeans 文檔內(nèi)聚類 + 序列平滑)
from typing import List, Dict
import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.cluster import KMeans
import re


def split_sentences_zh(text: str) -> List[str]:
    pattern = re.compile(r'([^。???;]*[。???;]+|[^。???;]+$)')
    return [m.group(0).strip() for m in pattern.finditer(text) if m.group(0).strip()]


def topic_chunk(
    text: str,
    k_topics: int = 5,
    min_chars: int = 500,
    max_chars: int = 1400,
    smooth_window: int = 2,
    model_name: str = "BAAI/bge-m3"
) -> List[Dict]:
    sents = split_sentences_zh(text)
    if not sents:
        return []
    
    model = SentenceTransformer(model_name)
    emb = model.encode(sents, normalize_embeddings=True, batch_size=64, show_progress_bar=False)
    emb = np.asarray(emb)
    
    km = KMeans(n_clusters=k_topics, n_init="auto", random_state=42)
    labels = km.fit_predict(emb)
    
    # 簡(jiǎn)單序列平滑:滑窗多數(shù)投票
    smoothed = labels.copy()
    for i in range(len(labels)):
        s = max(0, i - smooth_window)
        e = min(len(labels), i + smooth_window + 1)
        window = labels[s:e]
        vals, counts = np.unique(window, return_counts=True)
        smoothed[i] = int(vals[np.argmax(counts)])
    
    chunks, buf, start_idx, cur_label = [], "", 0, smoothed[0]
    def flush(end_idx: int):
        nonlocal buf, start_idx
        if buf.strip():
            chunks.append({
                "text": buf.strip(),
                "meta": {"start_sent": start_idx, "end_sent": end_idx-1, "topic": int(cur_label)}
            })
        buf, start_idx = "", end_idx
    
    for i, s in enumerate(sents):
        switched = smoothed[i] != cur_label
        over_max = len(buf) + len(s) > max_chars
        under_min = len(buf) < min_chars
        
        # 嘗試延后切分,保證最小塊長(zhǎng)
        if switched and not under_min:
            flush(i)
            cur_label = smoothed[i]
        
        if over_max and not under_min:
            flush(i)
        
        buf += s
    
    if buf:
        flush(len(sents))
    
    return chunks
  • 一些參數(shù)對(duì)結(jié)果的影響

k(主題數(shù)):難以精準(zhǔn)預(yù)設(shè),可通過輪廓系數(shù)(silhouette)/肘部法初篩,再結(jié)合領(lǐng)域先驗(yàn)與人工校正。

HDBSCAN:min_cluster_size 影響較大,過小會(huì)碎片化,過大則合并不同話題。

min_topic_span_sents:如 5–8 句,防止標(biāo)簽抖動(dòng)導(dǎo)致過密切分。

小文檔不宜用:樣本太少時(shí)主題不可分,優(yōu)先用語義分塊或結(jié)構(gòu)分塊。

高級(jí)分塊

小-大分塊

  • 分塊策略用“小粒度塊”(如句子/短句)做高精度召回,定位到最相關(guān)的微片段;再將其“所在的大粒度塊”(如段落/小節(jié))作為上下文送入 LLM,以兼顧精確性與上下文完整性。
  • 使用流程

構(gòu)建索引(離線):

1)Sentence/短句索引(索引A):?jiǎn)挝粸榫渥踊蜃泳洹?/p>

2)段落/小節(jié)存儲(chǔ)(存儲(chǔ)B):保留原始大塊文本與結(jié)構(gòu)信息。

檢索(在線):

      1)用索引A召回 top_k_small 個(gè)小塊(向量檢索)。

      2)將小塊按 parent_id 分組,計(jì)算組內(nèi)分?jǐn)?shù)(max/mean/加權(quán)),選出 top_m_big 個(gè)父塊候選。

      3)對(duì)“查詢-父塊文本”做交叉編碼重排,提升相關(guān)性排序的穩(wěn)定性。

      4)上下文組裝:在每個(gè)父塊中高亮或優(yōu)先保留命中小句附近的上下文(鄰近N句或窗口字符 w),在整體 token 預(yù)算內(nèi)拼接多塊。

      5)代碼示例(偽代碼)

# 離線:構(gòu)建小塊索引,并保存 parent_id -> 大塊文本 的映射
# 在線檢索:
small_hits = small_index.search(embed(query), top_k=30)
groups = group_by_parent(small_hits)
scored_parents = score_groups(groups, agg="max")
candidates = top_m(scored_parents, m=3)


# 交叉編碼重排
rerank_inputs = [(query, parent_text(pid)) for pid in candidates]
reranked = cross_encoder_rerank(rerank_inputs)


# 組裝上下文:對(duì)每個(gè)父塊,僅保留命中句及其鄰近窗口,并加上標(biāo)題路徑
contexts = []
for pid, _ in reranked:
    hits = groups[pid]
    context = build_local_window(parent_text(pid), hits, window_sents=1)
    contexts.append(prefix_with_breadcrumbs(pid) + context)


final_context = pack_under_budget(contexts, token_budget=3000)    # 留出回答空間

父子段分塊

  • 分塊策略

將文檔按章節(jié)/段落等結(jié)構(gòu)單元切成“父塊”(Parent),再在每個(gè)父塊內(nèi)切出“子塊”(通常為句子/短段或者篤固定塊)。然后為“子塊”建向量索引以做高精度召回。當(dāng)檢索時(shí)先召回子塊,再按 parent_id 聚合并擴(kuò)展到父塊或父塊中的局部窗口,兼顧最后召回內(nèi)容的精準(zhǔn)與上下文完整性。

  • 適用場(chǎng)景

結(jié)構(gòu)清晰的說明文、手冊(cè)、白皮書、法規(guī)、FAQ 聚合頁;

需要“句級(jí)證據(jù)準(zhǔn)確 + 段/小節(jié)級(jí)上下文完整”的問答。

  • 使用流程

結(jié)構(gòu)粗切(父塊)

1)按標(biāo)題層級(jí)/段落/代碼塊切出父塊。

2)父塊寫入 breadcrumbs(H1/H2/...)、anchor、block_type、start/end_offset。

精細(xì)切分(子塊)

      1)在父塊內(nèi)部以句子/子句/固定塊為單位切分(可用遞歸分塊兜底),小比例 overlap(或附加上一句內(nèi)容)。

      2)為每個(gè)子塊記錄child_offset、sent_index_range、parent_id。

建索引與存儲(chǔ)

      1)子塊向量索引A:先編碼,normalize 后建索引。

      2) 父塊存儲(chǔ)B:保存原文與結(jié)構(gòu)元信息,此處可以選建一個(gè)父塊級(jí)向量索引用于粗排或回退。

檢索與組裝

      1 ) 用索引A召回 top_k_child 子塊。

      2 ) 按 parent_id 分組并聚合打分(max/mean/命中密度),選出 top_m_parent 父塊候選。

      3 ) 對(duì) (query, parent_text 或 parent_window) 交叉編碼重排。

      4)上下文裁剪:對(duì)每個(gè)父塊僅保留“命中子塊±鄰近窗口”(±1–2 句或 80–200 字),加上標(biāo)題路徑前綴,控制整體 token 預(yù)算。

打分與聚合策略

1)組分?jǐn)?shù):score_parent = α·max(child_scores) + (1-α)·mean(child_scores) + β·coverage(命中子塊數(shù)/父塊子塊總數(shù))。

2)密度歸一化:density = sum(exp(score_i)) / length(parent_text),為避免長(zhǎng)父塊因命中多而“天然占優(yōu)”。

3)窗口合并:同一父塊內(nèi)相鄰命中窗口若間距小于閾值則合并,減少重復(fù)與碎片。

  • 與“小-大分塊”的關(guān)系

1)小-大分塊是檢索工作流(小粒度召回→大粒度上下文);

2)父子段分塊是數(shù)據(jù)建模與索引設(shè)計(jì)(顯式維護(hù) parent–child 映射)。

3)兩者強(qiáng)相關(guān)、常配合使用:父子映射讓小-大擴(kuò)展更穩(wěn)、更易去重與回鏈。

  • 示例
from typing import List, Dict, Tuple
import numpy as np
from sentence_transformers import SentenceTransformer




embedder = SentenceTransformer("BAAI/bge-m3")


def search_parent_child(query: str, top_k_child=40, top_m_parent=3, window_chars=180):
    q = embedder.encode([query], normalize_embeddings=True)[0]
    hits = small_index.search(q, top_k=top_k_child)  # 返回 [(child_id, score), ...]
    # 分組
    groups: Dict[str, List[Tuple[str, float]]] = {}
    for cid, score in hits:
        p = child_parent_id[cid]
        groups.setdefault(p, []).append((cid, float(score)))
    
    # 聚合打分(max + coverage)
    scored = []
    for pid, items in groups.items():
        scores = np.array([s for _, s in items])
        agg = 0.7 * scores.max() + 0.3 * (len(items) / (len(parents[pid]["sent_spans"]) + 1e-6))
        scored.append((pid, float(agg)))
    scored.sort(key=lambda x: x[1], reverse=True)
    candidates = [pid for pid, _ in scored[:top_m_parent]]
    
    # 為每個(gè)父塊構(gòu)造“命中窗口”
    contexts = []
    for pid in candidates:
        ptext = parents[pid]["text"]
        # 找到子塊命中區(qū)間并合并窗口
        spans = sorted([(children[cid]["start"], children[cid]["end"]) for cid, _ in groups[pid]])
        merged = []
        for s, e in spans:
            s = max(0, s - window_chars)
            e = min(len(ptext), e + window_chars)
            if not merged or s > merged[-1][1] + 50:
                merged.append([s, e])
            else:
                merged[-1][1] = max(merged[-1][1], e)
        windows = [ptext[s:e] for s, e in merged]
        prefix = " > ".join(parents[pid]["meta"].get("breadcrumbs", [])[-3:])
        contexts.append((pid, f"[{prefix}]\n" + "\n...\n".join(windows)))
    
    # 交叉編碼重排(此處用占位函數(shù))
    reranked = cross_encoder_rerank(query, [c[1] for c in contexts])  # 返回 indices 順序
    ordered = [contexts[i] for i in reranked]
    return ordered  # [(parent_id, context_text), ...]
  • 調(diào)參建議(僅作參考,具體需要按照實(shí)際來)調(diào)參順序:先定父/子塊長(zhǎng)度 → 標(biāo)定 top_k_child 與聚合權(quán)重 → 調(diào)整窗口大小與合并閾值 → 最后接入交叉編碼重排并控制 token 預(yù)算。

代理式分塊

  • 分塊策略

使用一個(gè)小溫度、強(qiáng)約束的 LLM Agent 模擬“人類閱讀與編排”,根據(jù)語義、結(jié)構(gòu)與任務(wù)目標(biāo)動(dòng)態(tài)決定分塊邊界,并輸出結(jié)構(gòu)化邊界信息與理由(rationale 可選,不用于檢索)。

  • 適用場(chǎng)景

高度復(fù)雜、長(zhǎng)篇、非結(jié)構(gòu)化且混合格式(文本+代碼+表格)的文檔;

結(jié)構(gòu)/語義/主題策略單獨(dú)使用難以取得理想邊界時(shí)。

  • 使用時(shí)的注意事項(xiàng)

規(guī)則護(hù)欄:

1)禁止在代碼塊、表格單元、引用塊中間切分,對(duì)圖片/公式作為原子單元處理。

2)保持標(biāo)題鏈路完整,強(qiáng)制最小/最大塊長(zhǎng)(min/max_chars / min/max_sents)。

目標(biāo)對(duì)齊:在系統(tǒng)提示中明確“為了檢索問答/用于摘要/用于診斷”的目標(biāo),Agent 以任務(wù)優(yōu)先級(jí)決定邊界與上下文冗余度。

1)結(jié)構(gòu)化輸出:要求輸出 segments: [{start_offset, end_offset, title_path, reason}],不能接受自由文本。

2)自檢與回退:Agent 產(chǎn)出的邊界先過一遍約束校驗(yàn)器(如長(zhǎng)度、原子塊、順序等),不符合規(guī)則的內(nèi)容則自動(dòng)回退到遞歸/句級(jí)分塊。

成本控制:

     1 )長(zhǎng)文分批閱讀(分段滑動(dòng)窗口);

     2 ) 在每段末尾只輸出邊界草案,最終匯總并去重;

     3 )溫度低(≤0.3)、max_tokens 受控。

     4) 示例:Agent 輸出模式(偽 Prompt 片段)

系統(tǒng):你是分塊器。目標(biāo):為RAG檢索創(chuàng)建高內(nèi)聚、可追溯的塊。規(guī)則:
1) 不得在代碼/表格/公式中間切分;
2) 每塊400-1000字;
3) 保持標(biāo)題路徑完整;
4) 盡量讓“定義+解釋”在同一塊;
5) 輸出JSON,含 start_offset/end_offset/title_path。


用戶:<文檔片段文本>
助手(示例輸出):
{
  "segments": [
    {"start": 0, "end": 812, "title_path": ["指南","安裝"], "reason": "完整步驟+注意事項(xiàng)"},
    {"start": 813, "end": 1620, "title_path": ["指南","配置"], "reason": "參數(shù)表與示例緊密相關(guān)"}
  ]
}
  • 集成的流程

粗切:先用結(jié)構(gòu)感知/遞歸策略獲得初步塊,降低 Agent 處理跨度。

Agent 精修:對(duì)“疑難塊”(過長(zhǎng)/多格式/主題混雜)調(diào)用 Agent 細(xì)化邊界。

質(zhì)檢:規(guī)則校驗(yàn) + 語義稀疏度檢測(cè)(塊內(nèi)相似度方差過大則再細(xì)分)。

寫入 metadata。

混合分塊

單一策略難覆蓋所有文檔與場(chǎng)景?;旌戏謮K通過“先粗后細(xì)、按需細(xì)化”,在效率、可追溯性與答案質(zhì)量之間取得穩(wěn)健平衡。

  • 分塊策略

先用宏觀邊界(結(jié)構(gòu)感知)做粗粒度切分,再對(duì)“過大或主題跨度大的塊”應(yīng)用更精細(xì)的策略(遞歸、句子、語義/主題)。查詢時(shí)配合“小-大分塊”/“父子段分塊”的檢索組裝,以小精召回、以大保上下文。

  • 使用流程

粗切(離線):按標(biāo)題/段落/代碼塊/表格等結(jié)構(gòu)單元切分,清理噪聲(頁眉頁腳/導(dǎo)航)。

細(xì)化(離線):對(duì)超長(zhǎng)或密度不均的塊,按規(guī)則選用遞歸/句子/語義分塊二次細(xì)分。

索引(離線):同時(shí)為“小塊索引(句/子句)”與“大塊存儲(chǔ)(段/小節(jié))”生成數(shù)據(jù)與metadata。

檢索(在線):小塊高精度召回 → 按父塊聚合與重排→ 在父塊中抽取命中句鄰域作為上下文,控制整體 token 預(yù)算。

  • 策略選擇規(guī)則

若塊類型為代碼/表格/公式:保持原子,不在中間切分,直接與其解釋文字打包。

若為對(duì)話:按輪次/說話人做對(duì)話式分塊,overlap 使用“輪次重疊”。

若為普通說明文/Markdown章節(jié):

1)長(zhǎng)度 > max_coarse或句長(zhǎng)方差高/標(biāo)點(diǎn)稀疏:優(yōu)先語義分塊(句向量+突變閾值)。

2)否則:遞歸字符分塊(標(biāo)題/段落/換行/空格/字符)保持語義邊界。

對(duì)過短塊:與同一父標(biāo)題相鄰塊合并,優(yōu)先向后合并。

  • 質(zhì)量-成本檔位(僅供參考)

fast:僅結(jié)構(gòu)→遞歸。overlap 5%–10%,不跑語義分塊和主題分塊

balanced(推薦):結(jié)構(gòu)→遞歸,對(duì)異常塊啟用語義分塊,小-大檢索,overlap 10%左右

quality:在 balanced 基礎(chǔ)上對(duì)疑難塊啟用 Agent 精修,更強(qiáng)的鄰接擴(kuò)展與rerank

  • 簡(jiǎn)潔調(diào)度器示例, 將結(jié)構(gòu)粗切與若干細(xì)分器組合為一個(gè)“混合分塊”入口,關(guān)鍵是類型判斷與長(zhǎng)度閾值控制??梢园亚拔囊褜?shí)現(xiàn)的結(jié)構(gòu)/句子/語義/對(duì)話分塊函數(shù)掛入此調(diào)度器。
from typing import List, Dict


def hybrid_chunk(
    doc_text: str,
    parse_structure,          # 函數(shù):返回 [{'type': 'text|code|table|dialogue', 'text': str, 'breadcrumbs': [...], 'anchor': str}]
    recursive_splitter,       # 函數(shù):text -> [{'text': str}]
    sentence_splitter,        # 函數(shù):text -> [{'text': str}]
    semantic_splitter,        # 函數(shù):text -> [{'text': str}]
    dialogue_splitter,        # 函數(shù):turns(list) -> [{'text': str}],若無對(duì)話則忽略
    max_coarse_len: int = 1100,
    min_chunk_len: int = 320,
    target_len: int = 750,
    overlap_ratio: float = 0.1,
) -> List[Dict]:
    """
    返回格式: [{'text': str, 'meta': {...}}]
    """
    blocks = parse_structure(doc_text)  # 先拿到結(jié)構(gòu)塊
    chunks: List[Dict] = []
    
    def emit(t: str, meta_base: Dict):
        t = t.strip()
        if not t:
            return
        # 結(jié)構(gòu)重疊前綴(標(biāo)題路徑)
        bc = " > ".join(meta_base.get("breadcrumbs", [])[-3:])
        prefix = f"[{bc}]\n" if bc else ""
        chunks.append({
            "text": (prefix + t) if not t.startswith(prefix) else t,
            "meta": meta_base
        })
    
    for b in blocks:
        t = b["text"]
        btype = b.get("type", "text")
        
        # 原子塊:代碼/表格
        if btype in {"code", "table", "formula"}:
            emit(t, {**b, "splitter": "atomic"})
            continue
        
        # 對(duì)話塊
        if btype == "dialogue":
            for ck in dialogue_splitter(b.get("turns", [])):
                emit(ck["text"], {**b, "splitter": "dialogue"})
            continue
        
        # 普通文本:依據(jù)長(zhǎng)度與“可讀性”啟用不同細(xì)分器
        if len(t) <= max_coarse_len:
            # 中短文本:遞歸 or 句子
            sub = recursive_splitter(t)
            # 合并過短子塊
            buf = ""
            for s in sub:
                txt = s["text"]
                if len(buf) + len(txt) < min_chunk_len:
                    buf += txt
                else:
                    emit(buf or txt, {**b, "splitter": "recursive"})
                    buf = "" if buf else ""
            if buf:
                emit(buf, {**b, "splitter": "recursive"})
        else:
            # 超長(zhǎng)文本:語義分塊優(yōu)先
            for ck in semantic_splitter(t):
                emit(ck["text"], {**b, "splitter": "semantic"})
    
    # 輕量字符重疊(可選)
    if overlap_ratio > 0:
        overlapped = []
        for i, ch in enumerate(chunks):
            overlapped.append(ch)
            if i + 1 < len(chunks) and ch["meta"].get("breadcrumbs") == chunks[i+1]["meta"].get("breadcrumbs"):
                # 在相鄰?fù)鹿?jié)塊間引入小比例重疊
                ov = int(len(ch["text"]) * overlap_ratio)
                if ov > 0:
                    head = ch["text"][-ov:]
                    chunks[i+1]["text"] = head + chunks[i+1]["text"]
        chunks = overlapped
    
    return chunks

五、結(jié)論

圖片圖片


責(zé)任編輯:武曉燕 來源: 得物技術(shù)
相關(guān)推薦

2025-05-27 08:35:00

2025-05-28 09:00:00

2024-08-05 10:23:36

2025-09-03 04:00:45

RAG系統(tǒng)分塊

2025-06-11 08:40:00

LangChainRAG人工智能

2024-10-29 11:54:25

2025-05-06 10:05:23

2025-04-03 16:02:14

2024-09-24 14:32:17

RAG高級(jí)優(yōu)化Fusion

2024-11-08 08:39:39

2024-06-27 16:38:57

2025-03-21 14:34:17

2025-10-27 08:25:01

2025-03-11 08:00:00

LLM開發(fā)深度學(xué)習(xí)

2024-08-12 08:28:53

2025-05-14 01:40:00

RAG數(shù)據(jù)工具

2025-02-06 13:50:06

2024-11-11 14:23:11

2024-08-06 10:02:42

2025-03-24 08:20:39

RAGLLM檢索增強(qiáng)生成
點(diǎn)贊
收藏

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