Главная / Статьи / Практические советы: стратегии разбиения на фрагменты RAG: полное инженерное руководство

Практические советы: стратегии разбиения на фрагменты RAG: полное инженерное руководство

Пошаговое руководство по практическим заметкам: стратегии сегментации RAG: полное инженерное руководство, включающее контракты, проверки и готовые блоки кода для команд, использующих эту модель.

2654 слов

В следующих заметках описывается практический подход к изучению книги «RAG Chunking Strategies: The Complete Engineering Guide». Основное внимание уделяется контрактам, проверкам и шаблонам кода, а не мотивирующим аспектам. На этапе обзора сначала запишите условия работы: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия элементов, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Основный компромисс: контекст против точности

Этап контекста критических компромиссов работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Разделяйте политику разбиения данных на части и политику их извлечения. Изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

[ TOO SMALL CHUNKS ]                  [ TOO LARGE CHUNKS ]
Loss of Context / Meaning             "Lost in the Middle" Effect
(e.g., "IF request is made...")       (Dense with irrelevant fluff)
            │                                      │
            └───────────────► 🎯 ◄─────────────────┘
                      THE GOLDILOCKS ZONE
                    (High Precision + Context)

Стратегия 1: Разделение фиксированного размера и рекурсивное разделение (базовые варианты)

Этап рекурсивного разделения на фиксированные блоки из стратегии 1 работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь граф зависимостей. Разделяйте политику разделения на блоки и политику извлечения данных. Изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

Разделение на фиксированные блоки (наивный подход)

При использовании метода фиксированного размера блоков на этапе «Наивный» лучший результат достигается, если рассматривать его как измеримую поверхность. Соберите один идеальный пример транскрипции, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный путь выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Разделяйте политику формирования блоков и политику извлечения данных; изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества. При использовании метода фиксированного размера блоков на этапе «Наивный» лучший результат достигается, если рассматривать его как измеримую поверхность. Соберите один идеальный пример транскрипции, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Рекурсивное разбиение на символьные блоки (Базовый вариант для производства)

На этапе рекурсивного разбиения на части символов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения и стоимость обработки токенов или запросов. Отображение стоимости на раннем этапе предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Необходимо указывать конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не могут отличить галлюцинации от пробелов в индексации.

# Example: LangChain Recursive Character Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=50,
    separators=["\n\n", "\n", ". ", " ", ""]
)

Стратегия 2: Разбиение с учетом структуры и семантики

Для этапа Semantic с учетом структуры в рамках стратегии 2 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Указывайте те участки текста, которые легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Чанкирование с учетом структуры (соответствующее формату документа)

Для этапа разбиения документов с учётом структуры необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации. Для этапа разбиения документов с учётом структуры необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия результатам работы, определите критерии успеха и откажитесь от безответственного частичного выполнения задачи.

завершение.

Семантическое разбиение на части (границы, основанные на значении)

При работе над этапом семантического разбиения на части, основанным на значении, сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает избегать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения и стоимость обработки токенов или запросов. Отслеживание затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Перед настройкой подсказок измерьте уровень воспроизведения ответов на фиксированный набор вопросов. Частая смена подсказок редко помогает улучшить качество поиска.

Sentence A ──► Embed ──┐
Sentence B ──► Embed ──┴── Similarity: 0.89 (Keep together)
Sentence C ──► Embed ──── Similarity: 0.32 (Drop below threshold -> CUT HERE)

Стратегия 3: Расширенные архитектуры с сохранением контекста

При работе над этапом «Стратегия 3: продвинутое сохранение контекста» сначала запишите условия работы алгоритма: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет избежать ошибок при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Измеряйте точность воспроизведения ответов на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

1. Разбиение на части от малого к большому (родитель-дочерний подход)

При работе над первым этапом разбиения на части от малого к большому запишите сначала контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Измеряйте точность воспроизведения на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска. При работе над первым этапом разбиения на части от малого к большому запишите сначала контракт: необходимые входные данные, сигнал о успехе и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

2. Позднее разбиение на части

Этап позднего разбиения на части работает наилучшим образом, если рассматривать его как измеримую характеристику. Соберите один идеальный пример транскрипции, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Разделяйте политику разбиения на части и политику поиска информации; изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

Матрица решений для производственной среды

Этап матрицы решений по производству работает наилучшим образом, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Разделяйте политику разбиения на части и политику извлечения данных. Изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

Краткое резюме инженерных правил для успеха

Правила инженерии для этапных работ наилучшим образом функционируют, когда их рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Документируйте как успешный путь выполнения, так и путь восстановления одновременно. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Разделяйте политику разбиения на части и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества. Правила инженерии для этапных работ наилучшим образом функционируют, когда их рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи.

Пора приступить к работе..

Прежде чем изменять код, необходимо определить входные данные, ответственного за выполнение шага и критерии завершения, чтобы готовить сценарий его реализации. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения, а также стоимость токенов или запросов. Отображение затрат с самого начала помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Указывайте те части текста, которые фактически легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Предварительные требования

На этапе предварительных требований необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Указывайте те участки текста, которые легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

pip install langchain langchain-community langchain-experimental llama-index llama-index-embeddings-openai openai chromadb
export OPENAI_API_KEY="your-openai-api-key"

1. Рекурсивное разбиение на символьные фрагменты (LangChain)

На этапе 1 «Рекурсивное разбиение на символьные блоки» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации. На этапе 1 «Рекурсивное разбиение на символьные блоки» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия результатов работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи.

from langchain_text_splitters import RecursiveCharacterTextSplitter

# Sample document
sample_text = """
# RAG System Design
Retrieval-Augmented Generation (RAG) decouples knowledge storage from reasoning capability.
Instead of forcing the AI to answer strictly from memory, RAG searches an external database first.
## The Ingestion Pipeline
1. Document Extraction: PDFs and web pages are converted into clean text.
2. Chunking: Documents are chopped into smaller, manageable text blocks.
3. Vectorization: Each block is converted into a numeric representation.
"""

# Initialize Recursive Splitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,        # Target chunk size in characters/tokens
    chunk_overlap=30,      # Overlap to prevent mid-sentence context loss
    separators=["\n\n", "\n", ". ", " ", ""] # Try double line breaks first
)
chunks = text_splitter.create_documents([sample_text])
print(f"Total chunks created: {len(chunks)}\n")
for i, chunk in enumerate(chunks):
    print(f"--- Chunk {i+1} ---")
    print(chunk.page_content)

2. Разбиение на части в формате «родитель-дочерний» / от малого к большому (LangChain + Chroma)

При работе над этапом разбиения на части в формате «родитель-дочерний» от малого к большому сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает избегать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения и стоимость в токенах или запросах. Отслеживание затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Перед настройкой подсказок измерьте уровень воспроизведения информации на фиксированном наборе вопросов. Частая смена подсказок редко помогает улучшить качество поиска информации.

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.retrievers import ParentDocumentRetriever
from langchain_community.vectorstores import Chroma
from langchain_community.storage import InMemoryStore
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
# 1. Initialize Vector Store (for small child embeddings) and DocStore (for large parent text)
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(collection_name="parent_child_rag", embedding_function=embeddings)
docstore = InMemoryStore()

# 2. Define Parent (Big) and Child (Small) Splitters
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=600, chunk_overlap=50)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=120, chunk_overlap=20)

# 3. Create the ParentDocumentRetriever
retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=docstore,
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)

# 4. Ingest Documents
docs = [
    Document(
        page_content="""
        System Architecture: The Two Pipelines.
        A production RAG framework runs on two main pipelines: Ingestion and Inference.
        The Ingestion pipeline extracts text, creates chunks, embeds them, and stores them in a vector DB.
        The Inference pipeline encodes user queries, performs vector similarity search, injects context into prompts, and generates LLM answers.
        Hybrid search combines keyword and vector retrieval to handle exact SKU IDs alongside general concepts.
        """
    )
]
retriever.add_documents(docs)

# 5. Query the Retriever
query = "What happens during inference in RAG?"
retrieved_parents = retriever.invoke(query)
print(f"Retrieved Parent Context (Full Block):\n")
print(retrieved_parents[0].page_content)

3. Семантическое разбиение на части (LlamaIndex)

При работе над тремя этапами Semantic Chunking LlamaIndex сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает избегать непреднамеренных изменений в коде позже. Храните конфигурацию отдельно от кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Измеряйте показатель воспроизведения на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.schema import Document
# 1. Initialize the Embedding Model used for detecting topic shifts
embed_model = OpenAIEmbedding(model="text-embedding-3-small")

# 2. Configure the Semantic Splitter
semantic_parser = SemanticSplitterNodeParser(
    buffer_size=1,                         # Number of surrounding sentences to evaluate together
    breakpoint_percentile_threshold=90,     # Split threshold percentile (higher = fewer, larger chunks)
    embed_model=embed_model
)

# 3. Sample document with distinct thematic shifts
raw_text = """
Quantum computing leverages qubits that can exist in superposition states, unlike classical bits.
Superposition allows algorithms to process vast potential outcomes simultaneously.
Entanglement further connects qubit states instantaneously across physical space.
On a totally different topic, baking sourdough bread requires maintaining a wild yeast starter.
You feed the starter equal parts flour and water every 24 hours to encourage fermentation.
Proper gluten development requires folding the dough during the bulk fermentation stage.
"""
doc = Document(text=raw_text)

# 4. Generate Nodes (Chunks)
nodes = semantic_parser.get_nodes_from_documents([doc])
print(f"Total Semantically Coherent Chunks: {len(nodes)}\n")
for i, node in enumerate(nodes):
    print(f"--- Chunk {i+1} ---")
    print(node.get_content().strip())
    print("\n")

Краткое описание реализации

На этапе подготовки краткого описания реализации сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Перед настройкой запросов измерьте точность воспроизведения ответов на фиксированном наборе вопросов. Частая смена запросов редко помогает улучшить качество поиска. На этапе подготовки краткого описания реализации сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как договор между входными данными и проверенными выходными результатами. Укажите названия элементов системы, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Заключение: Разбиение на части — это инженерная проблема, а не проблема ИИ

Метод разбиения на части наилучшим образом работает, когда его рассматривают как измеримую структуру. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Разделяйте политику разбиения на части и политику поиска информации; изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

Чек-лист операций

На этапе составления чек-листа операций определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность повторно выполнить шаг, исходя из известной точки контроля, без необходимости угадывания скрытого состояния системы.