共计 1602 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
Transformer 架构通过 self-attention 机制处理输入序列,但其计算复杂度与序列长度呈平方关系。这导致实际应用中必须设置上下文窗口限制(如 Claude 的 8k/100k tokens)。当文本超过此限制时:

- 早期输入会被直接丢弃,模型失去对这些信息的访问能力
- Positional encoding 在长序列中可能失效,导致位置信息混乱
- 典型失忆场景包括:
- 长篇文档问答时遗漏开头的重要定义
- 多轮对话中忘记初始设定的角色背景
- 代码分析时丢失文件头部的重要 import 声明
技术方案对比
分块处理法
- 优点:实现简单,不依赖额外组件
- 缺点:可能破坏跨块的语义连贯性
- 适用场景:文档摘要、批量文本分类
关键信息提取法
- 优点:保留核心信息,减少 token 浪费
- 缺点:需要预训练 NER 模型
- 适用场景:合同分析、医学文献处理
记忆增强法
- 优点:支持长期记忆保持
- 缺点:引入额外系统复杂度
- 适用场景:多轮对话系统、知识库问答
核心实现:智能分块处理
import tiktoken
from langchain.text_splitter import RecursiveCharacterTextSplitter
def calculate_tokens(text: str, model: str = "claude-2") -> int:
"""使用 tiktoken 精确计算 token 数量"""
enc = tiktoken.encoding_for_model(model)
return len(enc.encode(text))
class SemanticChunker:
def __init__(self, max_tokens: int = 8000, overlap: int = 200):
self.splitter = RecursiveCharacterTextSplitter(
chunk_size=max_tokens,
chunk_overlap=overlap,
length_function=calculate_tokens
)
def chunk_text(self, text: str) -> list[str]:
try:
if not text.strip():
raise ValueError("输入文本为空")
chunks = self.splitter.split_text(text)
if any(calculate_tokens(c) > self.splitter._chunk_size for c in chunks):
raise RuntimeError("分块大小校验失败")
return chunks
except Exception as e:
print(f"分块失败: {str(e)}")
return [text] # 降级处理
性能考量
| 方法 | 内存开销 | CPU 时间(10k tokens) |
|---|---|---|
| 基础分块 | O(1) | 12ms |
| NER 信息提取 | O(n) | 150ms |
| 向量数据库缓存 | O(n) | 300ms(首次) |
测试环境:AWS t3.xlarge 实例,Python 3.9
避坑指南
- 语义断裂预防:
- 优先在段落边界分块
- 添加合理的重叠 token
-
避免拆分 Markdown/HTML 标签
-
特殊字符处理:
- Unicode 字符需统一标准化
- 数学公式建议整体保留
-
表格数据转为 CSV 格式处理
-
调试技巧:
- 使用
tiktoken.encoding_for_model().decode()检查分块边界 - 可视化 attention 矩阵定位信息丢失点
延伸思考
- 如何动态调整分块大小以适应不同文本结构?
- 能否通过微调 positional encoding 来增强长文本位置感知?
- 混合使用 KV 缓存和分块处理是否可行?
推荐工具链:
– LlamaIndex:专业的长文本检索增强框架
– Haystack:构建生产级文档处理流水线
– Weaviate:高性能向量数据库解决方案
实际项目中,建议先从小规模文本测试开始,逐步验证各方案的适用性。对于关键业务场景,组合使用分块处理和向量缓存通常能取得最佳效果。
正文完
