TokenTextSplitter不适配BGE-M3的解决方案及适配库咨询
解决Spring-AI TokenTextSplitter适配BAAI/BGE-M3的方案
核心问题原因
Spring-AI默认的TokenTextSplitter仅支持OpenAI等特定模型的token编码规则,而BAAI/BGE-M3采用SentencePiece编码体系,两者的token计数逻辑不兼容,导致无法直接使用。
解决方案一:自定义适配BGE-M3的TextSplitter
Spring-AI的TextSplitter是可扩展接口,你可以基于BGE-M3的tokenizer实现自定义拆分器,步骤如下:
引入依赖
引入支持BGE-M3 tokenizer的Java库,比如Hugging Face的transformers-java:<!-- Maven示例 --> <dependency> <groupId>com.huggingface</groupId> <artifactId>transformers</artifactId> <version>0.2.0</version> </dependency>实现TextSplitter接口
编写自定义拆分器,内部调用BGE-M3的tokenizer进行token计数,实现符合模型要求的文本拆分逻辑(参考Spring-AI默认TokenTextSplitter的拆分逻辑,替换token计数部分):import org.springframework.ai.document.Document; import org.springframework.ai.transformer.splitter.TextSplitter; import com.huggingface.transformers.Tokenizer; import java.util.ArrayList; import java.util.List; public class BGEM3TextSplitter implements TextSplitter { private final Tokenizer tokenizer; private final int chunkSize; private final int chunkOverlap; public BGEM3TextSplitter(Tokenizer tokenizer, int chunkSize, int chunkOverlap) { this.tokenizer = tokenizer; this.chunkSize = chunkSize; this.chunkOverlap = chunkOverlap; } @Override public List<Document> split(List<Document> documents) { return documents.stream() .flatMap(doc -> splitText(doc.getContent()).stream() .map(chunk -> new Document(chunk, doc.getMetadata()))) .toList(); } private List<String> splitText(String text) { List<String> chunks = new ArrayList<>(); String[] sentences = text.split("[。!?;\\n]"); StringBuilder currentChunk = new StringBuilder(); int currentTokens = 0; for (String sentence : sentences) { int sentenceTokens = tokenizer.encode(sentence).size(); // 检查当前chunk加上新句子是否超过阈值 if (currentTokens + sentenceTokens > chunkSize && currentChunk.length() > 0) { chunks.add(currentChunk.toString().trim()); // 处理重叠部分 String overlap = getOverlap(currentChunk.toString(), chunkOverlap); currentChunk = new StringBuilder(overlap); currentTokens = tokenizer.encode(overlap).size(); } currentChunk.append(sentence).append("。"); currentTokens += sentenceTokens; } // 添加最后一个chunk if (currentChunk.length() > 0) { chunks.add(currentChunk.toString().trim()); } return chunks; } private String getOverlap(String chunk, int overlapTokens) { List<Integer> tokens = tokenizer.encode(chunk); if (tokens.size() <= overlapTokens) { return chunk; } List<Integer> overlapTokenIds = tokens.subList(tokens.size() - overlapTokens, tokens.size()); return tokenizer.decode(overlapTokenIds); } }使用自定义拆分器
在Spring配置中初始化BGE-M3的tokenizer和自定义拆分器:@Configuration public class BGEM3Config { @Bean public Tokenizer bgeM3Tokenizer() throws Exception { // 加载本地或远程的BGE-M3 tokenizer return Tokenizer.fromPretrained("BAAI/bge-m3"); } @Bean public TextSplitter bgeM3TextSplitter(Tokenizer tokenizer) { return new BGEM3TextSplitter(tokenizer, 512, 50); // 根据模型需求设置chunkSize和overlap } }
解决方案二:集成LangChain4j的拆分器
如果你不想从头实现,可以使用LangChain4j中已有的SentencePieceTextSplitter,它支持BGE-M3这类使用SentencePiece编码的模型,再通过Spring-AI的扩展机制集成到项目中。
是否存在专门适配BGE-M3的TextSplitter库?
目前没有专门针对Spring-AI生态的BGE-M3专属TextSplitter库,但通过上述自定义实现或集成第三方工具的方式,完全可以实现适配需求。
内容的提问来源于stack exchange,提问作者bgraves
相关产品推荐
相关产品推荐

