@mingto/text-stream-slicer
v1.0.34
Published
文本流智能分段器,按语言规则将连续文本智能分割成有意义的段落与片段。支持中英混合、标点、数字及小数点等特殊符号的准确识别。
Readme
@mingto/text-stream-slicer
文本流智能分段器,按语言规则将连续文本智能分割成有意义的段落与片段。支持中英混合、标点、数字及小数点等特殊符号的准确识别。
特性
- 📝 智能分段:基于语言规则识别句末标点,精确分割文本段落
- 🌍 多语言支持:完美支持中英混合文本,智能识别中英文标点
- 🔢 特殊符号处理:准确识别数字、小数点、符号等特殊字符,避免错误分割
- 🧹 文本去噪:自动移除非法字符与多余空白
- 🔧 文本预处理:智能处理尾部歧义,缓存中间结果
- 🔄 流式支持:专为流式文本设计,处理流式文本精准分割
- 📦 TypeScript 支持:完整的类型定义与类型推导
- ✨ 文本清洗:内置段落清洗过滤,过滤空段与无意义段
- 🔍 语义单元识别:智能识别语义单元,避免断句不当
- 🎯 精准分割:智能处理句末歧义与标点特殊情况
安装
# npm
npm install @mingto/text-stream-slicer
# yarn
yarn add @mingto/text-stream-slicer
# pnpm (推荐)
pnpm add @mingto/text-stream-slicer快速开始
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
// 创建实例
const splitter = new TextStreamSplitter()
// 处理单段文本
const text = '这是第一段。这是第二段。这是第三段。'
const paragraphs = splitter.processText(text, true)
console.log(paragraphs)
// 输出: ['这是第一段。', '这是第二段。', '这是第三段。']API 文档
创建实例
new TextStreamSplitter()
创建文本流分段器实例。
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()实例方法
splitter.processText(text, includeRemaining?)
同步处理输入文本片段,返回已分段的文本数组。
const paragraphs = splitter.processText('这是第一段。这是第二段。')
console.log(paragraphs)| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| text | string | ✅ | - | 本次输入的文本片段 |
| includeRemaining | boolean | ❌ | false | 是否已无后续文本,true 表示文本已结束 |
使用示例
基础分段
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()
const text = '你好,世界。这是一个测试。今天天气真好。'
const result = splitter.processText(text, true)
console.log(result)
// 输出: ['你好,世界。', '这是一个测试。', '今天天气真好。']中英文混合文本
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()
const mixedText = 'Hello, world. 这是中文。This is English. 也是中文。'
const result = splitter.processText(mixedText, true)
console.log(result)
// 输出: ['Hello, world.', '这是中文。', 'This is English.', '也是中文。']数字与标点识别
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()
// 包含数字的文本不会被错误分割
const textWithNumbers = '商品价格是 99.99 元。数量是 100 件。'
const result = splitter.processText(textWithNumbers, true)
console.log(result)
// 输出: ['商品价格是 99.99 元。', '数量是 100 件。']流式文本处理
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()
// 模拟流式接收
const textChunks = [
'这是第一段。',
'这是第二段的前半部分,',
'这是第二段的后半部分。',
'这是第三段。'
]
let allParagraphs = []
textChunks.forEach((chunk, index) => {
// 最后一段设置 includeRemaining 为 true
const isLast = index === textChunks.length - 1
const paragraphs = splitter.processText(chunk, isLast)
allParagraphs.push(...paragraphs)
})
console.log(allParagraphs)
// 输出: ['这是第一段。', '这是第二段的前半部分,这是第二段的后半部分。', '这是第三段。']结合 TypeScript 完整示例
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const splitter = new TextStreamSplitter()
// 模拟 AI 流式输出处理
async function processStreamText() {
const textStream = [
'今天天气真不错,',
'我想去公园散步。',
'路上看到了很多花,',
'有红玫瑰、白百合,还有郁金香。',
]
const allResults: string[] = []
textStream.forEach((text, index) => {
const isLastChunk = index === textStream.length - 1
const paragraphs = splitter.processText(text, isLastChunk)
paragraphs.forEach((paragraph) => {
console.log('新段落:', paragraph)
allResults.push(paragraph)
})
})
return allResults
}
processStreamText()内部处理流程
文本流分段器采用 5 阶段处理流程:
输入文本
↓
1. 文本去噪 (SanitizeText) → 移除非法字符与多余空白
↓
2. 文本预处理 (PreprocessText) → 处理尾部歧义并缓存中间结果
↓
3. 文本替换 (ReplaceText) → 按规则替换特殊语义单元
↓
4. 段落构建 (Paragraphs) → 按句末标点与长度规则拆分段落
↓
5. 段落清洗 (SanitizeParagraphs) → 过滤空段与无意义段
↓
输出段落数组支持的句末标点
文本流分段器能够识别以下句末标点:
| 标点 | 说明 |
|------|------|
| 。 | 中文句号 |
| ? | 中文问号 |
| ! | 中文感叹号 |
| ; | 中文分号 |
| ?! | 中文问号+感叹号 |
| , | 中文逗号(长度优先) |
| ; | 中文分号(长度优先) |
| : | 中文冒号(长度优先) |
| . | 英文句号 |
| ? | 英文问号 |
| ! | 英文感叹号 |
| ; | 英文分号 |
| ?! | 英文问号+感叹号 |
| , | 英文逗号(长度优先) |
特殊场景处理
1. 小数点识别
// 不会错误分割
const text = '价格是 99.99 元。'
// 正确分割为: ['价格是 99.99 元。']2. 省略号处理
// 不会错误分割
const text = '等等... 还有其他。'
// 正确分割为: ['等等... 还有其他。']3. 英文缩写处理
// 不会错误分割
const text = 'Mr. Smith 来了。'
// 正确分割为: ['Mr. Smith 来了。']4. 网址处理
// 不会错误分割
const text = '访问 https://example.com/index.html。'
// 正确分割为: ['访问 https://example.com/index.html。']5. IP地址处理
// 不会错误分割
const text = '服务器地址是 192.168.1.1。'
// 正确分割为: ['服务器地址是 192.168.1.1。']6. 日期处理
// 不会错误分割
const text = '今天是 2024.01.01。'
// 正确分割为: ['今天是 2024.01.01。']与其他工具组合使用
结合 type-writer 实现流式打字机效果
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
import { createTypeWriter } from '@mingto/type-writer'
const splitter = new TextStreamSplitter()
const typeWriter = createTypeWriter({ speed: 50 })
typeWriter.on('change', (text) => {
document.getElementById('output').innerText = text
})
// 模拟流式文本输入
const streamChunks = ['这是第一句。', '这是第二句。', '这是第三句。']
streamChunks.forEach((chunk, index) => {
const isLast = index === streamChunks.length - 1
const paragraphs = splitter.processText(chunk, isLast)
paragraphs.forEach(paragraph => {
typeWriter.send(paragraph + ' ')
})
})结合 LLM 流式输出处理
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
import huoshanTTS from '@mingto/huoshan-tts'
const splitter = new TextStreamSplitter()
// 配置 TTS
huoshanTTS.config()
const tts = huoshanTTS.create({
speed_ratio: 1.2
})
// 模拟 LLM 流式输出
async function handleLLMStream(stream) {
for await (const chunk of stream) {
const paragraphs = splitter.processText(chunk, false)
paragraphs.forEach(paragraph => {
tts.send(paragraph)
})
}
// 处理最后的剩余文本
const finalParagraphs = splitter.processText('', true)
finalParagraphs.forEach(paragraph => {
tts.send(paragraph)
})
tts.end()
}在 React 中使用
import { useState, useRef, useCallback } from 'react'
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const TextStreamComponent = () => {
const [paragraphs, setParagraphs] = useState([])
const splitterRef = useRef(null)
useEffect(() => {
splitterRef.current = new TextStreamSplitter()
}, [])
const handleTextChunk = useCallback((text, isLast) => {
const newParagraphs = splitterRef.current.processText(text, isLast)
setParagraphs(prev => [...prev, ...newParagraphs)
}, [])
return (
<div>
<div>
{paragraphs.map((paragraph, index) => (
<p key={index}>{paragraph}</p>
))}
</div>
</div>
)
}
export default TextStreamComponent在 Vue 3 中使用
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { TextStreamSplitter } from '@mingto/text-stream-slicer'
const paragraphs = ref([])
let splitter = null
onMounted(() => {
splitter = new TextStreamSplitter()
})
const handleTextChunk = (text, isLast) => {
const newParagraphs = splitter.processText(text, isLast)
paragraphs.value.push(...newParagraphs)
}
</script>
<template>
<div>
<p v-for="(paragraph, index) in paragraphs" :key="index">{{ paragraph }}</p>
</div>
</template>处理策略
标点优先策略
// 优先根据标点符号分割文本,保证语义完整性:
// 句号(。.)、问号(??)、感叹号(!!)、分号(;;)等具有最高优先级长度优先策略
// 文本过长时,根据文本过长时自动分割,避免单段文本过长
// 逗号(,,)、分号(;;)等触发长度触发分割智能尾部处理
// 处理尾部歧义,避免断句不当:
// - 检测尾部标点是否完整
// - 缓存不完整句子,等待后续文本
// - 最后一段强制结束时强制结束时清空所有缓存注意事项
- ⚠️ **流式文本处理时,记得最后一段必须设置
includeRemaining = true确保所有缓存文本被处理 - ⚠️ 输入文本建议不要包含过多的特殊字符,否则可能影响分割结果
- ⚠️ 长文本建议分段处理,避免内存占用过多占用过多内存
- ⚠️ 中英混合文本会自动识别中英文标点,无需额外配置
- ✅ 支持流式文本的流式文本处理工具库专为流式文本
- ✅ 建议段落长度建议控制在合理范围,避免单次文本过长影响体验
- ✅ 段落长度建议控制在 500字以内效果最佳
- ✅ 特殊场景需要保留特殊场景下建议结合具体调整策略文本
常见问题
**Q: 为什么句末标点后必须包含标点吗? A: 保留标点,分段结果会保留标点,确保完整性。
**Q: 中文和英文混合文本有什么影响? A: 不会自动切换的英文混合文本会自动识别中英文标点,无需额外配置。
**Q: 连续句号会被当作句末标点会被正确识别吗? A: 会的,工具会智能识别小数点、省略号、网址中的句号、IP地址中的小数点等特殊场景不会被错误分割。
**Q: 文本中有复杂语义单元会被智能保留吗? A: 会的,工具会识别特殊语义单元并做特殊处理。
许可证
MIT
