重构项目模块结构,更新pom.xml文件,统一模块命名为简洁形式,移除冗余依赖,优化依赖管理。新增子模块支持,提升项目可维护性和可扩展性。

This commit is contained in:
2025-08-22 17:29:00 +08:00
parent 890c60bcb3
commit 300daf0af5
55 changed files with 1410 additions and 1164 deletions
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.emotionmuseum</groupId>
<artifactId>ai</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>ai-api</artifactId>
<name>ai-api</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.emotionmuseum</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,14 @@
package com.emotionmuseum.ai.api.client;
import com.emotionmuseum.common.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "ai")
public interface AiClient {
@GetMapping("/api/ai/chat/health")
Result<Boolean> health();
}
+7 -101
View File
@@ -3,110 +3,16 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.emotionmuseum</groupId>
<artifactId>backend</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>emotion-ai</artifactId>
<name>emotion-ai</name>
<description>AI对话服务</description>
<dependencies>
<!-- 内部模块依赖 -->
<dependency>
<groupId>com.emotionmuseum</groupId>
<artifactId>emotion-common</artifactId>
</dependency>
<!-- Spring Cloud Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Spring Boot DevTools for automatic restart -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- 暂时移除Spring AI,使用原生HTTP客户端实现 -->
<!-- HTTP客户端 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 监控指标 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.emotionmuseum.ai.AiApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<artifactId>ai</artifactId>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>server</module>
</modules>
</project>
+65
View File
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.emotionmuseum</groupId>
<artifactId>ai</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>ai-server</artifactId>
<name>ai</name>
<description>AI对话服务</description>
<dependencies>
<dependency>
<groupId>com.emotionmuseum</groupId>
<artifactId>ai-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.emotionmuseum</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
</dependencies>
</project>
@@ -4,7 +4,12 @@ import com.emotionmuseum.ai.request.*;
import com.emotionmuseum.ai.response.*;
import com.emotionmuseum.ai.service.AiChatService;
import com.emotionmuseum.ai.service.ConversationDbService;
import com.emotionmuseum.ai.entity.Conversation;
import com.emotionmuseum.ai.entity.Message;
import com.emotionmuseum.ai.dto.ChatRequest;
import com.emotionmuseum.ai.dto.ChatResponse;
import com.emotionmuseum.common.response.BasePageResponse;
import com.emotionmuseum.common.dto.PageQuery;
import com.emotionmuseum.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -15,6 +20,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
* AI聊天控制器
@@ -35,32 +41,34 @@ public class AiChatController {
@Operation(summary = "创建会话")
@PostMapping("/conversation/create")
public Result<CreateConversationResponse> createConversation(
@Valid @RequestBody CreateConversationRequest request) {
public Result<com.emotionmuseum.ai.dto.CreateConversationResponse> createConversation(
@Valid @RequestBody com.emotionmuseum.ai.dto.CreateConversationRequest request) {
log.info("收到创建会话请求: userId={}, title={}", request.getUserId(), request.getTitle());
CreateConversationResponse response = aiChatService.createConversation(request);
com.emotionmuseum.ai.dto.CreateConversationResponse response = aiChatService.createConversation(request);
return Result.success(response);
}
@Operation(summary = "发送聊天消息")
@PostMapping("/send")
public Result<AiChatResponse> sendMessage(@Valid @RequestBody AiChatRequest request) {
public Result<com.emotionmuseum.ai.dto.ChatResponse> sendMessage(
@Valid @RequestBody com.emotionmuseum.ai.dto.ChatRequest request) {
log.info("收到聊天请求: userId={}, message={}", request.getUserId(), request.getMessage());
AiChatResponse response = aiChatService.chat(request);
com.emotionmuseum.ai.dto.ChatResponse response = aiChatService.chat(request);
return Result.success(response);
}
@Operation(summary = "情绪分析")
@PostMapping("/emotion/analyze")
public Result<EmotionAnalysisResponse> analyzeEmotion(@Valid @RequestBody EmotionAnalysisRequest request) {
public Result<com.emotionmuseum.ai.dto.EmotionAnalysisResponse> analyzeEmotion(
@Valid @RequestBody com.emotionmuseum.ai.dto.EmotionAnalysisRequest request) {
log.info("收到情绪分析请求: userId={}, text={}", request.getUserId(), request.getText());
EmotionAnalysisResponse response = aiChatService.analyzeEmotion(request);
com.emotionmuseum.ai.dto.EmotionAnalysisResponse response = aiChatService.analyzeEmotion(request);
return Result.success(response);
}
@Operation(summary = "流式聊天")
@PostMapping("/stream")
public Result<String> streamChat(@Valid @RequestBody AiChatRequest request) {
public Result<String> streamChat(@Valid @RequestBody com.emotionmuseum.ai.dto.ChatRequest request) {
log.info("收到流式聊天请求: userId={}", request.getUserId());
String response = aiChatService.streamChat(request);
return Result.success(response);
@@ -181,10 +189,11 @@ public class AiChatController {
"这是第三段回复,介绍了情感分析功能。我可以分析你的情绪状态并提供建议。";
// 创建或获取会话
CreateConversationRequest convRequest = new CreateConversationRequest();
com.emotionmuseum.ai.dto.CreateConversationRequest convRequest = new com.emotionmuseum.ai.dto.CreateConversationRequest();
convRequest.setUserId(request.getUserId());
convRequest.setTitle("测试拆分消息");
CreateConversationResponse conversation = aiChatService.createConversation(convRequest);
com.emotionmuseum.ai.dto.CreateConversationResponse conversation = aiChatService
.createConversation(convRequest);
// 保存用户消息
Message userMessage = new Message();
@@ -2,6 +2,8 @@ package com.emotionmuseum.ai.controller;
import com.emotionmuseum.ai.request.*;
import com.emotionmuseum.ai.response.*;
import com.emotionmuseum.ai.dto.MessageListResponse;
import com.emotionmuseum.ai.dto.GuestUserInfo;
import com.emotionmuseum.ai.service.GuestChatService;
import com.emotionmuseum.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
@@ -33,7 +35,8 @@ public class GuestChatController {
@PostMapping("/chat")
@Operation(summary = "访客聊天", description = "访客模式下发送消息并获取AI回复")
public Result<GuestChatResponse> guestChat(@RequestBody GuestChatRequest request) {
public Result<com.emotionmuseum.ai.dto.GuestChatResponse> guestChat(
@RequestBody com.emotionmuseum.ai.dto.GuestChatRequest request) {
// 自动获取客户端IP和User-Agent
String clientIp = getClientIp();
@@ -56,7 +59,7 @@ public class GuestChatController {
String clientIp = getClientIp();
log.info("获取访客会话列表: IP={}", clientIp);
return guestChatService.getGuestConversations(clientIp, pageNum, pageSize);
return (Result) guestChatService.getGuestConversations(clientIp, pageNum, pageSize);
}
@GetMapping("/conversation/{conversationId}/messages")
@@ -96,8 +99,8 @@ public class GuestChatController {
@PostMapping("/emotion/analyze")
@Operation(summary = "访客情绪分析", description = "分析访客输入文本的情绪")
public Result<EmotionAnalysisResponse> analyzeGuestEmotion(
@RequestBody EmotionAnalysisRequest request) {
public Result<com.emotionmuseum.ai.dto.EmotionAnalysisResponse> analyzeGuestEmotion(
@RequestBody com.emotionmuseum.ai.dto.EmotionAnalysisRequest request) {
String clientIp = getClientIp();
log.info("访客情绪分析: IP={}, Text={}", clientIp, request.getText());
@@ -113,7 +116,8 @@ public class GuestChatController {
@PostMapping("/test/split")
@Operation(summary = "测试消息拆分功能", description = "测试AI回复消息的拆分功能")
public Result<GuestChatResponse> testMessageSplit(@RequestBody GuestChatRequest request) {
public Result<com.emotionmuseum.ai.dto.GuestChatResponse> testMessageSplit(
@RequestBody com.emotionmuseum.ai.dto.GuestChatRequest request) {
log.info("测试消息拆分功能: message={}", request.getMessage());
// 模拟包含不同换行符的AI回复进行测试
@@ -132,7 +136,7 @@ public class GuestChatController {
}
// 创建模拟的访客聊天响应
GuestChatResponse response = new GuestChatResponse();
com.emotionmuseum.ai.dto.GuestChatResponse response = new com.emotionmuseum.ai.dto.GuestChatResponse();
response.setGuestUserId("test_guest_user");
response.setGuestNickname("测试用户");
response.setConversationId("test_conversation_" + System.currentTimeMillis());