- 1. 项目定位与生态
- 2. 核心抽象与编程模型
- 3. 模型与供应商支持(整体趋势)
- 4. 典型使用场景对比
- 5. 总结性对比表
- 6. 四个框架之间的关系
- 7. 市面上常见向量数据库选型
- 8. RAG 工作流 ASCII 示意图
- 9. Tools 的作用与调用关系
- 10. 经验:多模态大模型 + RAG 性能
- 11. MCP 总览与简化架构图
-
Spring AI
- 由 Spring 官方维护的 LLM 集成项目(类似 Spring Data / Spring Cloud 的定位)。
- 目标:为 Spring / Spring Boot 应用提供统一、供应商无关的 AI 接入抽象(Chat、Embedding、Image、工具调用等)。
- 更关注“如何在 Spring 生态里用好 AI 能力”,而不是编排复杂 Agent / Chain。
-
Spring AI Alibaba
- 由阿里相关社区维护,在理念和 API 上与 Spring AI 高度对齐,通常视为“面向国内模型生态的增强版 Spring AI”。
- 目标:更友好地支持中国境内常用的大模型服务(如阿里云通义等),提供本地化配置示例、文档和最佳实践。
- 对国内网络环境、鉴权方式、地域/专有云等场景有更多封装和约定。
-
LangChain4j
- LangChain 的 Java 生态实现,偏“LLM 应用编排框架”,不依赖 Spring,本身就是一个通用 Java 库。
- 目标:提供 Chain、Agent、Memory、Tool 以及对话状态管理等高级能力,用来构建复杂的 LLM 应用。
- 可以与 Spring/Spring Boot 集成(有 Starter),但它的核心设计不依赖 Spring。
-
LangGraph
- 可以理解为在 LangChain / LangChain4j 之上的“图式工作流框架”,更关注对话/Agent 的有状态编排。
- 目标:用节点(Node)和边(Edge)描述复杂对话流、决策树、多 Agent 协作等,把 LLM 应用抽象成可观测、可维护的“有向图”。
- 在本项目中,可以把它看成是对 LangChain4j 的增强层,类似于 Spring 体系里「Spring AI Alibaba 之于 Spring AI」的定位。
-
Spring AI
- 核心抽象:
ChatClient/EmbeddingClient/ImageClient等。 - 强调“声明式 + 配置驱动”:通过
application.yml配置模型供应商和参数,然后在代码里注入客户端使用。 - 与 Spring Boot 深度集成:自动配置、
@Bean、环境抽象、RestClient等。 - 提供简单的工具调用 / Function Calling 支持,但不会强行引入“链式 DSL”。
- 核心抽象:
-
Spring AI Alibaba
- 在 Spring AI 模型之上补充/增强供应商适配和 Starter,保持 Spring 风格不变。
- 常见特征:
- 针对国内 LLM 厂商提供 Boot Starter(依赖少量配置即可接入)。
- 针对国内 API 的差异(签名、地域、SSE/流式协议)做适配。
- 如果你已经熟悉 Spring AI,它基本上是“同一套编程模型 + 更多国内厂商支持”。
-
LangChain4j
- 核心抽象:
ChatLanguageModel、StreamingChatLanguageModel、EmbeddingModel、AiServices、Tool等。 - 提供“链式 / 组合式”编程模型,用代码装配 Prompt 模板、记忆模块、工具调用、路由等。
- Agent / Chain / Memory 一等公民,更适合需要多步骤推理、复杂工作流的场景。
- Spring 只是它的一个集成选项,你可以在纯 Java 项目、Micronaut、Quarkus 等环境中使用。
- 核心抽象:
-
LangGraph
- 核心抽象:
Graph、Node、State等,通常在节点内部使用 LangChain4j 的 Chain / Agent / Tool。 - 编程模型:先定义状态结构,再通过“图 + 路由规则”描述对话流转,让复杂逻辑可视化、可拆分。
- 更强调“有状态对话 + 分支/循环 + 人机协同”等高级模式,而不是单条链式调用。
- 核心抽象:
-
Spring AI
- 官方优先支持主流国际供应商(OpenAI、Azure OpenAI、Anthropic、Ollama 等),随后逐步扩展到其他厂商。
- 追求统一配置和统一返回结构,便于在不同模型间切换。
-
Spring AI Alibaba
- 优先支持国内主流模型服务,对阿里云生态有最佳支持。
- 为国内用户提供较好的开箱体验(示例、中文文档、演示工程等)。
-
LangChain4j
- 支持多家国际/国内模型,覆盖 Chat、Embedding、RAG、向量库等完整链路。
- 对“供应商多样性 + 高级编排能力”关注度高,适合需要频繁试验不同模型 / 检索方案的团队。
-
LangGraph
- 模型与向量库等底层能力全部复用 LangChain4j,理论上支持 LangChain4j 能接入的所有厂商。
- 更关注“如何把这些能力编排成可观测的工作流”,而不是新增模型适配。
-
如果你主要是 Spring Boot 应用,希望:
- 简单地在现有微服务里调用 LLM(问答、摘要、分类、简单 RAG)。
- 利用现有的 Spring 生态(配置、监控、安全、云原生环境)。
- 需要的是“稳定的生产级集成方式”,而不是复杂的 Agent。
- 优先选:Spring AI;国内模型优先时可考虑 Spring AI Alibaba。
-
如果你主要面向国内模型生态,且:
- 使用阿里云等国内大模型服务为主。
- 希望官方示例、中文文档、本地化配置更完善。
- 需要跟 Spring 保持一致风格,同时解决国内网络/环境的细节问题。
- 优先选:Spring AI Alibaba(通常仍然基于/兼容 Spring AI 体系)。
-
如果你需要构建复杂 LLM 应用,希望:
- 做 Agent、多步推理、工具调用编排、复杂 RAG 和工作流。
- 在 Java 世界里获得与 Python LangChain 相近的能力。
- 框架独立,可运行在非 Spring 环境甚至桌面/命令行应用中。
- 优先选:LangChain4j,并按需与 Spring Boot 集成。
-
如果你的应用已经比较复杂,希望:
- 对话中存在大量条件分支、循环、人工干预(例如:客服流转、审批流、跨系统编排)。
- 需要把多个 Agent / 工具 / RAG 流程组织成一个整体工作流,且希望后续能可视化、可观测。
- 希望在 LangChain4j 的基础上,获得更清晰的“状态 + 流程图”编码体验。
- 优先选:在 LangChain4j 之上叠加 LangGraph(LangChain4j 负责能力层,LangGraph 负责流程层)。
| 维度 | Spring AI | Spring AI Alibaba | LangChain4j | LangGraph |
|---|---|---|---|---|
| 核心定位 | Spring 官方 LLM 集成 | 面向国内模型生态的 Spring AI 增强/扩展 | Java 版 LangChain,LLM 编排框架 | 基于 LangChain4j 的图式工作流 / 有状态 Agent 编排框架 |
| 是否依赖 Spring | 是,深度绑定 Spring/Spring Boot | 是,延续 Spring AI 模型 | 否(可选 Spring 集成) | 否,依赖 LangChain4j,可与任意 Java 应用/框架组合 |
| 编程模型 | 客户端抽象 + 配置驱动 | 同 Spring AI,增加国内厂商适配 | Chain / Agent / Tool / Memory 编排 | Graph / Node / State + Agent / Tool 的图式编排 |
| 国内模型支持友好度 | 取决于具体适配器,整体在增强中 | 高,优先考虑国内主流模型和本地化场景 | 视具体适配器而定,一般覆盖但未必本地化最佳 | 跟随底层 LangChain4j,取决于具体适配器 |
| 复杂智能体/多步骤编排 | 基础支持,非核心卖点 | 与 Spring AI 类似 | 核心能力,适合复杂 LLM 应用 | 面向复杂状态机、多 Agent、多分支流程,是核心卖点 |
| 适合人群 | Spring 后端团队 | 使用国内云厂商、偏 Spring 体系的后端团队 | 想在 Java 中玩转 LangChain 思路的开发者 | 已经在用 LangChain4j,希望把复杂对话和流程做成可观测工作流的团队 |
粗略理解:
- Spring AI:Spring 里的“LLM 驱动层”
- Spring AI Alibaba:Spring AI 在国内模型生态上的增强版
- LangChain4j:Java 版 LangChain,用来编排复杂 AI 应用
- LangGraph:基于 LangChain4j 的有状态 Agent / 工作流图框架
-
按生态阵营划分
- Spring 生态线:
Spring AI(官方 LLM 接入层) ←Spring AI Alibaba(面向国内模型的增强版)。 - LangChain 生态线(Java):
LangChain4j(通用编排框架) ←LangGraph(图式工作流 / 有状态 Agent 增强层)。
- Spring 生态线:
-
一张关系小图(抽象示意)
Spring 生态(接入层) LangChain 生态(编排层,Java)
Spring Boot / Spring Cloud 应用 任意 Java 应用 / 服务
│ │
▼ ▼
+-----------+ +--------------+
| Spring AI | | LangChain4j |
+-----------+ +--------------+
│ │
(增强国内模型支持 / 本地化) (增强有状态 Agent / 工作流)
▼ ▼
+---------------------------+ +------------------------+
| Spring AI Alibaba(CN) | | LangGraph(on LC4j) |
+---------------------------+ +------------------------+
-
按层次角色划分
- 接入层:
Spring AI、Spring AI Alibaba主要解决“如何在 Spring 应用里接好模型、配好参数、跑在生产环境中”。 - 编排层:
LangChain4j、LangGraph主要解决“如何把模型 + 工具 + 向量库编排成复杂的对话/工作流”。
- 接入层:
-
增强关系(纵向类比)
Spring AI Alibaba之于Spring AI:在保持 Spring AI 编程模型的前提下,加强国内模型厂商支持和本地化体验。LangGraph之于LangChain4j:在保持 LangChain4j 能力的前提下,引入图式状态机,让复杂 Agent / 对话流程更易表达与维护。
-
在本仓库中的推荐使用方式
- 如果你是 Spring 团队,想先把 LLM 接入到现有服务:从
Spring AI/Spring AI Alibaba入手。 - 如果你想进一步做复杂多轮对话、Agent 编排:在模型接入稳定后,引入
LangChain4j,并按需叠加LangGraph做工作流编排。
- 如果你是 Spring 团队,想先把 LLM 接入到现有服务:从
- 适用场景
- 不想自己运维,只希望“直接调用 API 就能用”的 RAG、语义搜索、推荐等大规模在线服务。
- 特点
- 完全托管 SaaS,自动扩缩容,多副本、高可用;支持向量 + 元数据过滤、分库分表等。
- 优点
- 基本零运维;可支撑大规模数据和高 QPS;生态成熟(SDK、多种平台集成)。
- 缺点
- 成本相对高;厂商锁定明显;对国内用户网络/延迟不一定友好。
- 适用场景
- TB 级数据、大规模 RAG / 语义检索、推荐系统;需要私有化或国产化部署的企业场景。
- 特点
- CNCF 开源项目,多种向量索引(HNSW、IVF、DiskANN 等),支持水平扩展;Zilliz Cloud 提供托管版。
- 优点
- 性能强,社区活跃;生态成熟(SDK、可视化工具、与 RAG 框架集成好);适合企业级生产环境。
- 缺点
- 集群部署和运维相对复杂(依赖组件较多);对小规模项目而言可能显得“过重”。
- 适用场景
- 需要高性能、强过滤能力,又希望部署简单的在线向量检索服务。
- 特点
- Rust 实现,单机性能好;支持向量 + 结构化过滤、多租户、持久化;提供集群模式。
- 优点
- 部署轻量、依赖少;性能和性价比好;API 设计友好。
- 缺点
- 生态和社区规模略小于 Milvus;高级工具链相对少一些。
- 适用场景
- 既需要知识图谱/对象建模,又要向量检索和混合检索(文本 + 向量)的知识库场景。
- 特点
- 类“图 + 向量”的数据库,有 schema / class / 属性;内置 BM25 + 向量混合检索和一些扩展模块。
- 优点
- 适合面向“实体/对象”的语义知识库;混合检索能力好;文档比较完善。
- 缺点
- 架构偏重;对 schema 与类的建模有学习成本;国内社区相对较小。
- 适用场景
- 已经大量使用 Postgres,希望在一个库里同时管理结构化数据和向量(中小规模 RAG、语义搜索)。
- 特点
- 通过 pgvector 扩展在 Postgres 中直接存向量,支持索引和相似度查询;使用 SQL 写检索逻辑。
- 优点
- 部署简单,可复用现有 Postgres 运维体系;事务、备份、权限等能力齐全;方便做“向量 + 业务数据”的联合查询。
- 缺点
- 面向超大规模向量和极高 QPS 时性能有限;索引和存储成本偏高;向量算法选择比专用向量库少。
- 适用场景
- 原本就用 ES/OS 做全文检索,希望顺带支持语义搜索/向量检索,而不想引入额外组件。
- 特点
- 向量字段 + 近似 kNN;可以同时用 BM25 + 向量打分做混合检索。
- 优点
- 一套集群同时搞定全文 + 结构化 + 向量;生态成熟、运维经验丰富。
- 缺点
- ES 本身较重,资源消耗大;向量检索属于“附加能力”,在极端性能/延迟场景不如专用向量库。
- 适用场景
- 对延迟极度敏感、数据量中小、数据适合放在内存里的场景(对话短期记忆、session 级向量缓存等)。
- 特点
- 在 Redis 中为文档增加向量字段,并建立向量索引;全部在内存里计算。
- 优点
- 延迟极低,开发简单;可顺便利用 Redis 的缓存、TTL、发布订阅等能力。
- 缺点
- 内存成本高、容量受限;不适合超大规模数据;复杂检索需求时维护成本上升。
- 适用场景
- 本地快速搭建 RAG Demo、PoC、小工具,尤其是 Python 场景。
- 特点
- 内嵌/本地向量库,零运维、安装简单,常与 LangChain 等框架深度集成。
- 优点
- 上手非常快,适合验证想法和小规模项目。
- 缺点
- 不适合生产级、分布式和高可用场景;多语言支持和生态相对弱。
- 如果数据量和并发都很大,且是长期的核心业务:
- 优先考虑 Milvus / Zilliz、Qdrant、Weaviate 等专用向量库;不想运维时可以考虑托管服务(如 Zilliz Cloud、Pinecone)。
- 如果团队已有稳定的 Postgres 或 ES 集群,且规模中小:
- 优先考虑 Postgres+pgvector 或 Elasticsearch/OpenSearch 的向量能力,减少新组件。
- 如果对延迟极度敏感、数据规模不大:
- 可以考虑 Redis 向量能力,用作对话短期记忆或 session 级缓存。
- 如果只是本地开发、实验或 PoC:
- 使用 Chroma 等本地向量库即可,后续再迁移到生产级向量数据库。
RAG 工作流(与上方示意图中的节点和箭头一一对应)
[文档] --切分--> [chunks] --Embedding--> [向量数据库]
用户 -----------------------> [问题] --Embedding--> [向量] --检索--> [向量数据库]
^ | |
| | v
| | [context]
| | |
| +---------------------------> [prompt] <-------+
| |
| v
+--------------------------- response ------------------------ [LLM]
- 在 Spring AI、LangChain4j、LangGraph 等框架中,Tools(工具调用 / Function Calling)本质上是:
- 一组由开发者实现的“受控函数”,对外暴露清晰的名称、入参和返回值;
- 这些描述会以结构化方式(schema)告诉大模型,让大模型在需要时主动“调用函数”,而不是只靠自然语言胡乱猜。
- 作用可以概括为:
- 把“只能聊天的模型”升级成“能调用系统能力的智能体”(查库、HTTP 请求、执行业务逻辑等);
- 明确模型可用的能力边界,降低安全风险和幻觉(模型必须通过 Tools 才能动数据)。
业务代码 / 应用程序
│
│ 调用
v
[ChatClient / Agent]
│
自然语言对话 / Tool 调用协议
│
v
[LLM / Model]
│
(根据工具描述决定是否调用某个 Tool)
│ function call
v
[Tools:Java 方法等]
│
┌─────────────┼──────────────┐
v v v
数据库 向量数据库 第三方 API
- 对开发者:
- 只需要用代码实现好 Tools(例如 Spring Bean / Java 方法),并按框架要求暴露出去;
- 其余工作(向模型暴露 tool schema、解析 function_call、执行并把结果回填给模型)由框架负责。
- 对模型:
- 它只“看见”一个个带说明文档的工具列表,按需要选择调用哪些工具、以什么参数调用。
-
模型本身更“胖”
- 多模态模型 = 文本 LLM + 图像/音频编码器 + 对齐模块,参数更多、推理图更复杂。
- 即便没有传图片/音频,这套结构仍然要跑,单 token 计算量几乎一定大于同家族的纯文本模型。
-
RAG 带来的额外链路
- 相比“直接聊天”,RAG 多了几步:问题 Embedding、向量库检索、拼接 context,再交给模型生成。
- 每一步都增加一定延迟,当最终调用的是本来就偏慢的多模态模型时,整体响应会更慢。
-
上下文更长,计算量线性变大
- 多模态模型上下文窗口通常更大,RAG 又会把检索到的 chunks 全部拼进 prompt。
- LLM 的复杂度大致随“输入 token + 输出 token”线性(甚至略高)增长,长上下文 + 大模型 = 显著变慢。
-
服务端策略和资源调度
- 厂商往往对多模态模型设置更保守的速率限制,或者放在资源更紧张的集群中。
- 即使用的是同版本号,实测首 token 延迟和整体吞吐通常都不如纯文本模型。
-
只做文本对话(包含 RAG)时
- 优先选择对应的纯文本大模型版本(例如同家族的 text-only 模型),多模态模型保留给确实需要“看图/看表”的场景。
-
拆分 Embedding 模型与对话模型
- 文档向量离线用专门的 embedding 模型计算,在线查询时也用轻量的 embedding 模型。
- 最终回答使用一个高效的文本对话模型,而不是多模态模型。
-
控制 RAG 的负担
- 合理设置 topK、chunk 大小和拼接策略,避免每轮调用塞入过多 context。
- 对长对话定期做“总结压缩”,减少历史消息 token 数量。
-
区分文本请求和多模态请求
- 在网关或业务层按请求类型路由:纯文本走文本模型,多模态任务(图文问答等)才调用多模态模型。
- MCP(Model Context Protocol)是用来规范“大模型 ↔ 外部工具 / 资源 / 提示模板”交互的开放协议。
- 核心思想:
- 把 Tools、Resources、Prompts 抽象成一个标准化的“能力服务”(MCP Server);
- 任何支持 MCP 的客户端(包括 Spring AI、编辑器插件、命令行工具等)都可以发现并调用这些能力;
- 协议本身与具体模型厂商无关,仅定义消息格式与传输方式(stdio / SSE / HTTP 等)。
用户 / 业务调用
|
v
+--------------------+
| 应用程序 / 服务 |
| (Spring Boot 等) |
+---------+----------+
|
| 自然语言请求 (chat)
v
+--------------------+
| LLM 客户端层 |
| (Spring AI 等) |
+---------+----------+
|
| 1. 调用大模型,携带可用工具描述
v
+---------+
| LLM |
| Model |
+----+----+
|
| 2. 模型决定调用某个外部 Tool
| (function_call / tool_call)
v
+--------------------+
| MCP Client |
+---------+----------+
|
| 3. 按 MCP 协议转发调用
v
+--------------------+
| MCP Server |
| (工具与资源服务) |
+---------+----------+
|
+---------+----------+
| DB / 向量库 / API |
+--------------------+
- 应用只需要面向 LLM 客户端层(如 Spring AI)编写对话逻辑;
- LLM 通过 MCP Client/Server 访问统一的工具与数据,不再被某个应用或厂商的专有 Tool 定义锁死。
-
Tools
- Tools 是 MCP 里的“执行者”,让 LLM 不只是嘴炮,还能干活。简单说,就是服务器提供一些函数或者 API,LLM 可以直接调用去完成具体任务。
- 面向“动作/调用”的能力,类似一组可以被模型调用的受控函数或命令;
- 每个 Tool 有名称、说明和参数 schema(通常是 JSON Schema),返回结构化结果;
- 常用于查数据库、查向量库、调用业务接口、触发工作流等。
-
Resources
- 相当于给 LLM 提供“原材料”;服务器(MCP Server)把这些数据暴露出来,客户端(比如 LLM 应用)可以读取它们,然后塞进模型的上下文里去推理或者生成内容。比如你有个日志文件 app.log,通过 Resources 就能让 LLM 直接看到里面的错误信息。
- 面向“数据/文档”的只读资源抽象,可以理解为受控的“文件 / 文档 / 记录”视图;
- 客户端可以枚举可用资源,或按标识读取具体内容;
- 适用于暴露说明文档、配置、知识库条目等,而不直接开放底层数据库或文件系统。
-
Prompts
- Prompts 是 MCP 的“模板大师”,提供预定义的交互模式或者推理指引。可以说它是 LLM 的“剧本”,告诉它怎么开口、怎么思考。
- 服务器定义好一堆 Prompt 模板(比如“写个产品描述”或者“调试错误”),客户端可以直接选一个,填入参数,然后丢给 LLM 执行。
- 面向“提示/模板”的能力,用于集中管理系统提示、角色设定、任务说明等;
- 支持变量占位符,客户端在使用时填充具体内容;
- 多个应用可以复用同一套提示模板,避免在各处复制粘贴提示词。
三者的关系可以简单理解为:
- Tools:负责“做事”;
- Resources:负责“提供数据”;
- Prompts:负责“指导模型如何理解任务及如何使用前两者”。
以“技术面试流程”为例,可以这样理解:
- 如果把模型当成一个“面试助理”,那么:
- Tools 像是它可以执行的一系列操作按钮:
安排面试时间:调用日程系统给候选人和面试官找共同空档,并创建日历事件;更新候选人状态:把候选人标记为“已初面 / 待终面 / 已发 Offer”等;记录面试反馈:把面试官的打分和评语写入招聘系统。
- Resources 像是它随时可以查阅的资料库:
- 候选人的简历、作品集、测评结果;
- 岗位 JD、团队介绍文档;
- 公司统一的面试流程和评估标准说明。
- Prompts 则像是给这位“面试助理”的工作手册和话术模板:
- 系统提示:
你是一名严谨的技术面试助理,要根据岗位 JD 和面试标准帮助面试官做判断; - 模板提示:
根据候选人表现,用专业但礼貌的语气生成一份面试反馈邮件; - 变量占位:
{候选人姓名}、{岗位名称}、{面试结果}等在使用时再填充。
- 系统提示:
- Tools 像是它可以执行的一系列操作按钮:
在这个类比下:
- Tools 让助理“能真正动手做事”(排期、更新系统);
- Resources 让助理“心中有数”(了解候选人和岗位、知道公司规则);
- Prompts 让助理“说对话、按对的流程办事”(用合适的风格和步骤执行面试相关任务)。
在 spring_ai_alibaba-demo/src/main/java/com/zhoubyte/spring_ai_alibaba_demo/rag/RagChatClientController.java 中,使用的是 TokenTextSplitter 对输入文本进行切分并写入 PgVectorStore。这里补充几种常见的文档切分方案,方便在不同业务中进行选择。
代码示例:
TokenTextSplitter tokenTextSplitter = TokenTextSplitter.builder()
.withChunkSize(50)
.withKeepSeparator(true)
.withMaxNumChunks(1024)
.withMinChunkLengthToEmbed(20)
.withMinChunkSizeChars(10)
.build();核心参数含义(结合源码推断):
chunkSize:每个分片的最大 token 数(基于 jtokkit 进行编码),控制单个 chunk 的上下文长度。minChunkSizeChars:在选择切分位置时,最小字符数阈值,用来避免切得过碎(比如刚好在换行符前切断)。minChunkLengthToEmbed:最终参与 embedding 的最小长度,小于该长度的分片会被丢弃,不入库,减少噪声与向量数量。maxNumChunks:单个输入允许生成的最大分片数,防止一次性上传超长文档产生过多 chunk。keepSeparator:是否保留换行符等分隔符;保留有利于维持段落/格式信息,不保留则更“干净”。
优点:
- 以 token 为单位切分,能更精确地控制接近模型上下文窗口(比如 512、1024 tokens)的尺寸。
- 适合中英文混合文本,不需要显式处理多语言的字符长度差异。
- 搭配
minChunkLengthToEmbed可以自动过滤过短噪声,减少向量存储与检索开销。
缺点:
- 需要依赖 tokenizer(jtokkit),实现复杂度高于简单字符分割。
- 默认不会显式感知“语义边界”(句子、段落、标题),可能在中间切断语句。
适用场景:
- 已经明确使用某个 LLM 的 token 限制(如 4k/8k/32k),希望严格控制 chunk 大小的通用 RAG 场景。
- 知识库文本结构不算特别规整(例如 FAQ、Chat 记录等),更关心“上下文长度”而非完美的段落边界。
下面几类方案是 RAG 项目里最常用的文档切分思路,可以在 Spring AI 中通过自定义 TextSplitter 或自定义 DocumentTransformer 来实现,在 LangChain4j 等框架中也有类似抽象。
| 策略类型 | 典型实现方式 | 关键参数例子 | 优点 | 缺点 | 推荐使用场景 |
|---|---|---|---|---|---|
| 固定字符长度切分 | 按 N 个字符一刀切,或带少量重叠滑动窗口 | chunkSizeChars、chunkOverlapChars |
实现最简单、性能好;不依赖 tokenizer 或语言特性 | 容易把一句话或一个段落切开,语义边界不友好 | 小型 Demo、对语义要求不高的日志类文本 |
| 句子/段落优先切分 | 先按空行拆段落,再按句号、问号、换行等拆句 | separators(如 ["\n\n",".","。","?","?"] 等)、maxCharsPerChunk |
更贴近自然语言边界,单个 chunk 语义完整度更高 | 不同语言标点差异大,规则维护成本高;chunk 长度不均匀 | FAQ、说明文档、产品手册等结构化自然语言文档 |
| 基于文档结构的层级切分 | 利用 Markdown 标题、HTML 标签、PDF 目录等 | maxSectionDepth、maxSectionSize、mergeShortSections |
能保留标题-正文层次,检索时更易关联到人类可读的章节 | 需要针对不同格式写解析器;实现和测试成本较高 | 技术文档、API 文档、知识库 Wiki、规章制度类长文档 |
| 基于语义/Embedding 的切分 | 对连续文本滚动计算 embedding,根据相似度切断 | similarityThreshold、windowSize、maxSegmentLength |
可以在语义“话题变化处”切分,chunk 语义一致性最好 | 计算成本最高,需要两次 embedding;实现复杂度也最高 | 对答案质量极其敏感的高价值场景,如法律条款、医学资料等 |
一些实践经验:
- 如果只是做 RAG Demo 或内部小工具:优先用
TokenTextSplitter或简单“固定字符长度 + 小重叠”的方案即可。 - 如果面向生产、且文档是 Markdown/手册类:可以考虑“结构化层级切分(标题/段落优先) + Token 级限长”组合。
- 如果业务对召回准确性要求非常高(如法律、金融风控):可尝试在关键文档上使用“语义切分”,但要接受更高的计算和实现成本。