文章总结: 本文分析RAG场景下的代码分割算法优化,对比了通用文本切分与基于Tree-sitter的AST分割方案。针对现有工具切断代码语义的问题,测试发现benbrandt/text-splitter-rust在行边界对齐和语义完整性上表现最佳。建议采用该方案进行代码向量化,以提升Embedding质量与检索效果,同时指出模型质量同样关键。 综合评分: 90 文章分类: AI安全,安全工具
对 AI 更友好的代码分割算法分析
原创
crossoverJie
crossoverJie
2026年1月14日 08:08 重庆
字数 1192,阅读大约需 6 分钟
背景
因为最近在基于 RAG[1] 对我们的 code repo 做 AI 分析,其中有一个非常核心的流程就是需要将我们的代码库里的源码进行分割,分割之后会作为 chunk 供 RAG 查询;然后再将查询到的 chunk 提交给 LLM 做分析。
目前我们所使用的 deepwiki-open[2]对代码的分析使用的是最通用的 text_splitter:
分割方法也是最简单的按照 word 进行分割,普通场景下 text_splitter 够用,但对于我们这种存代码的场景就需要使用特殊的 Spitter 了;主要问题是它不理解语言结构,容易把函数/类等语义单元切断,导致检索召回片段不完整、上下文丢失。
算法对比
1. 基础文本切分
简介: 最原始的方法。不管代码逻辑,直接按字符长度或者空格硬切。就像切西瓜不管瓜瓤结构,每一刀切固定的厚度。
- • 优点:简单,适用于所有文本项目
- • 缺点:不适合代码项目,经常把一个完整的函数拦腰截断,大模型读起来云里雾里。
代码示例:
splitter = TextSplitter(**configs["text_splitter"])
document = splitter.split_text(code)
手搓 Tree-Sitter (参考Claude-context[3])
it('should split Java code from external file', async () => {
const filePath = 'AppService.java';
if (fs.existsSync(filePath)) {
const code = fs.readFileSync(filePath, 'utf-8');
console.log(`Reading Java file from: ${filePath}`);
console.log(`File size: ${code.length} characters`);
const chunks = await splitter.split(code, 'java', filePath);
console.log(`Split into ${chunks.length} chunks`);
chunks.forEach((chunk, index) => {
console.log(`>>>>Chunk ${index}: ${chunk.content}\n`);
console.log(`Metadata:`, chunk.metadata);
console.log(`Content preview: ${chunk.content.substring(0, 100)}...`); });
} else {
console.warn(`File not found: ${filePath}`);
}
});
原本是 TS[4] 写的,核心是使用 tree-sitter 做 AST 分析之后进行拆分,只是会在解析 AST 失败的时候使用 LangChainCodeSplitter 作为兜底。
这部分没有找到现成的开源方案,于是我就按照 ts 代码翻译了一份 Python 的版本:
splitter = AstCodeSplitter(chunk_size, chunk_overlap)
chunks = splitter.split(code, "java", file_path)
for i, chunk in enumerate(chunks):
print(f">>>>Chunk {i}: {chunk.content}\n")
| 方案 | 主要原理 | 代码友好度 | 适合场景 | 主要缺点 | | — | — | — | — | — | | 现有:deepwiki-open 的 TextSplitter(split_by=word) | 纯通用文本切分:按 word/长度 + overlap 切块 | 弱 | 快速起步;纯文本/注释类内容较多;对精度要求不高 | 容易把函数/类切断;chunk 语义不完整;对代码检索召回不稳 | | claude-context[3],没有 Python 库,得自己实现。 使用了 LangChain CodeTextSplitter[5] 兜底。 | 使用 tree-sitter 解析 AST,支持 chunk_size 和 overlap。 生成 chunk 后再处理是否超过 chunk_size,内存占用大于 code-spitter 相关代码[6] | 很强 | 多语言代码库 RAG、希望按函数/类分块 | 内存占用大于 code-spitter | | wangxj03/code-splitter[7](rust 编写有提供 Python[8] binding库) 参考了 benbrandt/text[9]-splitter[7] & LlamaIndex’s CodeSpiller[10](提供了 Python 库) | 用 tree-sitter[11] 解析 AST,再按语法节点+ chunk 长度合并。 边遍历边合并,内存占用较小;相关代码[12]。 直接将语法数按照 chunk 分割,没有处理 overlap; | 很强 | 多语言代码库 RAG、希望按函数/类分块 | 依赖 tree-sitter grammar;集成复杂度略高 没有处理 overlap,生成的上下文可能会不连续。 | | LangChain CodeTextSplitter[5] | 按语言特征分隔符(def/class/function等)切分(部分场景可结构化) 预设了一些语言的关键字[13]。 | 中-强 | 想快速落地、LangChain 生态、主流语言 | 多数实现偏“规则/正则”,复杂嵌套不如 AST 稳 | | benbrandt/text[9]-splitter[7](语义/边界优先),rust 编写, 有提供 Python binding 库[14]。 | 用 tree-sitter[11] 解析 AST。 | 强 | | | | LlamaIndex CodeSplitter[10] | 用 tree-sitter[11] 解析 AST。只使用了最大字符分割,没有处理 overlap; | 强 | | 没有处理 overlap; |
总结
我们对同一个 Java 源码文件分别使用了 claude-context[3] 和 text-splitter[9]进行了对比。
| 特性 | benbrandt:text-splitter-rust | claude-context-ts / claude-py-impl |
| — | — | — |
| 行边界对齐 | 极佳 。每个 Chunk 都从新行开始,在行末结束。 | 较差 。经常在行中间甚至单词中间切断(如 esDO)。 |
| 语法完整性 | 高 。尽量保持了方法签名或逻辑块的完整。 | 低 。由于是基于字符/Token 硬切,导致代码语义破碎。 |
| 重叠策略 (Overlap) | 有意义的逻辑重叠 。在方法交界处进行重叠。 | 机械重叠 。简单的滑动窗口,不考虑代码逻辑。 |
| Embedding 质量 | 高 。由于没有破碎单词,向量表示的语义更精准。 | 中 。存在破碎的单词 |
最后我们选择了 benbrandt:text-splitter-rust 的版本(提供了 Python binding 库)。
但对某个代码 repo 分析的效果与许多因素有关,比如 LLM 大模型质量、Embeding 的质量、提示词是否合理;其中的 Code Splitter 算法只是较小的一个环节。
这类需求随着大模型的迭代也需要常用常新,后续也会继续迭代相关知识。
引用链接
[1] RAG: https://crossoverjie.top/2025/12/25/AI/deepwiki-rag-principle/
[2] deepwiki-open: https://github.com/AsyncFuncAI/deepwiki-open/
[3] Claude-context: https://github.com/zilliztech/claude-context
[4] TS: https://github.com/zilliztech/claude-context/blob/2efe1e9aaf59f4f8c9aa3635b27326a2ae94fa1b/packages/core/src/splitter/ast-splitter.ts#L44
[5] LangChain CodeTextSplitter: https://reference.langchain.com/python/langchain_text_splitters/?_gl=1*1wsspz*_gcl_au*MTQxMjAyNDczOS4xNzY1NDQ2MTUx*_ga*NDcyOTM2OTM2LjE3NjU0NDYxNTI.*_ga_47WX3HKKY2*czE3NjY0NjkxODUkbzYkZzEkdDE3NjY0NzA0MDkkajYwJGwwJGgw#langchain_text_splitters.RecursiveCharacterTextSplitter.from_language
[6] 相关代码: https://github.com/zilliztech/claude-context/blob/2efe1e9aaf59f4f8c9aa3635b27326a2ae94fa1b/packages/core/src/splitter/ast-splitter.ts#L109
[7] wangxj03/code-splitter: https://github.com/wangxj03/code-splitter
[8] Python: https://pypi.org/project/code-splitter/
[9] benbrandt/text: https://github.com/benbrandt/text-splitter
[10] LlamaIndex’s CodeSpiller: https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/#codesplitter
[11] tree-sitter: https://tree-sitter.github.io/tree-sitter/
[12] 相关代码: https://github.com/wangxj03/code-splitter/blob/aa9a37e967c242b481a8a0ad1f663e5113d12a04/src/splitter.rs#L118
[13] 关键字: https://github.com/langchain-ai/langchain/blob/master/libs/text-splitters/langchain_text_splitters/character.py#L172
[14] 有提供 Python binding 库: https://pypi.org/project/semantic-text-splitter/
往期推荐
AI 如何用 AST 每天对 200 万+ 文件做高质量分块(用于代码搜索)
DeepWiki 一个常用 RAG 应用的开发流程
大模型应用开发必需了解的基本概念
持续剖析超级增强:将 Trace/ Span 和 Profile 整合打通
点分享
点收藏
点点赞
点在看
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:crossoverJie crossoverJie《对 AI 更友好的代码分割算法分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论