You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于标点将超长文本分割为长度相近、不超长度上限的最少块?

文本按标点边界均等拆分方案

现有成熟方案说明

  • 轻量无依赖场景:建议自行实现核心逻辑,无需引入第三方库
  • NLP场景:可直接使用HuggingFace Tokenizer的chunk_size+split_special_tokens相关配置,或NLTK、jieba的句子分割+分块组合能力,以上工具都原生支持按语义边界拆分的能力

核心算法实现逻辑

前置约束:单句长度必须小于阈值X,否则无法满足「不截断完整语句」的要求,需先处理超长单句场景。
实现步骤如下:

  1. 标记合法拆分点:遍历字符串,记录所有语句结束标点(.、!、?、。、!、?,可根据需求扩展)的后一个下标作为合法拆分位置,只有在这些位置拆分才不会截断完整语句。
  2. 确定最小拆分块数k:从最低要求k=2开始向上尝试,校验是否可以用k-1个拆分点将字符串分为k段,每段长度都小于X,找到满足条件的最小k值。
  3. 均等拆分:计算每块的理想长度avg = 总长度 / k,遍历合法拆分点,优先选择让当前块长度最接近avg的位置拆分,保证所有块长度尽可能接近,且都不超过阈值。

Python实现代码示例

import re

def split_string_by_punctuation(s: str, max_len: int) -> list:
    # 字符串本身长度小于阈值直接返回
    if len(s) < max_len:
        return [s]
    
    # 匹配所有语句结束标点的位置,兼容中英文标点,可根据需求扩展标点列表
    split_pattern = re.compile(r'[.。!!??,,;;]')
    split_points = [match.end() for match in split_pattern.finditer(s)]
    # 合法拆分点去重、排序
    split_points = sorted(list(set(split_points)))
    
    # 校验是否存在单句超过max_len,无法按规则拆分
    prev = 0
    for p in split_points:
        if p - prev >= max_len:
            raise ValueError(f"存在单句长度超过阈值{max_len},无法按规则拆分")
        prev = p
    if len(s) - prev >= max_len:
        raise ValueError(f"存在单句长度超过阈值{max_len},无法按规则拆分")
    
    # 找到最小拆分块数k
    total_len = len(s)
    min_k = 2
    while True:
        # 平均长度超过max_len直接跳过当前k
        if (total_len / min_k) >= max_len:
            min_k += 1
            continue
        # 模拟贪心拆分校验可行性
        current = 0
        chunks = 0
        for p in split_points:
            if p - current >= max_len:
                break
            if (p - current) >= (total_len / min_k) or p == split_points[-1]:
                chunks += 1
                current = p
                if current >= total_len:
                    break
        if current >= total_len and chunks <= min_k:
            break
        min_k += 1
    
    # 执行最优均等拆分
    avg = total_len / min_k
    res = []
    current_start = 0
    for i, p in enumerate(split_points):
        next_p = split_points[i+1] if i < len(split_points)-1 else total_len
        # 当前拆分点更接近平均长度,或下一个拆分点会超过长度阈值则拆分
        if (p - current_start) >= avg or (next_p - current_start) >= max_len:
            res.append(s[current_start:p].strip())
            current_start = p
        if current_start >= total_len:
            break
    if current_start < total_len:
        res.append(s[current_start:].strip())
    return res

# 示例测试
if __name__ == "__main__":
    max_len = 10
    strings = ["Hello. How are you? I'm fine", "other string containg dots", "another string containg dots"]
    result = []
    for s in strings:
        if len(s) > max_len:
            chunks = split_string_by_punctuation(s, max_len)
            result.extend(chunks)
        else:
            result.append(s)
    print(result)

内容的提问来源于stack exchange,提问作者Paolo Magnani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:06:03