项目模块介绍
这篇文档带着大家一起看看 Ragent 的项目整体结构,搞清楚每个目录和模块各自负责什么。
项目中的代码并不是一成不变的,未来如果有更好的设计思路,会进行重构、优化,甚至新增功能模块。如果发现文档内容和实际代码对不上,请联系马哥,谢谢。
根目录文件一览
1. pom.xml
这是 Maven 父 POM,管理所有子模块的依赖版本和构建插件。打开它你会看到四个 <module>:
<modules>
<module>bootstrap</module>
<module>framework</module>
<module>infra-ai</module>
<module>mcp-server</module>
</modules>
它通过 <dependencyManagement> 统一锁定了所有关键依赖的版本号,比如 Spring Boot 3.5.7、Milvus SDK 2.6.6、MyBatis Plus 3.5.14 等等。子模块引用这些依赖时不需要再写版本号,避免版本冲突。
2. lombok.config
Lombok 的全局配置文件。几个关键设置:
- 让 Jacoco 忽略 Lombok 生成的代码(这个是 GitHub 统计时需要,大家忽 略即可)。
- 禁止
@Data自动调用callSuper,避免继承场景下生成不合理的equals/hashCode。 - 允许 Spring 的
@Qualifier注解在 Lombok 构造器注入时被正确复制。
3. .gitignore
定义了哪些文件不纳入 Git 管理:构建产物(target/)、IDE 配置(.idea/)、前端的 node_modules 和 .env.local、以及日志目录等。
4. mvnw / mvnw.cmd
Maven Wrapper 脚本,分别对应 Unix 和 Windows。有了它,即使机器上没有全局安装 Maven,也能直接用 ./mvnw 来构建项目。
5. LICENSE
Apache License 2.0 许可证全文。
四大子模块
Ragent 的代码按职责拆成了四个模块,依赖关系大致是这样的:
bootstrap ──依赖──▶ framework
│ ▲
└──依赖──▶ infra-ai ┘
mcp-server(独立运行)
bootstrap 是最上层的业务模块,它依赖 framework(通用基础设施)和 infra-ai(AI 能力层)。mcp-server 是一个独立的 Spring Boot 应用,通过 HTTP 提供 MCP 工具调用服务。
framework —— 通用基础设施层
这个模块不包含任何业务逻辑,放的全是跨模块复用的基础组件。任何模块都可能依赖它。
1. 统一数据结构
Result<T>:标准 API 响应包装。所有接口返回的都是这个结构,包含code(状态码,"0"表示成功)、message、data,以及一个requestId用于链路追踪。ChatRequest:发给大模型的请求体。封装了messages(对话历史)、temperature、topP、maxTokens等参数,用 Builder 模式构建。不管底层接哪家大模型,上层都用这一个类。ChatMessage:对话中的单条消息,包含角色(SYSTEM/USER/ASSISTANT)和内容,提供了system()、user()、assistant()三个工厂方法。RetrievedChunk:向量检索返回的单条结果,包含id、text和相似度score。
2. 异常体系
BaseErrorCode:错误码枚举,遵循阿里巴巴的 A/B/C 分类规范。A 类是客户端错误(参数校验失败、重复提交等),B 类是服务端错误(超时、内部异常),C 类是远程调用错误(第三方接口挂了)。AbstractException:异常基类,携带错误码和错误消息。RemoteException:专门用于远程服务调用失败的异常。GlobalExceptionHandler:全局异常拦截器,把各种异常统一转成Result<Void>返回给前端,同时记录日志。它还处理了 Sa-Token 的NotLoginException和NotRoleException。
3. 用户上下文
UserContext:基于TransmittableThreadLocal的用户信息容器。在 请求入口设置当前用户信息,后续业务代码随时可以通过UserContext.getUserId()获取,即使跨线程池也不会丢。这里之所以用TransmittableThreadLocal而不是普通ThreadLocal,是因为普通ThreadLocal在线程池场景下会失效——线程被复用时,子线程拿不到父线程设置的值。TransmittableThreadLocal(来自阿里的 TTL 库)能在线程池提交任务时自动传递上下文,而 RAG 系统大量使用异步线程池做检索和模型调用,所以这个选择是必须的。LoginUser:用户数据传输对象,包含userId、username、role、avatar。
4. 链路追踪与幂等
RagTraceContext:分布式链路追踪上下文,用 TTL 实现跨线程传递。维护traceId、taskId,以及一个节点栈来追踪 DAG 执行路径。IdempotentSubmit:幂等注解,防止表单重复提交。用 SpEL 表达式自定义幂等键。
5. SSE 工具
SseEmitterSender:对 Spring 的SseEmitter做了线程安全封装。通过AtomicBoolean保证连接只关闭一次,发送前检查连接状态,避免往已关闭的连接写数据时抛异常。
infra-ai —— AI 模型基础设施层
这个模块是整个系统和大模型之间的桥梁。它屏蔽了不同 AI 服务商的接口差异,对上层提供统一的调用方式。内部按能力分为四个子包:chat(对话)、embedding(向量化)、rerank(重排序)、model(路由与容错)。
1. chat 子包 —— 对话能力
1.1 客户端与服务接口
ChatClient:对话客户端的接口定义。BaiLianChatClient:对接阿里云百炼平台。SiliconFlowChatClient:对接 SiliconFlow 平台。OllamaChatClient:对接本地部署的 Ollama。LLMService:大模型调用的顶层接口,提供流式和非流式两种调用方式。RoutingLLMService:LLMService的实现,通过ModelSelector选候选模型,再交给ModelRoutingExecutor执行(自动容错降级)。
1.2 流式相关
StreamCallback:流式回调接口,定义了onToken(收到一个 token)、onThinking(思考过程)、onComplete(完成)、onError(出错)等事件。StreamAsyncExecutor:异步执行流式调用,确保不阻塞主线程。StreamCancellationHandle/StreamCancellationHandles:用来取消正在进行的流式请求(比如用户关掉了页面)。OpenAIStyleSseParser:解析 OpenAI 风格的 SSE 响应。很多国内大模型平台的流式接口格式都兼容 OpenAI,所以这个解析器能复用。FirstPacketAwaiter:等待流式响应的第一个数据包到达,用于超时检测。
2. embedding 子包 —— 向量化能力
EmbeddingClient:向量化客户端接口。SiliconFlowEmbeddingClient/OllamaEmbeddingClient:两个具体实现。EmbeddingService:向量化服务接口。RoutingEmbeddingService:带路由和容错的实现,逻辑跟RoutingLLMService一样——选候选、降级、熔断。