Я не понимаю следующее поведение рекурсивного разделителя текста Langchain. Вот мой код и вывод.
from langchain.text_splitter import RecursiveCharacterTextSplitter
r_splitter = RecursiveCharacterTextSplitter(
chunk_size=10,
chunk_overlap=0,
# separators=["\n"]#, "\n", " ", ""]
)
test = """a\nbcefg\nhij\nk"""
print(len(test))
tmp = r_splitter.split_text(test)
print(tmp)
Выход
13
['a\nbcefg', 'hij\nk']
Как видите, он выводит фрагменты размером 7 и 5 и разделяется только на один из символов новой строки. Я ожидал, что вывод будет ['a','bcefg','hij','k']






Поведение, которое вы наблюдаете в рекурсивном разделителе текста Langchain, связано с заданными вами настройками. Давайте разберем код и разберемся с выводом.
Во-первых, вы определяете объект RecursiveCharacterTextSplitter со значением chunk_size, равным 10, и chunk_overlap, равным 0. Параметр chunk_size определяет максимальный размер каждого фрагмента, а параметр chunk_overlap указывает количество символов, которые должны перекрываться между последовательными фрагментами. В вашем случае куски не будут перекрываться.
Затем вы определяете тестовую строку test длиной 13 символов. Строка содержит символы новой строки ("\n") в определенных позициях.
Когда вы вызываете r_splitter.split_text(test), алгоритм разделения текста обрабатывает входной текст в соответствии с заданными параметрами. Поскольку для параметра chunk_size задано значение 10 и между фрагментами нет перекрытия, алгоритм пытается разбить текст на фрагменты размером 10.
В процессе разделения учитываются указанные вами разделители. Однако в вашем коде параметр разделителей закомментирован (# separators=["\n"]). В результате алгоритм не рассматривает символы новой строки как разделители.
Алгоритм начинает с начала входного текста и пытается разбить его на куски размером 10. Он находит символ новой строки ("\n") в индексе 1 и определяет, что он не может разбить текст в этой позиции, сохраняя фрагмент размер 10. Таким образом, он продолжается до следующего индекса.
По индексу 7 алгоритм находит еще один символ новой строки. Поскольку он не может разделить текст в этой позиции, сохраняя размер блока равным 10, текущий блок останавливается и начинается новый блок с оставшимся текстом.
Таким образом, вывод, который вы видите, будет ['a\nbcefg', 'hij\nk'], где первый фрагмент — это «a\nbcefg» (7 символов), а второй фрагмент — «hij\nk» (5 символов).
Если вы хотите разделить текст на каждом символе новой строки, вам нужно раскомментировать параметр разделителей и указать «\n» в качестве разделителя. Вот обновленный код:
from langchain.text_splitter import RecursiveCharacterTextSplitter
r_splitter = RecursiveCharacterTextSplitter(
chunk_size=10,
chunk_overlap=0,
separators=["\n"]
)
test = """a\nbcefg\nhij\nk"""
print(len(test))
tmp = r_splitter.split_text(test)
print(tmp)
С этой модификацией вывод будет ['a', 'bcefg', 'hij', 'k'], как вы и ожидали. Каждый символ новой строки будет рассматриваться как разделитель, в результате чего для каждой части текста будут отдельные фрагменты.
В соответствии с функцией разделения текста в RecursiveCharacterTextSplitter
def split_text(self, text: str) -> List[str]:
"""Split incoming text and return chunks."""
final_chunks = []
# Get appropriate separator to use
separator = self._separators[-1]
for _s in self._separators:
if _s == "":
separator = _s
break
if _s in text:
separator = _s
break
# Now that we have the separator, split the text
if separator:
splits = text.split(separator)
else:
splits = list(text)
# Now go merging things, recursively splitting longer texts.
_good_splits = []
for s in splits:
if self._length_function(s) < self._chunk_size:
_good_splits.append(s)
else:
if _good_splits:
merged_text = self._merge_splits(_good_splits, separator)
final_chunks.extend(merged_text)
_good_splits = []
other_info = self.split_text(s)
final_chunks.extend(other_info)
if _good_splits:
merged_text = self._merge_splits(_good_splits, separator) # Here will merge the items if the cusum is less than chunk size in your example is 10
final_chunks.extend(merged_text)
return final_chunks
это объединит элементы, если cusum меньше размера блока в вашем примере 10
Я посмотрел исходный код дальше в функцию _merge_splits (github.com/hwchase17/langchain/blob/master/langchain/…), и теперь это имеет смысл.
Этот ответ выглядит как ChatGPT