Skip to content

Commit 020e5c3

Browse files
committed
feat(ragent): 拆分模块并新增 Agent 执行架构支持
- 新增 agent 模块及相关 Maven 配置,实现 Agent 执行架构(v2 ReAct) - 拆分原 bootstrap 模块为 system、rag、agent 三个模块,重构项目结构 - 调整依赖关系,bootstrap 模块精简为启动装配层,仅含启动类与配置 - 调整配置文件,添加 agent 执行架构参数支持 - 移动部分实体类和配置类到对应新模块,更新包导入路径 - stream 任务管理器及相关类迁移并优化,支持跨节点流式取消管理 - 修改测试类引用,支持新的测试配置环境 - 完善 rag 模块依赖,添加关键词检索、文件解析等组件支持 - 增加对系统支撑域(用户认证和审计)的 system 模块支持 - 修改 WebMvc 配置,新增体验环境只读模式拦截器注册机制 - 优化提示词服务,支持根据上下文控制引用规则拼接行为 - README 更新,完善七个后端模块职责说明和整体架构说明
1 parent 7f3a7f3 commit 020e5c3

576 files changed

Lines changed: 434 additions & 175 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,16 @@ RAG 项目的核心竞争力不在于你用了多强的模型,而在于工程
175175

176176
## 🏗️ Ragent 核心设计
177177

178-
采用前后端分离的模块化单体架构,后端按职责分为四个 Maven 模块:
178+
采用前后端分离的模块化单体架构,后端按职责分为七个 Maven 模块:
179179

180180
| 模块 | 职责 |
181181
|:---|:---|
182-
| `framework` | 统一响应与异常、认证上下文、幂等、分布式 ID、MQ 适配、TraceSSE 等通用基础能力 |
182+
| `framework` | 统一响应与异常、认证上下文、幂等、分布式 ID、MQ 适配、TraceSSE 与跨节点流式取消等通用基础能力 |
183183
| `infra-ai` | Chat / Embedding / Rerank / VLM 模型客户端、模型档位、路由、首包探测、健康状态与降级 |
184-
| `bootstrap` | RAG 问答、知识库、入库 Pipeline、意图树、检索、会话、审计及管理端 API |
184+
| `system` | 用户认证与审计日志,位于各业务引擎之下的系统支撑域 |
185+
| `rag` | RAG 问答、知识库、入库 Pipeline、意图树、检索、会话及管理端 API |
186+
| `agent` | Agent 执行架构(v2 ReAct)骨架,RAG 管线将以工具形式接入 |
187+
| `bootstrap` | 启动装配层,仅含启动类与主配置 |
185188
| `mcp-server` | 基于 MCP Java SDK 的独立工具服务,内置天气、票务、销售与联网搜索示例 |
186189

187190
这个分层不是为了炫技,而是把业务编排、AI 供应商差异和通用基础设施隔离开。切换模型、向量库或对象存储时,核心问答流程不需要跟着重写。

agent/pom.xml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.nageoffer.ai</groupId>
7+
<artifactId>ragent</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
</parent>
10+
11+
<!-- Agent 执行架构(v2 ReAct):仅通过窄接口消费 rag 的检索门面与人设解析 -->
12+
<artifactId>agent</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>com.nageoffer.ai</groupId>
17+
<artifactId>rag</artifactId>
18+
<version>${project.version}</version>
19+
</dependency>
20+
21+
<dependency>
22+
<groupId>io.agentscope</groupId>
23+
<artifactId>agentscope-core</artifactId>
24+
</dependency>
25+
26+
<dependency>
27+
<groupId>io.agentscope</groupId>
28+
<artifactId>agentscope-extensions-model-openai</artifactId>
29+
</dependency>
30+
</dependencies>
31+
</project>

bootstrap/pom.xml

Lines changed: 3 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -9,123 +9,21 @@
99
</parent>
1010

1111
<artifactId>bootstrap</artifactId>
12+
<description>启动装配层:仅启动类与配置相关代码,业务代码禁止入内</description>
1213

1314
<dependencies>
1415
<dependency>
1516
<groupId>com.nageoffer.ai</groupId>
16-
<artifactId>framework</artifactId>
17+
<artifactId>rag</artifactId>
1718
<version>${project.version}</version>
1819
</dependency>
1920

2021
<dependency>
2122
<groupId>com.nageoffer.ai</groupId>
22-
<artifactId>infra-ai</artifactId>
23+
<artifactId>agent</artifactId>
2324
<version>${project.version}</version>
2425
</dependency>
2526

26-
<dependency>
27-
<groupId>org.springframework.boot</groupId>
28-
<artifactId>spring-boot-starter-webmvc</artifactId>
29-
</dependency>
30-
31-
<dependency>
32-
<groupId>io.milvus</groupId>
33-
<artifactId>milvus-sdk-java</artifactId>
34-
</dependency>
35-
36-
<!-- 关键词检索(可选):仅 rag.keyword.type=es 时使用,版本由 Spring Boot BOM 管理 -->
37-
<dependency>
38-
<groupId>co.elastic.clients</groupId>
39-
<artifactId>elasticsearch-java</artifactId>
40-
</dependency>
41-
42-
<!-- 解析 PDF / DOC / DOCX / Markdown 等 -->
43-
<dependency>
44-
<groupId>org.apache.tika</groupId>
45-
<artifactId>tika-parsers-standard-package</artifactId>
46-
</dependency>
47-
48-
<dependency>
49-
<groupId>org.apache.tika</groupId>
50-
<artifactId>tika-core</artifactId>
51-
</dependency>
52-
53-
<!-- Markdown 结构化解析(AST 输出 HeadingBlock / ParagraphBlock 等) -->
54-
<dependency>
55-
<groupId>org.commonmark</groupId>
56-
<artifactId>commonmark</artifactId>
57-
</dependency>
58-
59-
<dependency>
60-
<groupId>org.commonmark</groupId>
61-
<artifactId>commonmark-ext-gfm-tables</artifactId>
62-
</dependency>
63-
64-
<dependency>
65-
<groupId>org.apache.xmlgraphics</groupId>
66-
<artifactId>batik-transcoder</artifactId>
67-
</dependency>
68-
69-
<dependency>
70-
<groupId>org.apache.xmlgraphics</groupId>
71-
<artifactId>batik-codec</artifactId>
72-
</dependency>
73-
74-
<dependency>
75-
<groupId>org.postgresql</groupId>
76-
<artifactId>postgresql</artifactId>
77-
</dependency>
78-
79-
<dependency>
80-
<groupId>com.pgvector</groupId>
81-
<artifactId>pgvector</artifactId>
82-
<version>0.1.6</version>
83-
</dependency>
84-
85-
<dependency>
86-
<groupId>org.springframework.boot</groupId>
87-
<artifactId>spring-boot-starter-jdbc</artifactId>
88-
</dependency>
89-
90-
<dependency>
91-
<groupId>software.amazon.awssdk</groupId>
92-
<artifactId>s3</artifactId>
93-
</dependency>
94-
95-
<!-- 阿里云 OSS SDK:rag.storage.type=oss 时启用;含 jdom2/commons 传递依赖,如与 Spring BOM 冲突再按需 exclude -->
96-
<dependency>
97-
<groupId>com.aliyun.oss</groupId>
98-
<artifactId>aliyun-sdk-oss</artifactId>
99-
</dependency>
100-
101-
<dependency>
102-
<groupId>org.mockito</groupId>
103-
<artifactId>mockito-core</artifactId>
104-
<scope>test</scope>
105-
</dependency>
106-
107-
<!-- LightRAG 客户端归属/删除谓词的 HTTP 桩测试,版本由 OkHttp BOM 统一管理 -->
108-
<dependency>
109-
<groupId>com.squareup.okhttp3</groupId>
110-
<artifactId>mockwebserver3</artifactId>
111-
<scope>test</scope>
112-
</dependency>
113-
114-
<dependency>
115-
<groupId>org.springframework.boot</groupId>
116-
<artifactId>spring-boot-starter-validation</artifactId>
117-
</dependency>
118-
119-
<dependency>
120-
<groupId>io.modelcontextprotocol.sdk</groupId>
121-
<artifactId>mcp</artifactId>
122-
</dependency>
123-
124-
<dependency>
125-
<groupId>io.modelcontextprotocol.sdk</groupId>
126-
<artifactId>mcp-json-jackson2</artifactId>
127-
</dependency>
128-
12927
<dependency>
13028
<groupId>io.github.mouzt</groupId>
13129
<artifactId>bizlog-sdk</artifactId>
@@ -144,11 +42,6 @@
14442
</exclusion>
14543
</exclusions>
14644
</dependency>
147-
148-
<dependency>
149-
<groupId>javax.validation</groupId>
150-
<artifactId>validation-api</artifactId>
151-
</dependency>
15245
</dependencies>
15346

15447
<build>

bootstrap/src/main/resources/application.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ ragent:
4545
eval:
4646
enabled: true
4747

48+
# Agent 执行架构(ragent.engine.type=agent 时生效);单模型无 fallback,供应商可用性由 provider 侧保障
49+
agent:
50+
chat:
51+
provider: bailian # 引用 ai.providers 下的供应商,取其 url / api-key / endpoints.chat
52+
model: qwen3-max # 直接传给 OpenAI 兼容端点的模型名
53+
max-iters: 10 # ReAct 循环上限,超出后熔断收尾
54+
max-retries: 2 # 单次模型调用失败重试次数
55+
sse-timeout-ms: 300000
56+
4857
rag:
4958
storage:
5059
type: s3 # 可选 s3(rustfs / minio)/ oss(阿里云)

framework/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,10 @@
8080
<groupId>org.apache.rocketmq</groupId>
8181
<artifactId>rocketmq-spring-boot-starter</artifactId>
8282
</dependency>
83+
84+
<dependency>
85+
<groupId>org.postgresql</groupId>
86+
<artifactId>postgresql</artifactId>
87+
</dependency>
8388
</dependencies>
8489
</project>

bootstrap/src/main/java/com/nageoffer/ai/ragent/knowledge/dao/handler/JsonbTypeHandler.java renamed to framework/src/main/java/com/nageoffer/ai/ragent/framework/database/JsonbTypeHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
package com.nageoffer.ai.ragent.knowledge.dao.handler;
18+
package com.nageoffer.ai.ragent.framework.database;
1919

2020
import org.apache.ibatis.type.BaseTypeHandler;
2121
import org.apache.ibatis.type.JdbcType;

bootstrap/src/main/java/com/nageoffer/ai/ragent/rag/service/handler/StreamTaskManager.java renamed to framework/src/main/java/com/nageoffer/ai/ragent/framework/web/StreamTaskManager.java

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,11 @@
1515
* limitations under the License.
1616
*/
1717

18-
package com.nageoffer.ai.ragent.rag.service.handler;
18+
package com.nageoffer.ai.ragent.framework.web;
1919

2020
import cn.hutool.core.util.StrUtil;
2121
import com.google.common.cache.Cache;
2222
import com.google.common.cache.CacheBuilder;
23-
import com.nageoffer.ai.ragent.rag.enums.SSEEventType;
24-
import com.nageoffer.ai.ragent.rag.dto.CompletionPayload;
25-
import com.nageoffer.ai.ragent.framework.web.SseEmitterSender;
26-
import com.nageoffer.ai.ragent.infra.chat.StreamCancellationHandle;
2723
import jakarta.annotation.PostConstruct;
2824
import jakarta.annotation.PreDestroy;
2925
import lombok.SneakyThrows;
@@ -35,8 +31,13 @@
3531

3632
import java.time.Duration;
3733
import java.util.concurrent.atomic.AtomicBoolean;
38-
import java.util.function.Supplier;
3934

35+
/**
36+
* 流式任务跨节点取消管理器
37+
* <p>
38+
* 机制层与引擎无关:注册表 + Redis 标记 + 广播主题构成统一的取消协议,
39+
* 各引擎的个性化收尾动作(补发事件、中断上游流等)以回调形式注入
40+
*/
4041
@Slf4j
4142
@Component
4243
public class StreamTaskManager {
@@ -76,22 +77,26 @@ public void unsubscribe() {
7677
redissonClient.getTopic(CANCEL_TOPIC).removeListener(listenerId);
7778
}
7879

79-
public void register(String taskId, SseEmitterSender sender, Supplier<CompletionPayload> onCancelSupplier) {
80+
/**
81+
* 注册取消收尾回调,负责补发终止事件并结束响应流
82+
* 若任务已被其他节点标记取消,回调立即执行
83+
*/
84+
public void register(String taskId, Runnable onCancelFinalizer) {
8085
StreamTaskInfo taskInfo = getOrCreate(taskId);
81-
taskInfo.sender = sender;
82-
taskInfo.onCancelSupplier = onCancelSupplier;
86+
taskInfo.finalizer = onCancelFinalizer;
8387
if (isTaskCancelledInRedis(taskId, taskInfo)) {
84-
CompletionPayload payload = taskInfo.onCancelSupplier.get();
85-
sendCancelAndDone(sender, payload);
86-
sender.complete();
88+
onCancelFinalizer.run();
8789
}
8890
}
8991

90-
public void bindHandle(String taskId, StreamCancellationHandle handle) {
92+
/**
93+
* 绑定上游流的中断动作,取消时先于收尾回调执行
94+
*/
95+
public void bindHandle(String taskId, Runnable cancelAction) {
9196
StreamTaskInfo taskInfo = getOrCreate(taskId);
92-
taskInfo.handle = handle;
93-
if (taskInfo.cancelled.get() && handle != null) {
94-
handle.cancel();
97+
taskInfo.cancelAction = cancelAction;
98+
if (taskInfo.cancelled.get() && cancelAction != null) {
99+
cancelAction.run();
95100
}
96101
}
97102

@@ -139,15 +144,13 @@ private void cancelLocal(String taskId) {
139144
return;
140145
}
141146

142-
if (taskInfo.handle != null) {
143-
taskInfo.handle.cancel();
147+
if (taskInfo.cancelAction != null) {
148+
taskInfo.cancelAction.run();
144149
}
145150

146-
// 在取消时执行回调,保存已累积的内容
147-
if (taskInfo.sender != null) {
148-
CompletionPayload payload = taskInfo.onCancelSupplier.get();
149-
sendCancelAndDone(taskInfo.sender, payload);
150-
taskInfo.sender.complete();
151+
// 在取消时执行收尾回调,保存已累积的内容
152+
if (taskInfo.finalizer != null) {
153+
taskInfo.finalizer.run();
151154
}
152155
}
153156

@@ -163,21 +166,14 @@ private String cancelKey(String taskId) {
163166
return CANCEL_KEY_PREFIX + taskId;
164167
}
165168

166-
private void sendCancelAndDone(SseEmitterSender sender, CompletionPayload payload) {
167-
CompletionPayload actualPayload = payload == null ? new CompletionPayload(null, null) : payload;
168-
sender.sendEvent(SSEEventType.CANCEL.value(), actualPayload);
169-
sender.sendEvent(SSEEventType.DONE.value(), "[DONE]");
170-
}
171-
172169
@SneakyThrows
173170
private StreamTaskInfo getOrCreate(String taskId) {
174171
return tasks.get(taskId, StreamTaskInfo::new);
175172
}
176173

177174
private static final class StreamTaskInfo {
178175
private final AtomicBoolean cancelled = new AtomicBoolean(false);
179-
private volatile StreamCancellationHandle handle;
180-
private volatile SseEmitterSender sender;
181-
private volatile Supplier<CompletionPayload> onCancelSupplier;
176+
private volatile Runnable cancelAction;
177+
private volatile Runnable finalizer;
182178
}
183179
}

pom.xml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<batik.version>1.18</batik.version>
3030
<okhttp.version>5.3.2</okhttp.version>
3131
<mcp-sdk.version>1.1.2</mcp-sdk.version>
32+
<agentscope.version>2.0.2</agentscope.version>
3233
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
3334
<javax-validation-api.version>2.0.1.Final</javax-validation-api.version>
3435
<maven-compiler-plugin.version>3.15.0</maven-compiler-plugin.version>
@@ -40,9 +41,12 @@
4041
</properties>
4142

4243
<modules>
43-
<module>bootstrap</module>
4444
<module>framework</module>
4545
<module>infra-ai</module>
46+
<module>system</module>
47+
<module>rag</module>
48+
<module>agent</module>
49+
<module>bootstrap</module>
4650
<module>mcp-server</module>
4751
</modules>
4852

@@ -186,6 +190,20 @@
186190
<version>${mcp-sdk.version}</version>
187191
</dependency>
188192

193+
<!-- AgentScope 自带 MCP SDK 0.17.0 传递依赖,被本文件的 1.1.2 统一压制;
194+
因此 agent 模块不得使用 io.agentscope.core.tool.mcp.* 客户端,MCP 走 rag 既有连接桥接 -->
195+
<dependency>
196+
<groupId>io.agentscope</groupId>
197+
<artifactId>agentscope-core</artifactId>
198+
<version>${agentscope.version}</version>
199+
</dependency>
200+
201+
<dependency>
202+
<groupId>io.agentscope</groupId>
203+
<artifactId>agentscope-extensions-model-openai</artifactId>
204+
<version>${agentscope.version}</version>
205+
</dependency>
206+
189207
<dependency>
190208
<groupId>io.github.mouzt</groupId>
191209
<artifactId>bizlog-sdk</artifactId>

0 commit comments

Comments
 (0)