Browse Source

1. 添加注释
2. 将 vo 的类改为 record
3. 添加回调函数, 使 ai 有查询数据的能力
4. 规范代码
5. 更改embed为shaw/dmeta-embedding-zh
更改模型为sam4096/qwen2tools:1.5b(支持函数回调)

zhenghao 4 tháng trước cách đây
mục cha
commit
1c8e105609
79 tập tin đã thay đổi với 1271 bổ sung383 xóa
  1. 0 21
      LICENSE
  2. 2 2
      pom.xml
  3. 4 16
      sql/pg.sql
  4. 6 6
      src/main/java/cn/jlsxwkj/common/R/Response.java
  5. 13 3
      src/main/java/cn/jlsxwkj/common/R/ResponseError.java
  6. 13 4
      src/main/java/cn/jlsxwkj/common/R/ResponseSucceed.java
  7. 4 0
      src/main/java/cn/jlsxwkj/common/R/package-info.java
  8. 48 0
      src/main/java/cn/jlsxwkj/common/config/FunctionCallConfig.java
  9. 7 0
      src/main/java/cn/jlsxwkj/common/config/RateLimiterConfig.java
  10. 4 3
      src/main/java/cn/jlsxwkj/common/config/SaTokenConfig.java
  11. 8 8
      src/main/java/cn/jlsxwkj/common/config/UserConfig.java
  12. 4 0
      src/main/java/cn/jlsxwkj/common/config/package-info.java
  13. 12 0
      src/main/java/cn/jlsxwkj/common/dao/Dao.java
  14. 4 0
      src/main/java/cn/jlsxwkj/common/dao/package-info.java
  15. 8 1
      src/main/java/cn/jlsxwkj/common/exception/AccountAuthFailException.java
  16. 8 1
      src/main/java/cn/jlsxwkj/common/exception/AccountPasswordCheckFailException.java
  17. 4 1
      src/main/java/cn/jlsxwkj/common/exception/CustomException.java
  18. 8 1
      src/main/java/cn/jlsxwkj/common/exception/FileDeleteFailException.java
  19. 8 1
      src/main/java/cn/jlsxwkj/common/exception/FileTypeDoesNotSupportException.java
  20. 8 2
      src/main/java/cn/jlsxwkj/common/exception/InsertFailException.java
  21. 8 1
      src/main/java/cn/jlsxwkj/common/exception/LoginAccountAlreadyLoginException.java
  22. 8 1
      src/main/java/cn/jlsxwkj/common/exception/LoginWrongPasswordException.java
  23. 8 1
      src/main/java/cn/jlsxwkj/common/exception/NotContentInFileException.java
  24. 4 1
      src/main/java/cn/jlsxwkj/common/exception/OpenFileFailException.java
  25. 5 1
      src/main/java/cn/jlsxwkj/common/exception/TooManyRequestsException.java
  26. 8 1
      src/main/java/cn/jlsxwkj/common/exception/UnknownException.java
  27. 4 0
      src/main/java/cn/jlsxwkj/common/exception/package-info.java
  28. 19 5
      src/main/java/cn/jlsxwkj/common/filter/ExecTimeFilter.java
  29. 17 4
      src/main/java/cn/jlsxwkj/common/filter/RateLimiterFilter.java
  30. 4 0
      src/main/java/cn/jlsxwkj/common/filter/package-info.java
  31. 19 10
      src/main/java/cn/jlsxwkj/common/handler/GlobalRestExceptionHandler.java
  32. 30 11
      src/main/java/cn/jlsxwkj/common/handler/ResultResponseHandler.java
  33. 4 0
      src/main/java/cn/jlsxwkj/common/handler/package-info.java
  34. 52 11
      src/main/java/cn/jlsxwkj/common/reader/ParagraphDocReader.java
  35. 43 13
      src/main/java/cn/jlsxwkj/common/reader/ParagraphOcrReader.java
  36. 31 9
      src/main/java/cn/jlsxwkj/common/reader/ParagraphTextReader.java
  37. 4 0
      src/main/java/cn/jlsxwkj/common/reader/package-info.java
  38. 20 9
      src/main/java/cn/jlsxwkj/common/utils/CheckPassword.java
  39. 28 9
      src/main/java/cn/jlsxwkj/common/utils/FileType.java
  40. 46 7
      src/main/java/cn/jlsxwkj/common/utils/Log.java
  41. 32 16
      src/main/java/cn/jlsxwkj/common/utils/MergeDocuments.java
  42. 37 13
      src/main/java/cn/jlsxwkj/common/utils/SplitDocument.java
  43. 4 0
      src/main/java/cn/jlsxwkj/common/utils/package-info.java
  44. 43 13
      src/main/java/cn/jlsxwkj/moudles/chat/ChatController.java
  45. 14 2
      src/main/java/cn/jlsxwkj/moudles/chat/ChatRequest.java
  46. 12 0
      src/main/java/cn/jlsxwkj/moudles/chat/ChatResponse.java
  47. 175 42
      src/main/java/cn/jlsxwkj/moudles/chat/ChatService.java
  48. 29 9
      src/main/java/cn/jlsxwkj/moudles/chat/ChatUtil.java
  49. 6 1
      src/main/java/cn/jlsxwkj/moudles/chat/message/AssistantMessage.java
  50. 7 0
      src/main/java/cn/jlsxwkj/moudles/chat/message/Message.java
  51. 5 1
      src/main/java/cn/jlsxwkj/moudles/chat/message/SystemMessage.java
  52. 5 1
      src/main/java/cn/jlsxwkj/moudles/chat/message/UserMessage.java
  53. 11 0
      src/main/java/cn/jlsxwkj/moudles/chat/message/UserRole.java
  54. 4 0
      src/main/java/cn/jlsxwkj/moudles/chat/message/package-info.java
  55. 4 0
      src/main/java/cn/jlsxwkj/moudles/chat/package-info.java
  56. 10 1
      src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistory.java
  57. 8 3
      src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryController.java
  58. 14 2
      src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryMapper.java
  59. 16 9
      src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryService.java
  60. 12 0
      src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryVO.java
  61. 4 0
      src/main/java/cn/jlsxwkj/moudles/chat_history/package-info.java
  62. 0 13
      src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistoryVO.java
  63. 20 2
      src/main/java/cn/jlsxwkj/moudles/log_error/LogError.java
  64. 32 0
      src/main/java/cn/jlsxwkj/moudles/log_error/LogErrorMapper.java
  65. 9 2
      src/main/java/cn/jlsxwkj/moudles/log_error/LogErrorService.java
  66. 4 0
      src/main/java/cn/jlsxwkj/moudles/log_error/package-info.java
  67. 0 23
      src/main/java/cn/jlsxwkj/moudles/logerror/LogErrorMapper.java
  68. 10 1
      src/main/java/cn/jlsxwkj/moudles/user_list/UserList.java
  69. 20 6
      src/main/java/cn/jlsxwkj/moudles/user_list/UserListController.java
  70. 46 0
      src/main/java/cn/jlsxwkj/moudles/user_list/UserListMapper.java
  71. 31 12
      src/main/java/cn/jlsxwkj/moudles/user_list/UserListService.java
  72. 12 0
      src/main/java/cn/jlsxwkj/moudles/user_list/UserVO.java
  73. 4 0
      src/main/java/cn/jlsxwkj/moudles/user_list/package-info.java
  74. 0 28
      src/main/java/cn/jlsxwkj/moudles/userlist/UserListMapper.java
  75. 0 13
      src/main/java/cn/jlsxwkj/moudles/userlist/UserVO.java
  76. 12 0
      src/main/java/cn/jlsxwkj/moudles/weather_demo/Request.java
  77. 65 0
      src/main/java/cn/jlsxwkj/moudles/weather_demo/WeatherService.java
  78. 4 0
      src/main/java/cn/jlsxwkj/moudles/weather_demo/package-info.java
  79. 15 6
      src/main/resources/application-dev.yml

+ 0 - 21
LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2024 jianyuan1991
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 2 - 2
pom.xml

@@ -4,7 +4,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.3.2</version>
+        <version>3.3.3</version>
         <relativePath/>
     </parent>
     <groupId>cn.jlsxwkj</groupId>
@@ -13,7 +13,7 @@
     <description>rag chat for Spring Boot</description>
     <properties>
         <java.version>17</java.version>
-        <spring-ai.version>1.0.0-M1</spring-ai.version>
+        <spring-ai.version>1.0.0-M2</spring-ai.version>
     </properties>
     <dependencies>
         <!--spring web-->

+ 4 - 16
sql/pg.sql

@@ -1,18 +1,15 @@
 CREATE EXTENSION IF NOT EXISTS vector;
 CREATE EXTENSION IF NOT EXISTS hstore;
 CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-
 CREATE TABLE IF NOT EXISTS vector_store (
     id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
     content text,
     metadata json,
     embedding vector(768)
-    );
+);
 CREATE INDEX IF NOT EXISTS spring_ai_vector_index ON vector_store USING hnsw (embedding vector_cosine_ops);
 
-DROP TABLE IF EXISTS log_error;
-
-CREATE TABLE log_error (
+CREATE TABLE IF NOT EXISTS log_error (
     id bigserial PRIMARY KEY, -- 主键
     "exception" text NULL, -- 异常
     message text NULL, -- 异常消息
@@ -20,7 +17,6 @@ CREATE TABLE log_error (
     error_stack_trace text NULL, -- 异常堆栈
     create_time timestamp(0) DEFAULT now() NULL -- 创建时间
 );
-
 COMMENT ON COLUMN log_error.id IS '主键';
 COMMENT ON COLUMN log_error."exception" IS '异常';
 COMMENT ON COLUMN log_error.message IS '异常消息';
@@ -28,9 +24,7 @@ COMMENT ON COLUMN log_error.error_info IS '异常详细消息';
 COMMENT ON COLUMN log_error.error_stack_trace IS '异常堆栈';
 COMMENT ON COLUMN log_error.create_time IS '创建时间';
 
-
-DROP TABLE IF EXISTS chat_history;
-CREATE TABLE chat_history (
+CREATE TABLE IF NOT EXISTS chat_history (
     id bigserial PRIMARY KEY, -- 主键
     user_id text NULL, -- 用户id
     "user_Q" text NULL, -- 用户提问
@@ -39,7 +33,6 @@ CREATE TABLE chat_history (
     update_time timestamp(0) DEFAULT now() NULL, -- 更改时间
     is_deleted int2 DEFAULT 0 NULL -- 是否删除
 );
-
 COMMENT ON COLUMN chat_history.id IS '主键';
 COMMENT ON COLUMN chat_history.user_id IS '用户id';
 COMMENT ON COLUMN chat_history."user_Q" IS '用户提问';
@@ -48,9 +41,7 @@ COMMENT ON COLUMN chat_history.create_time IS '创建时间';
 COMMENT ON COLUMN chat_history.update_time IS '更改时间';
 COMMENT ON COLUMN chat_history.is_deleted IS '是否删除';
 
-
-DROP TABLE IF EXISTS user_list;
-CREATE TABLE user_list (
+CREATE TABLE IF NOT EXISTS user_list (
     id bigserial primary key, -- 主键
     user_id text not null, -- 用户id
     user_name text, -- 用户名
@@ -61,9 +52,6 @@ CREATE TABLE user_list (
     UNIQUE (user_name, is_deleted)
 );
 COMMENT ON TABLE user_list IS '用户列表';
-
--- Column comments
-
 COMMENT ON COLUMN user_list.id IS '主键';
 COMMENT ON COLUMN user_list.user_id IS '用户id';
 COMMENT ON COLUMN user_list.user_name IS '用户名';

+ 6 - 6
src/main/java/cn/jlsxwkj/common/R/Response.java

@@ -8,15 +8,15 @@ import lombok.Data;
 @Data
 public abstract class Response {
     /**
-     * 标识返回状态
+     * 标识返回状态.
      */
-    Integer code;
+    private Integer code;
     /**
-     * 标识返回内容
+     * 标识返回内容.
      */
-    Object data;
+    private Object data;
     /**
-     * 标识返回消息
+     * 标识返回消息.
      */
-    String message;
+    private String message;
 }

+ 13 - 3
src/main/java/cn/jlsxwkj/common/R/ResponseError.java

@@ -12,13 +12,23 @@ import lombok.EqualsAndHashCode;
 public class ResponseError extends Response {
 
     /**
-     * 标识返回异常
+     * 异常状态.
+     */
+    private static final int ERROR_CODE = 500;
+
+    /**
+     * 标识返回异常.
      */
     private String exception;
 
-    public static ResponseError data(String exception) {
+    /**
+     * response error.
+     * @param exception 异常名称
+     * @return 封装后的异常对象
+     */
+    public static ResponseError data(final String exception) {
         ResponseError r = new ResponseError();
-        r.setCode(500);
+        r.setCode(ERROR_CODE);
         r.setMessage("服务器异常");
         r.setException(exception);
         return r;

+ 13 - 4
src/main/java/cn/jlsxwkj/common/R/ResponseSucceed.java

@@ -5,18 +5,27 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 /**
- * @Author zh
+ * @author zh
  */
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class ResponseSucceed extends Response {
 
-    public static ResponseSucceed data(Object data){
+    /**
+     * 成功状态.
+     */
+    private static final int SUCCESS_CODE = 200;
+
+    /**
+     * response success.
+     * @param data 数据
+     * @return 返回响应成功对象
+     */
+    public static ResponseSucceed data(final Object data) {
         ResponseSucceed r = new ResponseSucceed();
-        r.setCode(200);
+        r.setCode(SUCCESS_CODE);
         r.setMessage("完成");
         r.setData(data);
         return r;
     }
 }
-

+ 4 - 0
src/main/java/cn/jlsxwkj/common/R/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 数据封装包.
+ */
+package cn.jlsxwkj.common.R;

+ 48 - 0
src/main/java/cn/jlsxwkj/common/config/FunctionCallConfig.java

@@ -0,0 +1,48 @@
+package cn.jlsxwkj.common.config;
+
+import cn.jlsxwkj.common.utils.Log;
+import cn.jlsxwkj.moudles.weather_demo.WeatherService;
+import jakarta.annotation.Resource;
+import org.springframework.ai.model.function.FunctionCallback;
+import org.springframework.ai.model.function.FunctionCallbackWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * @author zh
+ */
+@Configuration
+public class FunctionCallConfig {
+
+    /**
+     * 天气对象.
+     */
+    @Resource
+    private WeatherService weatherService;
+
+    /**
+     * 获取天气.
+     * @return 返回回调函数
+     */
+    @Bean
+    public FunctionCallback getWeather() {
+        try {
+            InetAddress byName = InetAddress.getByName("www.baidu.com");
+            int timeOut = 1000;
+            if (byName.isReachable(timeOut)) {
+                Log.info(this.getClass(), "互联网畅通");
+                return FunctionCallbackWrapper.builder(weatherService)
+                        .withName("getWeather")
+                        .withDescription("获取提供位置天气信息")
+                        .build();
+            }
+            Log.info(this.getClass(), "未连接互联网");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

+ 7 - 0
src/main/java/cn/jlsxwkj/common/config/RateLimiterConfig.java

@@ -16,9 +16,16 @@ import java.time.Duration;
 @Configuration
 public class RateLimiterConfig {
 
+    /**
+     * 用户配置类.
+     */
     @Resource
     private UserConfig userConfig;
 
+    /**
+     * 桶.
+     * @return 返回桶
+     */
     @Bean
     public Bucket bucket() {
         Bandwidth limit = Bandwidth.classic(

+ 4 - 3
src/main/java/cn/jlsxwkj/common/config/SaTokenConfig.java

@@ -13,13 +13,14 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 public class SaTokenConfig implements WebMvcConfigurer {
 
     /**
-     * 注册拦截器
+     * 注册拦截器.
      *
      * @param registry 注册
      */
     @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        registry.addInterceptor(new SaInterceptor(handler -> StpUtil.checkLogin()))
+    public void addInterceptors(final InterceptorRegistry registry) {
+        registry.addInterceptor(
+                new SaInterceptor(handler -> StpUtil.checkLogin()))
                 .addPathPatterns("/**");
     }
 }

+ 8 - 8
src/main/java/cn/jlsxwkj/common/config/UserConfig.java

@@ -13,35 +13,35 @@ import org.springframework.stereotype.Component;
 public class UserConfig {
 
     /**
-     * 用户自定义属性前缀
+     * 用户自定义属性前缀.
      */
     public static final String USER_PREFIX = "customer";
     /**
-     * ocr 地址
+     * ocr 地址.
      */
     private String cnocrUrl = "http://localhost:8501/ocr";
     /**
-     * 指定的 chat 系统消息
+     * 指定的 chat 系统消息.
      */
     private String sysMessage = "Always say you're an ai or 大模型";
     /**
-     * 消息列表最大长度
+     * 消息列表最大长度.
      */
     private Integer maxListMessageLength = 10;
     /**
-     * 机器人每条消息最大长度, 超过会截取
+     * 机器人每条消息最大长度, 超过会截取.
      */
     private Integer maxMessageLength = 512;
     /**
-     * 打印 api 大于指定执行时间
+     * 打印 api 大于指定执行时间.
      */
     private Integer execTime = 100;
     /**
-     * 重复请求限流时长(单位:秒)
+     * 重复请求限流时长(单位:秒).
      */
     private Integer rateLimitSec = 1;
     /**
-     * 限流时长中可请求的次数
+     * 限流时长中可请求的次数.
      */
     private Integer genTokens = 1;
 

+ 4 - 0
src/main/java/cn/jlsxwkj/common/config/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 配置包.
+ */
+package cn.jlsxwkj.common.config;

+ 12 - 0
src/main/java/cn/jlsxwkj/common/dao/Dao.java

@@ -7,8 +7,20 @@ import lombok.Data;
  */
 @Data
 public class Dao {
+    /**
+     * 编号.
+     */
     private Long id;
+    /**
+     * 创建时间.
+     */
     private java.sql.Timestamp createTime;
+    /**
+     * 更新时间.
+     */
     private java.sql.Timestamp updateTime;
+    /**
+     * 是否删除.
+     */
     private Integer isDeleted;
 }

+ 4 - 0
src/main/java/cn/jlsxwkj/common/dao/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 实体包.
+ */
+package cn.jlsxwkj.common.dao;

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/AccountAuthFailException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 用户注册失败异常
  */
 public class AccountAuthFailException extends CustomException {
 
+    /**
+     * AccountAuthFailException.
+     */
     @SuppressWarnings("unused")
     public AccountAuthFailException() {
         super("注册失败");
     }
 
-    public AccountAuthFailException(String message) {
+    /**
+     * @param message 消息
+     */
+    public AccountAuthFailException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/AccountPasswordCheckFailException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 用户密码检查未通过
  */
 public class AccountPasswordCheckFailException extends CustomException {
 
+    /**
+     * AccountPasswordCheckFailException.
+     */
     @SuppressWarnings("unused")
     public AccountPasswordCheckFailException() {
         super("用户密码检查未通过");
     }
 
-    public AccountPasswordCheckFailException(String message) {
+    /**
+     * @param message 消息
+     */
+    public AccountPasswordCheckFailException(final String message) {
         super(message);
     }
 }

+ 4 - 1
src/main/java/cn/jlsxwkj/common/exception/CustomException.java

@@ -6,7 +6,10 @@ package cn.jlsxwkj.common.exception;
  */
 public abstract class CustomException extends Exception {
 
-    public CustomException(String message) {
+    /**
+     * @param message 消息
+     */
+    public CustomException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/FileDeleteFailException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 文件删除失败
  */
 @SuppressWarnings("unused")
 public class FileDeleteFailException extends CustomException {
 
+    /**
+     * FileDeleteFailException.
+     */
     public FileDeleteFailException() {
         super("文件删除失败");
     }
 
-    public FileDeleteFailException(String message) {
+    /**
+     * @param message 消息
+     */
+    public FileDeleteFailException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/FileTypeDoesNotSupportException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 文件类型不支持
  */
 public class FileTypeDoesNotSupportException extends CustomException {
 
+    /**
+     * FileTypeDoesNotSupportException.
+     */
     @SuppressWarnings("unused")
     public FileTypeDoesNotSupportException() {
         super("文件类型不支持");
     }
 
-    public FileTypeDoesNotSupportException(String message) {
+    /**
+     * @param message 消息
+     */
+    public FileTypeDoesNotSupportException(final String message) {
         super(message);
     }
 }

+ 8 - 2
src/main/java/cn/jlsxwkj/common/exception/InsertFailException.java

@@ -2,15 +2,21 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 插入失败
  */
 public class InsertFailException extends CustomException {
-
+    /**
+     * InsertFailException.
+     */
     @SuppressWarnings("unused")
     public InsertFailException() {
         super("插入失败");
     }
 
-    public InsertFailException(String message) {
+    /**
+     * @param message 消息
+     */
+    public InsertFailException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/LoginAccountAlreadyLoginException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 重复登录
  */
 public class LoginAccountAlreadyLoginException extends CustomException {
 
+    /**
+     * LoginAccountAlreadyLoginException.
+     */
     @SuppressWarnings("unused")
     public LoginAccountAlreadyLoginException() {
         super("重复登录");
     }
 
-    public LoginAccountAlreadyLoginException(String message) {
+    /**
+     * @param message 消息
+     */
+    public LoginAccountAlreadyLoginException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/LoginWrongPasswordException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 登录密码错误
  */
 public class LoginWrongPasswordException extends CustomException {
 
+    /**
+     * LoginWrongPasswordException.
+     */
     @SuppressWarnings("unused")
     public LoginWrongPasswordException() {
         super("登录密码错误");
     }
 
-    public LoginWrongPasswordException(String message) {
+    /**
+     * @param message 消息
+     */
+    public LoginWrongPasswordException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/NotContentInFileException.java

@@ -2,15 +2,22 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 文件中没有内容
  */
 @SuppressWarnings("unused")
 public class NotContentInFileException extends CustomException {
 
+    /**
+     * NotContentInFileException.
+     */
     public NotContentInFileException() {
         super("文件中没有内容");
     }
 
-    public NotContentInFileException(String message) {
+    /**
+     * @param message 消息
+     */
+    public NotContentInFileException(final String message) {
         super(message);
     }
 }

+ 4 - 1
src/main/java/cn/jlsxwkj/common/exception/OpenFileFailException.java

@@ -4,7 +4,10 @@ package cn.jlsxwkj.common.exception;
  * @author zh
  */
 public class OpenFileFailException extends CustomException {
-    public OpenFileFailException(String message) {
+    /**
+     * @param message 消息
+     */
+    public OpenFileFailException(final String message) {
         super(message);
     }
 }

+ 5 - 1
src/main/java/cn/jlsxwkj/common/exception/TooManyRequestsException.java

@@ -2,10 +2,14 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 太多请求
  */
 public class TooManyRequestsException extends CustomException {
 
-    public TooManyRequestsException(String message) {
+    /**
+     * @param message 消息
+     */
+    public TooManyRequestsException(final String message) {
         super(message);
     }
 }

+ 8 - 1
src/main/java/cn/jlsxwkj/common/exception/UnknownException.java

@@ -2,14 +2,21 @@ package cn.jlsxwkj.common.exception;
 
 /**
  * @author zh
+ * 未知错误
  */
 public class UnknownException extends CustomException {
 
+    /**
+     * UnknownException.
+     */
     public UnknownException() {
         this("未知错误");
     }
 
-    public UnknownException(String message) {
+    /**
+     * @param message 消息
+     */
+    public UnknownException(final String message) {
         super(message);
     }
 }

+ 4 - 0
src/main/java/cn/jlsxwkj/common/exception/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 异常包.
+ */
+package cn.jlsxwkj.common.exception;

+ 19 - 5
src/main/java/cn/jlsxwkj/common/filter/ExecTimeFilter.java

@@ -15,19 +15,33 @@ import java.io.IOException;
 @Component
 public class ExecTimeFilter implements Filter {
 
+    /**
+     * 用户配置.
+     */
     @Resource
     private UserConfig userConfig;
 
+    /**
+     * @param servletRequest  ServletRequest
+     * @param servletResponse ServletResponse
+     * @param filterChain     FilterChain
+     * @throws IOException      IOException
+     * @throws ServletException ServletException
+     */
     @Override
-    public void doFilter(ServletRequest servletRequest,
-                         ServletResponse servletResponse,
-                         FilterChain filterChain) throws IOException, ServletException {
+    public void doFilter(
+            final ServletRequest servletRequest,
+            final ServletResponse servletResponse,
+            final FilterChain filterChain)
+            throws IOException, ServletException {
         long startTime = System.currentTimeMillis();
-        String url = ((HttpServletRequest) servletRequest).getRequestURL().toString();
+        String url = ((HttpServletRequest) servletRequest)
+                .getRequestURL().toString();
         filterChain.doFilter(servletRequest, servletResponse);
         long execTime = System.currentTimeMillis() - startTime;
         if (execTime > userConfig.getExecTime()) {
-            Log.warn(this.getClass(), "api: {}, exec_time ====> {}ms", url, execTime);
+            Log.warn(this.getClass(),
+                    "api: {}, exec_time ====> {}ms", url, execTime);
         }
     }
 

+ 17 - 4
src/main/java/cn/jlsxwkj/common/filter/RateLimiterFilter.java

@@ -18,17 +18,30 @@ import java.io.IOException;
 @Component
 public class RateLimiterFilter implements Filter {
 
+    /**
+     * 限流令牌桶.
+     */
     @Resource
     private Bucket bucket;
 
+    /**
+     * @param request ServletRequest
+     * @param response ServletResponse
+     * @param chain FilterChain
+     * @throws IOException IOException
+     * @throws ServletException ServletException
+     */
     @Override
-    public void doFilter(ServletRequest request,
-                         ServletResponse response,
-                         FilterChain chain) throws IOException, ServletException {
+    public void doFilter(
+            final ServletRequest request,
+            final ServletResponse response,
+            final FilterChain chain)
+            throws IOException, ServletException {
         if (bucket.tryConsume(1)) {
             chain.doFilter(request, response);
         } else {
-            ResponseError data = ResponseError.data(TooManyRequestsException.class.getName());
+            ResponseError data = ResponseError.data(
+                    TooManyRequestsException.class.getName());
             data.setMessage("请求次数过多, 请稍后再试");
             data.setCode(HttpStatus.TEMPORARY_REDIRECT.value());
 

+ 4 - 0
src/main/java/cn/jlsxwkj/common/filter/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * filter.
+ */
+package cn.jlsxwkj.common.filter;

+ 19 - 10
src/main/java/cn/jlsxwkj/common/handler/GlobalRestExceptionHandler.java

@@ -5,8 +5,8 @@ import cn.jlsxwkj.common.R.ResponseError;
 import cn.jlsxwkj.common.exception.CustomException;
 import cn.jlsxwkj.common.exception.InsertFailException;
 import cn.jlsxwkj.common.utils.Log;
-import cn.jlsxwkj.moudles.logerror.LogError;
-import cn.jlsxwkj.moudles.logerror.LogErrorService;
+import cn.jlsxwkj.moudles.log_error.LogError;
+import cn.jlsxwkj.moudles.log_error.LogErrorService;
 import jakarta.annotation.Resource;
 import org.springframework.web.ErrorResponse;
 import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -20,19 +20,23 @@ import java.util.Arrays;
 @RestControllerAdvice
 public class GlobalRestExceptionHandler {
 
+    /**
+     * log error 对象.
+     */
     @Resource
     private LogErrorService logErrorService;
 
     /**
-     * 捕捉全局异常
+     * 捕捉全局异常.
      *
      * @param e 异常
      * @return 封装异常对象
      */
     @ExceptionHandler(Throwable.class)
-    public ResponseError exception(Throwable e) {
+    public ResponseError exception(final Throwable e) {
 
-        ResponseError responseError = ResponseError.data(e.getClass().getName());
+        ResponseError responseError =
+                ResponseError.data(e.getClass().getName());
 
         if (e instanceof CustomException) {
             responseError.setMessage(e.getMessage());
@@ -46,18 +50,23 @@ public class GlobalRestExceptionHandler {
             responseError.setMessage("账户未登录");
         }
 
-        LogError errorHandlerToLogError = new LogError().castResponseErrorToLogError(responseError);
+        LogError errorHandlerToLogError =
+                new LogError().castResponseErrorToLogError(responseError);
         errorHandlerToLogError.setErrorInfo(e.getMessage());
-        errorHandlerToLogError.setErrorStackTrace(Arrays.toString(e.getStackTrace()));
+        errorHandlerToLogError.setErrorStackTrace(
+                Arrays.toString(e.getStackTrace()));
         try {
             logErrorService.insertOne(errorHandlerToLogError);
         } catch (InsertFailException insertFailException) {
             Log.warn(this.getClass(), insertFailException.getMessage());
         }
 
-        Log.error(e.getClass(), "Code       ====> {}", responseError.getCode());
-        Log.error(e.getClass(), "Exception  ====> {}", responseError.getException());
-        Log.error(e.getClass(), "Message    ====> {}", responseError.getMessage());
+        Log.error(e.getClass(),
+                "Code       ====> {}", responseError.getCode());
+        Log.error(e.getClass(),
+                "Exception  ====> {}", responseError.getException());
+        Log.error(e.getClass(),
+                "Message    ====> {}", responseError.getMessage());
 
         Log.info(this.getClass(), Arrays.toString(e.getStackTrace()));
 

+ 30 - 11
src/main/java/cn/jlsxwkj/common/handler/ResultResponseHandler.java

@@ -17,29 +17,48 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 import java.util.Arrays;
 
 /**
- * @Author Joker DJ
+ * @author Joker DJ
  * ControllerAdvice 绑定的Controller包的权限定名 例如:com.dj.Controller
  */
 @ControllerAdvice(basePackages = "cn.jlsxwkj.moudles")
 public class ResultResponseHandler implements ResponseBodyAdvice<Object> {
 
+    /**
+     * supports.
+     *
+     * @param methodParameter MethodParameter
+     * @param aClass          HttpMessageConverter
+     * @return boolean
+     */
     @Override
-    public boolean supports(@Nullable MethodParameter methodParameter,
-                            @Nullable Class<? extends HttpMessageConverter<?>> aClass) {
+    public boolean supports(
+            @Nullable final MethodParameter methodParameter,
+            @Nullable final Class<? extends HttpMessageConverter<?>> aClass) {
         return true;
     }
 
+    /**
+     * beforeBodyWrite.
+     *
+     * @param o                  Object
+     * @param methodParameter    MethodParameter
+     * @param mediaType          MediaType
+     * @param aClass             HttpMessageConverter
+     * @param serverHttpRequest  ServerHttpRequest
+     * @param serverHttpResponse ServerHttpResponse
+     * @return Object
+     */
     @Override
-    public Object beforeBodyWrite(Object o,
-                                  @Nullable MethodParameter methodParameter,
-                                  @Nullable MediaType mediaType,
-                                  @Nullable Class<? extends HttpMessageConverter<?>> aClass,
-                                  @Nullable ServerHttpRequest serverHttpRequest,
-                                  @Nullable ServerHttpResponse serverHttpResponse) {
+    public Object beforeBodyWrite(
+            @Nullable final Object o,
+            @Nullable final MethodParameter methodParameter,
+            @Nullable final MediaType mediaType,
+            @Nullable final Class<? extends HttpMessageConverter<?>> aClass,
+            @Nullable final ServerHttpRequest serverHttpRequest,
+            @Nullable final ServerHttpResponse serverHttpResponse) {
         // 对请求的结果在这里统一返回和处理
-        if (o instanceof ResponseError) {
+        if (o instanceof ResponseError errorHandler) {
             // 1、如果返回的结果是一个异常的结果,就把异常返回的结构数据倒腾到R.fail里面即可
-            ResponseError errorHandler = (ResponseError) o;
             return ResponseSucceed.data(errorHandler);
         }
         if (o instanceof String) {

+ 4 - 0
src/main/java/cn/jlsxwkj/common/handler/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 异常捕获包.
+ */
+package cn.jlsxwkj.common.handler;

+ 52 - 11
src/main/java/cn/jlsxwkj/common/reader/ParagraphDocReader.java

@@ -22,37 +22,78 @@ import java.util.List;
 @Data
 public class ParagraphDocReader implements DocumentReader {
 
+    /**
+     * parser.
+     */
     private final AutoDetectParser parser;
+    /**
+     * handler.
+     */
     private final ContentHandler handler;
+    /**
+     * metadata.
+     */
     private final Metadata metadata;
+    /**
+     * context.
+     */
     private final ParseContext context;
+    /**
+     * 文件流.
+     */
     private final InputStream inputStream;
+    /**
+     * 文件名.
+     */
     private final String fileName;
-    private int windowSize;
-    private ExtractedTextFormatter textFormatter;
+    /**
+     * 窗口大小.
+     */
+    private final int windowSize;
+    /**
+     * textFormatter.
+     */
+    private final ExtractedTextFormatter textFormatter;
 
-
-    public ParagraphDocReader(byte[] bytes,
-                              String fileName,
-                              int windowSize) {
+    /**
+     * doc reader.
+     *
+     * @param bytes 文件数据
+     * @param fn    文件名
+     * @param ws    窗口大小
+     */
+    public ParagraphDocReader(final byte[] bytes,
+                              final String fn,
+                              final int ws) {
         this.textFormatter = ExtractedTextFormatter.defaults();
         this.parser = new AutoDetectParser();
         this.handler = new BodyContentHandler(-1);
         this.metadata = new Metadata();
         this.context = new ParseContext();
         this.inputStream = new ByteArrayInputStream(bytes);
-        this.windowSize = windowSize;
-        this.fileName = fileName;
+        this.windowSize = ws;
+        this.fileName = fn;
     }
 
+    /**
+     * 获取文档.
+     *
+     * @return 返回文档列表
+     */
     @Override
     public List<Document> get() {
         try {
-            this.parser.parse(this.inputStream, this.handler, this.metadata, this.context);
+            this.parser.parse(
+                    this.inputStream,
+                    this.handler,
+                    this.metadata,
+                    this.context);
         } catch (Exception e) {
             e.printStackTrace();
         }
-        return SplitDocument.splitStringToListDocument(this.handler.toString(), this.windowSize, this.fileName);
+        return SplitDocument.splitStringToListDocument(
+                this.handler.toString(),
+                this.windowSize,
+                this.fileName);
     }
-
 }

+ 43 - 13
src/main/java/cn/jlsxwkj/common/reader/ParagraphOcrReader.java

@@ -17,23 +17,50 @@ import java.util.List;
  */
 @Data
 public class ParagraphOcrReader implements DocumentReader {
-
+    /**
+     * ocr 地址.
+     */
     private final String cnocrUrl;
+    /**
+     * 文件.
+     */
     private final byte[] bytes;
+    /**
+     * 文件编码.
+     */
     private final Charset charset = StandardCharsets.UTF_8;
+    /**
+     * 窗口大小.
+     */
     private final int windowSize;
+    /**
+     * 文件名.
+     */
     private final String fileName;
 
-    public ParagraphOcrReader(byte[] bytes,
-                              String fileName,
-                              String cnocrUrl,
-                              int windowSize) {
-        this.bytes = bytes;
-        this.windowSize = windowSize;
-        this.cnocrUrl = cnocrUrl;
-        this.fileName = fileName;
+    /**
+     * ocr reader.
+     *
+     * @param file   文件
+     * @param name  文件名
+     * @param url ocr 地址
+     * @param ws  窗口大小
+     */
+    public ParagraphOcrReader(final byte[] file,
+                              final String name,
+                              final String url,
+                              final int ws) {
+        this.bytes = file;
+        this.windowSize = ws;
+        this.cnocrUrl = url;
+        this.fileName = name;
     }
 
+    /**
+     * 获取文档.
+     *
+     * @return 返回文档列表
+     */
     @Override
     public List<Document> get() {
         String image = HttpRequest.post(cnocrUrl)
@@ -41,9 +68,12 @@ public class ParagraphOcrReader implements DocumentReader {
                 .execute()
                 .body();
         StringBuilder sb = new StringBuilder();
-        new JSONArray(new JSONObject(image).get("results"))
-                .forEach(x -> sb.append(new JSONObject(x).get("text")).append(" "));
+        new JSONArray(new JSONObject(image).get("results")).forEach(x ->
+                sb.append(new JSONObject(x).get("text")).append(" "));
         String document = sb.toString();
-        return SplitDocument.splitStringToListDocument(document, this.windowSize, this.fileName);
+        return SplitDocument.splitStringToListDocument(
+                document,
+                this.windowSize,
+                this.fileName);
     }
-}
+}

+ 31 - 9
src/main/java/cn/jlsxwkj/common/reader/ParagraphTextReader.java

@@ -21,21 +21,40 @@ import java.util.List;
 @Data
 public class ParagraphTextReader implements DocumentReader {
 
+    /**
+     * inputStream.
+     */
     private final InputStream inputStream;
+    /**
+     * 文件编码.
+     */
     private final Charset charset = StandardCharsets.UTF_8;
+    /**
+     * 窗口大小.
+     */
     private final int windowSize;
+    /**
+     * 文件名.
+     */
     private final String fileName;
 
-    public ParagraphTextReader(byte[] bytes,
-                               String fileName,
-                               int windowSize) {
-        this.inputStream = new ByteArrayInputStream(bytes);
-        this.windowSize = windowSize;
-        this.fileName = fileName;
+    /**
+     * text reader.
+     *
+     * @param file 文件
+     * @param name 文件名
+     * @param size 窗口大小
+     */
+    public ParagraphTextReader(final byte[] file,
+                               final String name,
+                               final int size) {
+        this.inputStream = new ByteArrayInputStream(file);
+        this.windowSize = size;
+        this.fileName = name;
     }
 
     /**
-     * 读取文本内容,并根据换行进行分段,采用窗口模式,窗口为段落的数量
+     * 读取文本内容,并根据换行进行分段,采用窗口模式,窗口为段落的数量.
      *
      * @return 文档信息列表
      */
@@ -48,6 +67,9 @@ public class ParagraphTextReader implements DocumentReader {
             e.printStackTrace();
         }
         assert document != null;
-        return SplitDocument.splitStringToListDocument(document, this.windowSize, this.fileName);
+        return SplitDocument.splitStringToListDocument(
+                document,
+                this.windowSize,
+                this.fileName);
     }
-}
+}

+ 4 - 0
src/main/java/cn/jlsxwkj/common/reader/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 文档切割包.
+ */
+package cn.jlsxwkj.common.reader;

+ 20 - 9
src/main/java/cn/jlsxwkj/common/utils/CheckPassword.java

@@ -6,30 +6,41 @@ import java.util.regex.Pattern;
 /**
  * @author LL
  */
-public class CheckPassword {
+public final class CheckPassword {
+    private CheckPassword() {
+    }
+
     /**
-     * 密码长度为8到20位,必须包含字母和数字,字母区分大小写
+     * 密码长度为8到20位,必须包含字母和数字,字母区分大小写.
      */
-    private static final String REG_EX1 = "^(?=.*[0-9])(?=.*[a-zA-Z])(.{8,20})$";
+    private static final String
+            REG_EX1 = "^(?=.*[0-9])(?=.*[a-zA-Z])(.{8,20})$";
     /**
-     * 密码中必须包含字母、数字、特称字符,至少8个字符,最多16个字符
+     * 密码中必须包含字母、数字、特称字符,至少8个字符,最多16个字符.
      */
-    private static final String REG_EX2 = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9])(.{8,16})$";
+    private static final String
+            REG_EX2 = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9])(.{8,16})$";
 
     /**
-     * 密码长度为8到20位,必须包含字母和数字,字母区分大小写
+     * 密码长度为8到20位,必须包含字母和数字,字母区分大小写.
+     *
+     * @param password 需要校验的密码
+     * @return 返回校验结果
      */
-    public static boolean checkPassword(String password) {
+    public static boolean checkPassword(final String password) {
         Pattern passwordPattern = Pattern.compile(REG_EX1);
         Matcher matcher = passwordPattern.matcher(password);
         return matcher.matches();
     }
 
     /**
-     * 密码中必须包含字母、数字、特称字符,至少8个字符,最多16个字符
+     * 密码中必须包含字母、数字、特称字符,至少8个字符,最多16个字符.
+     *
+     * @param password 需要校验的密码
+     * @return 返回校验结果
      */
     @SuppressWarnings("unused")
-    public static boolean password(String password) {
+    public static boolean password(final String password) {
         Pattern passwordPattern = Pattern.compile(REG_EX2);
         Matcher matcher = passwordPattern.matcher(password);
         return matcher.matches();

+ 28 - 9
src/main/java/cn/jlsxwkj/common/utils/FileType.java

@@ -12,19 +12,38 @@ import java.util.Map;
  * @author zh
  */
 public class FileType {
-
+    /**
+     * 缓存池.
+     */
     private static final Map<String, Tuple> TYPE = new HashMap<>();
 
-    public FileType(byte[] bytes,
-                    String fileName,
-                    int winSize,
-                    String cnocrUrl) {
-        TYPE.put("txt", new Tuple("文本", new ParagraphTextReader(bytes, fileName, winSize)));
-        TYPE.put("doc docx", new Tuple("文档", new ParagraphDocReader(bytes, fileName, winSize)));
-        TYPE.put("jpg png", new Tuple("图片", new ParagraphOcrReader(bytes, fileName, cnocrUrl, winSize)));
+    /**
+     * 创建校验对象.
+     *
+     * @param bytes    文件
+     * @param fileName 文件名
+     * @param winSize  窗口大小
+     * @param cnocrUrl ocr识别地址
+     */
+    public FileType(final byte[] bytes,
+                    final String fileName,
+                    final int winSize,
+                    final String cnocrUrl) {
+        TYPE.put("txt", new Tuple("文本",
+                new ParagraphTextReader(bytes, fileName, winSize)));
+        TYPE.put("doc docx", new Tuple("文档",
+                new ParagraphDocReader(bytes, fileName, winSize)));
+        TYPE.put("jpg png", new Tuple("图片",
+                new ParagraphOcrReader(bytes, fileName, cnocrUrl, winSize)));
     }
 
-    public Tuple getFileTypeAndResource(String fileType) {
+    /**
+     * 判断文件是否支持.
+     *
+     * @param fileType 文件类型
+     * @return 返回存在的对象
+     */
+    public Tuple getFileTypeAndResource(final String fileType) {
         for (String s : TYPE.keySet()) {
             if (s.contains(fileType)) {
                 return TYPE.get(s);

+ 46 - 7
src/main/java/cn/jlsxwkj/common/utils/Log.java

@@ -9,26 +9,65 @@ import java.util.concurrent.ConcurrentHashMap;
  * @author zh
  * 打印日志对象缓存池
  */
-public class Log {
+public final class Log {
+    private Log() {
+    }
 
-    private static final Map<String, Slf4jLog> CACHE_LOGS = new ConcurrentHashMap<>();
+    /**
+     * Log 对象池.
+     */
+    private static final Map<String, Slf4jLog>
+            CACHE_LOGS = new ConcurrentHashMap<>();
 
-    public static void info(Class<?> clazz, String format, Object... args) {
+    /**
+     * 打印 info 级别的日志.
+     *
+     * @param clazz  需要打印的对象类
+     * @param format 格式化或需要打印的字符串
+     * @param args   格式化字符串需要的参数
+     */
+    public static void info(final Class<?> clazz,
+                            final String format,
+                            final Object... args) {
         Slf4jLog log = getLogObj(clazz);
         log.info(format, args);
     }
 
-    public static void warn(Class<?> clazz, String format, Object... args) {
+    /**
+     * 打印 warn 级别的日志.
+     *
+     * @param clazz  需要打印的对象类
+     * @param format 格式化或需要打印的字符串
+     * @param args   格式化字符串需要的参数
+     */
+    public static void warn(final Class<?> clazz,
+                            final String format,
+                            final Object... args) {
         Slf4jLog log = getLogObj(clazz);
         log.warn(format, args);
     }
 
-    public static void error(Class<?> clazz, String format, Object... args) {
+    /**
+     * 打印 error 级别的日志.
+     *
+     * @param clazz  需要打印的对象类
+     * @param format 格式化或需要打印的字符串
+     * @param args   格式化字符串需要的参数
+     */
+    public static void error(final Class<?> clazz,
+                             final String format,
+                             final Object... args) {
         Slf4jLog log = getLogObj(clazz);
-        log.warn(format, args);
+        log.error(format, args);
     }
 
-    private static Slf4jLog getLogObj(Class<?> clazz) {
+    /**
+     * 获取或创建 log 对象.
+     *
+     * @param clazz 需要打印的对象类
+     * @return 返回 log 对象
+     */
+    private static Slf4jLog getLogObj(final Class<?> clazz) {
         if (!CACHE_LOGS.containsKey(clazz.getName())) {
             CACHE_LOGS.put(clazz.getName(), new Slf4jLog(clazz));
         }

+ 32 - 16
src/main/java/cn/jlsxwkj/common/utils/MergeDocuments.java

@@ -12,30 +12,36 @@ import java.util.stream.Collectors;
 /**
  * @author jay
  */
-public class MergeDocuments {
+public final class MergeDocuments {
+    private MergeDocuments() {
+    }
 
     /**
-     * 合并文档列表
+     * 合并文档列表.
      *
      * @param documentList 文档列表
      * @return 合并后的文档列表
      */
-    public static List<Document> mergeDocuments(List<Document> documentList) {
+    public static List<Document> mergeDocuments(
+            final List<Document> documentList) {
         ArrayList<Document> mergeDocuments = new ArrayList<>();
         //根据文档来源进行分组
-        for (var docListEntry : documentList.stream()
-                .collect(Collectors.groupingBy(
-                        document -> (String) document.getMetadata().get(SplitDocument.FILE_NAME)
+        for (var docListEntry : documentList.stream().collect(
+                Collectors.groupingBy(document -> (String)
+                        document.getMetadata()
+                                .get(SplitDocument.FILE_NAME)
                 )).entrySet()) {
             //获取最大的段落结束编码
-            Optional<Document> documents = docListEntry.getValue().stream()
-                    .max(Comparator.comparing(
-                            document -> (int) document.getMetadata().get(SplitDocument.END_PARAGRAPH_NUMBER)
+            Optional<Document> documents = docListEntry.getValue().stream().max(
+                    Comparator.comparing(document -> (int)
+                            document.getMetadata()
+                                    .get(SplitDocument.END_PARAGRAPH_NUMBER)
                     ));
             if (documents.isEmpty()) {
                 continue;
             }
-            int maxParagraphNum = (int) documents.get().getMetadata().get(SplitDocument.END_PARAGRAPH_NUMBER);
+            int maxParagraphNum = (int) documents.get().getMetadata()
+                    .get(SplitDocument.END_PARAGRAPH_NUMBER);
             //根据最大段落结束编码构建一个用于合并段落的空数组
             String[] paragraphs = new String[maxParagraphNum];
             //用于获取最小段落开始编码
@@ -44,21 +50,31 @@ public class MergeDocuments {
                 //文档内容根据回车进行分段
                 String[] tempPs = document.getContent().split("\n");
                 //获取文档开始段落编码
-                int startParagraphNumber = (int) document.getMetadata().get(SplitDocument.START_PARAGRAPH_NUMBER);
+                int startParagraphNumber = (int) document.getMetadata()
+                        .get(SplitDocument.START_PARAGRAPH_NUMBER);
                 if (minParagraphNum > startParagraphNumber) {
                     minParagraphNum = startParagraphNumber;
                 }
                 //将文档段落列表拷贝到合并段落数组中
-                System.arraycopy(tempPs, 0, paragraphs, startParagraphNumber - 1, tempPs.length);
+                System.arraycopy(
+                        tempPs,
+                        0,
+                        paragraphs,
+                        startParagraphNumber - 1,
+                        tempPs.length);
             }
             //合并段落去除空值,并组成文档内容
-            Document mergeDoc = new Document(ArrayUtil.join(ArrayUtil.removeNull(paragraphs), "\n"));
+            Document mergeDoc = new Document(
+                    ArrayUtil.join(ArrayUtil.removeNull(paragraphs), "\n"));
             //合并元数据
-            mergeDoc.getMetadata().putAll(docListEntry.getValue().get(0).getMetadata());
+            mergeDoc.getMetadata().putAll(docListEntry.getValue()
+                    .get(0).getMetadata());
             //设置元数据:开始段落编码
-            mergeDoc.getMetadata().put(SplitDocument.START_PARAGRAPH_NUMBER, minParagraphNum);
+            mergeDoc.getMetadata()
+                    .put(SplitDocument.START_PARAGRAPH_NUMBER, minParagraphNum);
             //设置元数据:结束段落编码
-            mergeDoc.getMetadata().put(SplitDocument.END_PARAGRAPH_NUMBER, maxParagraphNum);
+            mergeDoc.getMetadata()
+                    .put(SplitDocument.END_PARAGRAPH_NUMBER, maxParagraphNum);
             mergeDocuments.add(mergeDoc);
         }
         return mergeDocuments;

+ 37 - 13
src/main/java/cn/jlsxwkj/common/utils/SplitDocument.java

@@ -11,23 +11,35 @@ import java.util.stream.Collectors;
 /**
  * @author jay
  */
-public class SplitDocument {
+public final class SplitDocument {
+    private SplitDocument() {
+    }
 
+    /**
+     * 滑动窗口开始位置.
+     */
     public static final String START_PARAGRAPH_NUMBER = "startParagraphNumber";
+    /**
+     * 滑动窗口结束位置.
+     */
     public static final String END_PARAGRAPH_NUMBER = "endParagraphNumber";
+    /**
+     * 文件名.
+     */
     public static final String FILE_NAME = "source";
 
     /**
-     * 分割字符并转换为多个文档
+     * 分割字符并转换为多个文档.
      *
      * @param document   文档
      * @param windowSize 窗口大小
      * @param fileName   文件名
      * @return 多个文档
      */
-    public static List<Document> splitStringToListDocument(String document,
-                                                           int windowSize,
-                                                           String fileName) {
+    public static List<Document> splitStringToListDocument(
+            final String document,
+            final int windowSize,
+            final String fileName) {
         if (document.isBlank()) {
             return null;
         }
@@ -39,28 +51,40 @@ public class SplitDocument {
         int startIndex = 0;
         int endIndex = startIndex + windowSize;
         if (endIndex > paragraphs.size()) {
-            readDocuments.add(toDocument(paragraphs, fileName, startIndex + 1, paragraphs.size()));
+            readDocuments.add(toDocument(
+                    paragraphs,
+                    fileName,
+                    startIndex + 1,
+                    paragraphs.size()));
         } else {
             for (; endIndex <= paragraphs.size(); startIndex++, endIndex++) {
-                List<String> sub = ListUtil.sub(paragraphs, startIndex, endIndex);
-                readDocuments.add(toDocument(sub, fileName, startIndex + 1, endIndex));
+                List<String> sub = ListUtil.sub(
+                        paragraphs,
+                        startIndex,
+                        endIndex);
+                readDocuments.add(toDocument(
+                        sub,
+                        fileName,
+                        startIndex + 1,
+                        endIndex));
             }
         }
         return readDocuments;
     }
 
     /**
-     * 封装段落成文档
+     * 封装段落成文档.
      *
      * @param paragraphList     段落内容列表
+     * @param fileName          文件名
      * @param startParagraphNum 开始段落编码
      * @param endParagraphNum   结束段落编码
      * @return 文档信息
      */
-    private static Document toDocument(List<String> paragraphList,
-                                       String fileName,
-                                       int startParagraphNum,
-                                       int endParagraphNum) {
+    private static Document toDocument(final List<String> paragraphList,
+                                       final String fileName,
+                                       final int startParagraphNum,
+                                       final int endParagraphNum) {
         Document doc = new Document(String.join("\n", paragraphList));
         doc.getMetadata().put(FILE_NAME, fileName);
         doc.getMetadata().put(START_PARAGRAPH_NUMBER, startParagraphNum);

+ 4 - 0
src/main/java/cn/jlsxwkj/common/utils/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 工具包.
+ */
+package cn.jlsxwkj.common.utils;

+ 43 - 13
src/main/java/cn/jlsxwkj/moudles/chat/ChatController.java

@@ -2,7 +2,6 @@ package cn.jlsxwkj.moudles.chat;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import cn.jlsxwkj.common.exception.CustomException;
-import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import org.springframework.http.MediaType;
@@ -18,36 +17,67 @@ import reactor.core.publisher.Flux;
 @Tag(name = "RAG chat")
 public class ChatController {
 
+    /**
+     * chat 服务.
+     */
     @Resource
     private ChatService chatService;
 
-    @Operation(summary = "上传文档")
+    /**
+     * 上传文档.
+     *
+     * @param file 文件
+     * @return 上传成功
+     * @throws CustomException 上传失败异常
+     */
     @PostMapping("/upload")
     @SaIgnore
-    public String uploadDoc(@RequestBody MultipartFile file) throws CustomException {
+    public String uploadDoc(
+            @RequestBody final MultipartFile file) throws CustomException {
         return chatService.uploadDocument(file);
     }
 
-    @Operation(summary = "搜索文档")
+    /**
+     * 关键词搜索.
+     *
+     * @param keyword 关键词
+     * @return 结果
+     */
     @PostMapping("/search")
-    public String searchDoc(@RequestParam String keyword) {
+    public String searchDoc(@RequestParam final String keyword) {
         return chatService.search(keyword);
     }
 
-    @Operation(summary = "问答文档流")
-    @PostMapping(value = "/chatStream", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
-    public Flux<String> chatStream(@RequestParam String message) {
+    /**
+     * 问答文档流.
+     *
+     * @param message 消息
+     * @return 流消息
+     */
+    @PostMapping(value = "/chatStream",
+            produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
+    public Flux<String> chatStream(@RequestParam final String message) {
         return chatService.chatStream(message);
     }
 
-    @Operation(summary = "问答文档总结流")
-    @PostMapping(value = "/chatSummaryStream", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
-    public Flux<String> chatSummaryStream(@RequestParam(defaultValue = "帮我总结一下上面内容") String message,
-                                      @RequestBody MultipartFile file) {
+    /**
+     * 问答文档总结流.
+     *
+     * @param message 消息
+     * @param file    文件
+     * @return 流消息
+     */
+    @PostMapping(value = "/chatSummaryStream",
+            produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
+    public Flux<String> chatSummaryStream(
+            @RequestParam(defaultValue = "帮我总结一下上面内容") final String message,
+            @RequestBody final MultipartFile file) {
         return chatService.chatSummaryStream(message, file);
     }
 
-    @Operation(summary = "停止问答")
+    /**
+     * 停止问答.
+     */
     @GetMapping("/stopChat")
     public void stopChat() {
         chatService.stop();

+ 14 - 2
src/main/java/cn/jlsxwkj/moudles/chat/ChatRequest.java

@@ -2,7 +2,7 @@ package cn.jlsxwkj.moudles.chat;
 
 import cn.jlsxwkj.moudles.chat.message.Message;
 import lombok.Data;
-import org.springframework.ai.ollama.api.OllamaOptions;
+import org.springframework.ai.chat.prompt.ChatOptions;
 
 import java.util.List;
 
@@ -11,8 +11,20 @@ import java.util.List;
  */
 @Data
 public class ChatRequest {
+    /**
+     * 模型.
+     */
     private String model;
+    /**
+     * 消息列表.
+     */
     private List<Message> messages;
+    /**
+     * 是否流.
+     */
     private Boolean stream;
-    private OllamaOptions options;
+    /**
+     * chat 参数.
+     */
+    private ChatOptions options;
 }

+ 12 - 0
src/main/java/cn/jlsxwkj/moudles/chat/ChatResponse.java

@@ -8,8 +8,20 @@ import lombok.Data;
  */
 @Data
 public class ChatResponse {
+    /**
+     * 模型.
+     */
     private String model;
+    /**
+     * 创建时间.
+     */
     private String createdAt;
+    /**
+     * 机器人消息.
+     */
     private AssistantMessage message;
+    /**
+     * 是否完成.
+     */
     private Boolean done;
 }

+ 175 - 42
src/main/java/cn/jlsxwkj/moudles/chat/ChatService.java

@@ -9,11 +9,14 @@ import cn.jlsxwkj.common.utils.FileType;
 import cn.jlsxwkj.common.utils.Log;
 import cn.jlsxwkj.common.utils.MergeDocuments;
 import cn.jlsxwkj.moudles.chat.message.*;
-import cn.jlsxwkj.moudles.chathistory.ChatHistoryService;
+import cn.jlsxwkj.moudles.chat_history.ChatHistoryService;
 import jakarta.annotation.Resource;
+import org.springframework.ai.chat.prompt.Prompt;
 import org.springframework.ai.document.Document;
 import org.springframework.ai.document.DocumentReader;
 import org.springframework.ai.embedding.EmbeddingModel;
+import org.springframework.ai.ollama.OllamaChatModel;
+import org.springframework.ai.ollama.api.OllamaOptions;
 import org.springframework.ai.vectorstore.SearchRequest;
 import org.springframework.ai.vectorstore.VectorStore;
 import org.springframework.stereotype.Service;
@@ -22,10 +25,7 @@ import reactor.core.publisher.Flux;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -35,39 +35,90 @@ import java.util.stream.Collectors;
 @Service
 public class ChatService {
 
+    /**
+     * md5.
+     */
     private final MD5 md5 = cn.hutool.crypto.digest.MD5.create();
-    private final String PATH = System.getProperty("user.dir") + "/ai_doc/";
+    /**
+     * 获取当前项目地址 + /ai_doc.
+     */
+    private static final String
+            PATH = System.getProperty("user.dir") + "/ai_doc/";
+    /**
+     * 函数回调集合.
+     */
+    private static final HashSet<String> TOOLS_FUNCTION = new HashSet<>();
+    /**
+     * 历史消息列表.
+     */
     private List<Message> listMessage;
+    /**
+     * chat 消息.
+     */
     private StringBuffer chatMessage;
-
+    /**
+     * pg 向量对象(将文档转换为向量并保存至数据库).
+     */
     @Resource
     private VectorStore vectorStore;
+    /**
+     * ollama 模型.
+     */
+    @Resource
+    private OllamaChatModel ollamaChatModel;
+    /**
+     * 向量化模型.
+     */
     @Resource
     private EmbeddingModel embeddingModel;
+    /**
+     * 自定义 chat 工具.
+     */
     @Resource
     private ChatUtil chatUtil;
+    /**
+     * 保存对话对象(将对话保存至数据库).
+     */
     @Resource
     private ChatHistoryService chatHistoryService;
+    /**
+     * 自定义配置类.
+     */
     @Resource
     private UserConfig userConfig;
 
+    /*
+      初始化回调函数
+     */
+    static {
+        TOOLS_FUNCTION.add("getWeather");
+    }
 
     /**
-     * 使用spring ai解析txt文档并保存至 pg
+     * 使用spring ai解析txt文档并保存至 pg.
      *
      * @param file 保存的文件
      * @return 保存状态
      */
-    public String uploadDocument(MultipartFile file) throws CustomException {
+    public String uploadDocument(
+            final MultipartFile file) throws CustomException {
+        //检测文件是否支持
         Tuple supportFile = isSupportFile(file);
+        //需要保存的文件
         File saveFile = supportFile.get(0);
+        //文件名
         String fileName = supportFile.get(1);
+        //分割文档对象
         DocumentReader reader = supportFile.get(3);
+        //判断文件是否存在
         if (!saveFile.exists()) {
             try {
+                //保存文件
                 file.transferTo(saveFile);
+                //保存文档到数据库
                 vectorStore.add(reader.get());
             } catch (Exception e) {
+                //保存文件到数据库失败删除本地缓存文件
                 boolean delete = saveFile.delete();
                 if (!delete) {
                     Log.warn(this.getClass(), "删除文件失败: {}", fileName);
@@ -79,109 +130,153 @@ public class ChatService {
     }
 
     /**
-     * 根据关键词搜索向量库
+     * 根据关键词搜索向量库.
      *
      * @param keyword 关键词
      * @return 文本内容
      */
-    public String search(String keyword) {
-        SearchRequest searchRequest = SearchRequest.query(keyword).withSimilarityThreshold(0.5);
+    public String search(final String keyword) {
+        //设置检索文档关键字相似度至少近似 50% 以上
+        SearchRequest searchRequest =
+                SearchRequest.query(keyword).withSimilarityThreshold(0.5);
+        //检索文档
         List<Document> documents = vectorStore.similaritySearch(searchRequest);
+        //返回合并的文档
         return mergeDocuments(documents);
     }
 
     /**
-     * 问答流,根据输入内容回答
+     * 问答流,根据输入内容回答.
      *
      * @param message 输入内容
      * @return 回答内容
      */
-    public Flux<String> chatStream(String message) {
+    public Flux<String> chatStream(final String message) {
+        //检索知识库
         String context = search(message);
+        //预处理
+        //创建用户消息
+        org.springframework.ai.chat.messages.UserMessage userMessage =
+                new org.springframework.ai.chat.messages.UserMessage(message);
+        //设置提示词以及添加回调函数
+        Prompt prompt = new Prompt(userMessage, OllamaOptions.builder()
+                .withFunctions(TOOLS_FUNCTION).build());
+        //预处理, chat 总结的函数结果
+        String toolMessage = ollamaChatModel.call(prompt)
+                .getResult().getOutput().getContent();
+        //合并知识库结果和函数结果
         String format = """
-                %s : Please answer user questions based on the content.
                 %s
+                %s
+                如果以上内容不为空请永远用以上内容回答问题
                 """;
-        return stream(message, new SystemMessage(String.format(format, context, message)));
+        //提问 chat 并返回流
+        return stream(message, new SystemMessage(
+                String.format(format, context, toolMessage, message)));
     }
 
     /**
-     * 问答总结流, 根据给定的文档总结内容
+     * 问答总结流, 根据给定的文档总结内容.
      *
      * @param message 输入内容
      * @param file    文件
      * @return 内容总结
      */
-    public Flux<String> chatSummaryStream(String message, MultipartFile file) {
+    public Flux<String> chatSummaryStream(final String message,
+                                          final MultipartFile file) {
+        //检测模型是否开启
         embeddingModel.embed("");
+        //检测文件是否支持
         Tuple supportFile;
         try {
             supportFile = isSupportFile(file);
         } catch (CustomException e) {
+            //如果异常则通过流返回异常
             return Flux.just(e.getMessage()).concatWithValues("<{完成}>");
         }
+        //文件名
         String fileName = supportFile.get(1);
+        //文件类型
         String fileTypeCn = supportFile.get(2);
+        //分割文档对象
         DocumentReader reader = supportFile.get(3);
+        //格式化提问格式
         String format = """
                 %s :: %s ====> %s
                 ↑ %s
                 """;
-        String context = String.format(format, fileTypeCn, fileName, mergeDocuments(reader.get()), message);
+        String context = String.format(format,
+                fileTypeCn, fileName, mergeDocuments(reader.get()), message);
+        //设置用户消息
         UserMessage userMessage = new UserMessage(context);
         Log.info(this.getClass(), context);
+        //返回 chat 流
         return stream(message, userMessage);
     }
 
     /**
-     * 合并文档
+     * 合并文档.
      *
      * @param documents 文档列表
      * @return 合并后的文档
      */
-    private String mergeDocuments(List<Document> documents) {
+    private String mergeDocuments(final List<Document> documents) {
         return MergeDocuments.mergeDocuments(documents).stream()
                 .map(Document::getContent)
                 .collect(Collectors.joining("\n"));
     }
 
     /**
-     * 停止 chat
+     * 停止 chat.
      */
     public void stop() {
         chatUtil.stop();
     }
 
     /**
-     * 获取prompt
+     * 获取prompt.
      *
      * @param message 提问内容
      * @param context 提示词
      */
-    private void setChatMessage(String message, Message context) {
+    private void setChatMessage(final String message,
+                                final Message context) {
+        //初始化消息并设置系统提示词
         if (listMessage == null) {
             listMessage = new ArrayList<>();
             listMessage.add(new SystemMessage(userConfig.getSysMessage()));
         }
+        //判断消息列表是否大于定义的消息列表长度
         if (listMessage.size() > userConfig.getMaxListMessageLength()) {
-            int start = listMessage.size() - userConfig.getMaxListMessageLength();
-            listMessage = listMessage.subList(start, listMessage.size()).stream()
-                    .filter(msg -> !msg.getContent().equals(userConfig.getSysMessage()))
+            //缩减长度到指定列表长度
+            int start =
+                    listMessage.size() - userConfig.getMaxListMessageLength();
+            listMessage = listMessage.subList(start,
+                    listMessage.size()).stream()
+                    //过滤定义的定义的系统消息
+                    .filter(msg -> !msg.getContent()
+                            .equals(userConfig.getSysMessage()))
                     .map(msg -> {
+                        //判断是否为 chat 消息, 如果是缩减 chat 回答后的长度
                         if (msg.getRole().equals(UserRole.ASSISTANT)) {
                             String content = msg.getContent();
-                            if (content.length() > userConfig.getMaxMessageLength()) {
-                                String assistantMessage = content.substring(0, userConfig.getMaxMessageLength());
-                                return new AssistantMessage(assistantMessage);
+                            if (content.length()
+                                    > userConfig.getMaxMessageLength()) {
+                                return new AssistantMessage(content.substring(
+                                        0,
+                                        userConfig.getMaxMessageLength()));
                             }
                         }
                         return msg;
                     }).distinct()
                     .collect(Collectors.toList());
+            //再次将自定义系统提示词添加到列表末尾
             listMessage.add(new SystemMessage(userConfig.getSysMessage()));
         }
+        //如果 context 是系统消息则将两个都添加
         if (context.getRole().equals(UserRole.SYSTEM)) {
             listMessage.add(new UserMessage(message));
+            //判断系统消息是否为空
             if (!context.getContent().isBlank()) {
                 listMessage.add(context);
             }
@@ -192,68 +287,106 @@ public class ChatService {
     }
 
     /**
-     * chat stream 封装
+     * chat stream 封装.
      *
      * @param message 提问内容
      * @param context 提示词
      * @return flux
      */
-    private Flux<String> stream(String message, Message context) {
+    private Flux<String> stream(final String message,
+                                final Message context) {
+        //获取用户id
         String userId = SaManager.getStpLogic("").getLoginIdAsString();
+        //初始化
         chatMessage = new StringBuffer();
+        //设置消息列表
         setChatMessage(message, context);
+        //返回消息流
         return chatUtil.chat(listMessage, true).map(response -> {
+            //获取消息主体
             String str = response.getMessage().getContent();
+            //添加至消息中
             chatMessage.append(str);
-            System.out.print(str);
+            //格式化字符串
             return str.replace(" ", "  ")
                     .replace("\t", "    ");
-        }).concatWithValues("<{完成}>")
+        })
+                //流完成后拼接的字符
+                .concatWithValues("<{完成}>")
+                //取消时返回的调度器
                 .cancelOn(chatUtil.getScheduler())
-                .doOnCancel(this::stop)
+                //取消时执行的操作
+                .doOnCancel(() -> {
+                    //上游
+                    this.stop();
+                    Log.info(this.getClass(), "{} ==== 用户停止", userId);
+                })
+                //流完成时的操作
                 .doOnComplete(() -> {
                     String chatMsg = chatMessage.toString();
                     listMessage.add(new AssistantMessage(chatMsg));
                     try {
+                        //将消息添加至数据库
                         chatHistoryService.insert(userId, message, chatMsg);
                     } catch (InsertFailException e) {
                         Log.warn(this.getClass(), e.getMessage());
                     }
-                    Log.info(this.getClass(), "{} user message ==> {}", userId, message);
-                    Log.info(this.getClass(), "{} chat message ==> {}", userId, chatMsg);
+                    Log.info(this.getClass(),
+                            "{} user message ==> {}", userId, message);
+                    Log.info(this.getClass(),
+                            "{} chat message ==> {}", userId, chatMsg);
                 });
     }
 
     /**
-     * 封装文件
+     * 封装文件.
      *
      * @param file 文件流
-     * @return 元组(File file, String fileName, String fileTypeCn, DocumentReader reader)
+     * @return 元组
      */
-    private Tuple isSupportFile(MultipartFile file) throws CustomException {
+    private Tuple isSupportFile(
+            final MultipartFile file) throws CustomException {
+        //初始化
         byte[] bytes;
         try {
+            //读取文件
             bytes = file.getBytes();
         } catch (IOException e) {
             throw new OpenFileFailException("读取文件失败");
         }
-        String[] split = Objects.requireNonNull(file.getOriginalFilename()).split("\\.");
+        //对文件名分割
+        String[] split = Objects.requireNonNull(file.getOriginalFilename())
+                .split("\\.");
+        //文件类型
         String fileType = split[split.length - 1].toLowerCase(Locale.ROOT);
+        //保存文件地址
         File savePath = new File(PATH);
+        //保存文件
         File saveFile = new File(PATH + md5.digestHex(bytes) + "." + fileType);
+        //文件名
         String fileName = saveFile.getName();
+        //判断文件地址是否存在
         if (!savePath.exists()) {
+            //创建文件夹
             if (!savePath.mkdirs()) {
                 Log.warn(this.getClass(), "创建文件夹失败: " + PATH);
             }
         }
-        Tuple fileTypeAndResource = new FileType(bytes, fileName, 5, userConfig.getCnocrUrl())
+        //获取文件的各参数
+        Tuple fileTypeAndResource = new FileType(
+                bytes,
+                fileName,
+                5,
+                userConfig.getCnocrUrl())
                 .getFileTypeAndResource(fileType);
         if (fileTypeAndResource == null) {
             throw new FileTypeDoesNotSupportException("暂不支持的文件类型: " + fileType);
         }
+        //文件类型(中文)
         String fileTypeCn = fileTypeAndResource.get(0);
+        //分割文档对象
         DocumentReader reader = fileTypeAndResource.get(1);
+        //返回(保存文件对象, 文件名, 文件类型中文名, 分割文档对象)
         return new Tuple(saveFile, fileName, fileTypeCn, reader);
     }
 }

+ 29 - 9
src/main/java/cn/jlsxwkj/moudles/chat/ChatUtil.java

@@ -2,12 +2,12 @@ package cn.jlsxwkj.moudles.chat;
 
 import cn.hutool.http.HttpRequest;
 import cn.hutool.json.JSONUtil;
+import cn.jlsxwkj.common.config.UserConfig;
 import cn.jlsxwkj.common.utils.Log;
 import cn.jlsxwkj.moudles.chat.message.Message;
 import jakarta.annotation.Resource;
 import org.springframework.ai.autoconfigure.ollama.OllamaConnectionDetails;
 import org.springframework.ai.chat.model.ChatModel;
-import org.springframework.ai.ollama.api.OllamaOptions;
 import org.springframework.stereotype.Component;
 import reactor.core.publisher.Flux;
 import reactor.core.scheduler.Scheduler;
@@ -26,31 +26,51 @@ import java.util.List;
 @Component
 public class ChatUtil {
 
+    /**
+     * ChatModel.
+     */
     @Resource
     private ChatModel chatModel;
+    /**
+     * model url.
+     */
     @Resource
     private OllamaConnectionDetails ollamaConnectionDetails;
+    /**
+     * InputStream.
+     */
     private InputStream inputStream;
+    /**
+     * InputStreamReader.
+     */
     private InputStreamReader inputStreamReader;
+    /**
+     * BufferedReader.
+     */
     private BufferedReader bufferedReader;
+    /**
+     * Scheduler.
+     */
     private final Scheduler scheduler = Schedulers.single();
 
     /**
-     * 请求上游 chat api
+     * 请求上游 chat api.
      *
      * @param messages 消息列表(带历史对话)
      * @param isStream 是否流式返回
      * @return 流式返回
      */
-    public Flux<ChatResponse> chat(List<Message> messages, boolean isStream) {
+    public Flux<ChatResponse> chat(
+            final List<Message> messages,
+            final boolean isStream) {
         ChatRequest chatRequest = new ChatRequest();
-        OllamaOptions options = (OllamaOptions) chatModel.getDefaultOptions();
-        chatRequest.setModel(options.getModel());
+        chatRequest.setModel(chatModel.getDefaultOptions().getModel());
         chatRequest.setMessages(messages);
         chatRequest.setStream(isStream);
-        chatRequest.setOptions(options);
+        chatRequest.setOptions(chatModel.getDefaultOptions());
         Log.info(this.getClass(), JSONUtil.toJsonStr(chatRequest));
-        inputStream = HttpRequest.post(ollamaConnectionDetails.getBaseUrl() + "/api/chat")
+        inputStream = HttpRequest.post(
+                ollamaConnectionDetails.getBaseUrl() + "/api/chat")
                 .body(JSONUtil.toJsonStr(chatRequest))
                 .execute(isStream)
                 .bodyStream();
@@ -62,7 +82,7 @@ public class ChatUtil {
     }
 
     /**
-     * 停止流
+     * 停止流.
      */
     public void stop() {
         try {
@@ -83,7 +103,7 @@ public class ChatUtil {
     }
 
     /**
-     * 获取调度器
+     * 获取调度器.
      *
      * @return 调度器
      */

+ 6 - 1
src/main/java/cn/jlsxwkj/moudles/chat/message/AssistantMessage.java

@@ -10,7 +10,12 @@ import lombok.EqualsAndHashCode;
 @Data
 public class AssistantMessage extends Message {
 
-    public AssistantMessage(String message) {
+    /**
+     * 机器人消息.
+     *
+     * @param message 消息
+     */
+    public AssistantMessage(final String message) {
         this.setRole(UserRole.ASSISTANT);
         this.setContent(message);
     }

+ 7 - 0
src/main/java/cn/jlsxwkj/moudles/chat/message/Message.java

@@ -4,9 +4,16 @@ import lombok.Data;
 
 /**
  * @author zh
+ * 消息父类
  */
 @Data
 public abstract class Message {
+    /**
+     * 角色.
+     */
     private String role;
+    /**
+     * 消息.
+     */
     private String content;
 }

+ 5 - 1
src/main/java/cn/jlsxwkj/moudles/chat/message/SystemMessage.java

@@ -10,7 +10,11 @@ import lombok.EqualsAndHashCode;
 @Data
 public class SystemMessage extends Message {
 
-    public SystemMessage(String message) {
+    /**
+     * 系统消息.
+     * @param message 消息
+     */
+    public SystemMessage(final String message) {
         this.setRole(UserRole.SYSTEM);
         this.setContent(message);
     }

+ 5 - 1
src/main/java/cn/jlsxwkj/moudles/chat/message/UserMessage.java

@@ -10,7 +10,11 @@ import lombok.EqualsAndHashCode;
 @Data
 public class UserMessage extends Message {
 
-    public UserMessage(String message) {
+    /**
+     * 用户消息.
+     * @param message 消息
+     */
+    public UserMessage(final String message) {
         this.setRole(UserRole.USER);
         this.setContent(message);
     }

+ 11 - 0
src/main/java/cn/jlsxwkj/moudles/chat/message/UserRole.java

@@ -4,9 +4,20 @@ package cn.jlsxwkj.moudles.chat.message;
  * @author zh
  */
 public final class UserRole {
+    private UserRole() {
+    }
 
+    /**
+     * 用户.
+     */
     public static final String USER = "user";
+    /**
+     * 系统.
+     */
     public static final String SYSTEM = "system";
+    /**
+     * 机器人.
+     */
     public static final String ASSISTANT = "assistant";
 
 }

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/chat/message/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 消息包.
+ */
+package cn.jlsxwkj.moudles.chat.message;

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/chat/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * chat 包.
+ */
+package cn.jlsxwkj.moudles.chat;

+ 10 - 1
src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistory.java → src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistory.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.chathistory;
+package cn.jlsxwkj.moudles.chat_history;
 
 import cn.jlsxwkj.common.dao.Dao;
 import lombok.Data;
@@ -11,8 +11,17 @@ import lombok.EqualsAndHashCode;
 @Data
 public class ChatHistory extends Dao {
 
+    /**
+     * 用户id.
+     */
     private String userId;
+    /**
+     * 用户问.
+     */
     private String userQ;
+    /**
+     * chat 回答.
+     */
     private String chatA;
 
 }

+ 8 - 3
src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistoryController.java → src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryController.java

@@ -1,6 +1,5 @@
-package cn.jlsxwkj.moudles.chathistory;
+package cn.jlsxwkj.moudles.chat_history;
 
-import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -17,10 +16,16 @@ import java.util.List;
 @Tag(name = "chat history")
 public class ChatHistoryController {
 
+    /**
+     * ChatHistoryService.
+     */
     @Resource
     private ChatHistoryService chatHistoryService;
 
-    @Operation(summary = "获取历史对话")
+    /**
+     * 获取历史对话.
+     * @return 返回历史消息列表
+     */
     @GetMapping("/getHistory")
     public List<ChatHistoryVO> selectHistory() {
         return chatHistoryService.selectHistoryByUserId();

+ 14 - 2
src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistoryMapper.java → src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryMapper.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.chathistory;
+package cn.jlsxwkj.moudles.chat_history;
 
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
@@ -13,14 +13,26 @@ import java.util.List;
 @Mapper
 public interface ChatHistoryMapper {
 
+    /**
+     * 插入对话消息.
+     * @param userId 用户id
+     * @param userQ 用户问
+     * @param chatA chat 回答
+     * @return 成功条数
+     */
     @Insert("""
-            insert into chat_history(user_id, "user_Q", "chat_A") 
+            insert into chat_history(user_id, "user_Q", "chat_A")
             values (#{userId}, #{userQ}, #{chatA})
             """)
     Integer insert(@Param("userId") String userId,
                    @Param("userQ") String userQ,
                    @Param("chatA") String chatA);
 
+    /**
+     * 查询历史回答.
+     * @param userId 用户id
+     * @return 返回近期 20 条历史回答
+     */
     @Select("""
             select *
             from chat_history

+ 16 - 9
src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistoryService.java → src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryService.java

@@ -1,13 +1,8 @@
-package cn.jlsxwkj.moudles.chathistory;
+package cn.jlsxwkj.moudles.chat_history;
 
 import cn.dev33.satoken.SaManager;
-import cn.hutool.json.JSONUtil;
 import cn.jlsxwkj.common.exception.InsertFailException;
 import jakarta.annotation.Resource;
-import org.springframework.ai.autoconfigure.ollama.OllamaConnectionDetails;
-import org.springframework.ai.chat.memory.ChatMemory;
-import org.springframework.ai.chat.model.ChatModel;
-import org.springframework.ai.ollama.api.OllamaOptions;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -19,19 +14,31 @@ import java.util.List;
 @Service
 public class ChatHistoryService {
 
+    /**
+     * ChatHistoryMapper.
+     */
     @Resource
     private ChatHistoryMapper chatHistoryMapper;
 
+    /**
+     * @param userId userId
+     * @param userQ  userQ
+     * @param chatA  chatA
+     * @throws InsertFailException 插入失败
+     */
     @Transactional(rollbackFor = InsertFailException.class)
-    public void insert(String userId,
-                       String userQ,
-                       String chatA) throws InsertFailException {
+    public void insert(final String userId,
+                       final String userQ,
+                       final String chatA) throws InsertFailException {
         Integer rows = chatHistoryMapper.insert(userId, userQ, chatA);
         if (rows < 1) {
             throw new InsertFailException("插入失败");
         }
     }
 
+    /**
+     * @return 历史消息列表
+     */
     public List<ChatHistoryVO> selectHistoryByUserId() {
         String userId = SaManager.getStpLogic("").getLoginIdAsString();
         return chatHistoryMapper.selectHistoryByUserId(userId);

+ 12 - 0
src/main/java/cn/jlsxwkj/moudles/chat_history/ChatHistoryVO.java

@@ -0,0 +1,12 @@
+package cn.jlsxwkj.moudles.chat_history;
+
+/**
+ * @param userId 用户id
+ * @param userQ  用户问
+ * @param chatA  chat 回答
+ */
+public record ChatHistoryVO(
+        String userId,
+        String userQ,
+        String chatA) {
+}

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/chat_history/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * chat_history 包.
+ */
+package cn.jlsxwkj.moudles.chat_history;

+ 0 - 13
src/main/java/cn/jlsxwkj/moudles/chathistory/ChatHistoryVO.java

@@ -1,13 +0,0 @@
-package cn.jlsxwkj.moudles.chathistory;
-
-import lombok.Data;
-
-/**
- * @author zh
- */
-@Data
-public class ChatHistoryVO {
-    private String userId;
-    private String userQ;
-    private String chatA;
-}

+ 20 - 2
src/main/java/cn/jlsxwkj/moudles/logerror/LogError.java → src/main/java/cn/jlsxwkj/moudles/log_error/LogError.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.logerror;
+package cn.jlsxwkj.moudles.log_error;
 
 import cn.jlsxwkj.common.R.ResponseError;
 import cn.jlsxwkj.common.dao.Dao;
@@ -12,12 +12,30 @@ import lombok.EqualsAndHashCode;
 @Data
 public class LogError extends Dao {
 
+    /**
+     * 异常名.
+     */
     private String exception;
+    /**
+     * 异常消息.
+     */
     private String message;
+    /**
+     * 异常信息.
+     */
     private String errorInfo;
+    /**
+     * 异常堆栈.
+     */
     private String errorStackTrace;
 
-    public LogError castResponseErrorToLogError(ResponseError errorHandler) {
+    /**
+     * 转换异常.
+     * @param errorHandler 异常
+     * @return LogError
+     */
+    public LogError castResponseErrorToLogError(
+            final ResponseError errorHandler) {
         this.setMessage(errorHandler.getMessage());
         this.setException(errorHandler.getException());
         return this;

+ 32 - 0
src/main/java/cn/jlsxwkj/moudles/log_error/LogErrorMapper.java

@@ -0,0 +1,32 @@
+package cn.jlsxwkj.moudles.log_error;
+
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author zh
+ */
+@Mapper
+public interface LogErrorMapper {
+
+    /**
+     * 插入错误日志.
+     *
+     * @param logError log实体
+     * @return 成功条数
+     */
+    @Insert("""
+            insert into log_error(
+                message,
+                exception,
+                error_info,
+                error_stack_trace)
+            values (
+                #{LogError.message},
+                #{LogError.exception},
+                #{LogError.errorInfo},
+                #{LogError.errorStackTrace})
+            """)
+    Integer insertOne(@Param("LogError") LogError logError);
+}

+ 9 - 2
src/main/java/cn/jlsxwkj/moudles/logerror/LogErrorService.java → src/main/java/cn/jlsxwkj/moudles/log_error/LogErrorService.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.logerror;
+package cn.jlsxwkj.moudles.log_error;
 
 import cn.jlsxwkj.common.exception.InsertFailException;
 import jakarta.annotation.Resource;
@@ -11,11 +11,18 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class LogErrorService {
 
+    /**
+     * LogErrorMapper.
+     */
     @Resource
     private LogErrorMapper logErrorMapper;
 
+    /**
+     * @param logError logError
+     * @throws InsertFailException 插入失败
+     */
     @Transactional(rollbackFor = InsertFailException.class)
-    public void insertOne(LogError logError) throws InsertFailException {
+    public void insertOne(final LogError logError) throws InsertFailException {
         Integer rows = logErrorMapper.insertOne(logError);
         if (rows < 1) {
             throw new InsertFailException("插入失败");

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/log_error/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * log_error 包.
+ */
+package cn.jlsxwkj.moudles.log_error;

+ 0 - 23
src/main/java/cn/jlsxwkj/moudles/logerror/LogErrorMapper.java

@@ -1,23 +0,0 @@
-package cn.jlsxwkj.moudles.logerror;
-
-import org.apache.ibatis.annotations.Insert;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * @author zh
- */
-@Mapper
-public interface LogErrorMapper {
-
-    /**
-     * 插入错误日志
-     *
-     * @param logError log实体
-     */
-    @Insert("""
-            insert into log_error(message, exception, error_info,error_stack_trace) 
-            values (#{LogError.message}, #{LogError.exception},#{LogError.errorInfo},#{LogError.errorStackTrace})
-            """)
-    Integer insertOne(@Param("LogError") LogError logError);
-}

+ 10 - 1
src/main/java/cn/jlsxwkj/moudles/userlist/UserList.java → src/main/java/cn/jlsxwkj/moudles/user_list/UserList.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.userlist;
+package cn.jlsxwkj.moudles.user_list;
 
 import cn.jlsxwkj.common.dao.Dao;
 import lombok.Data;
@@ -10,7 +10,16 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class UserList extends Dao {
+    /**
+     * 用户id.
+     */
     private String userId;
+    /**
+     * 用户名.
+     */
     private String userName;
+    /**
+     * 用户密码.
+     */
     private String userPassword;
 }

+ 20 - 6
src/main/java/cn/jlsxwkj/moudles/userlist/UserListController.java → src/main/java/cn/jlsxwkj/moudles/user_list/UserListController.java

@@ -1,9 +1,8 @@
-package cn.jlsxwkj.moudles.userlist;
+package cn.jlsxwkj.moudles.user_list;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.jlsxwkj.common.exception.CustomException;
-import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import org.springframework.web.bind.annotation.*;
@@ -16,18 +15,33 @@ import org.springframework.web.bind.annotation.*;
 @Tag(name = "user login")
 public class UserListController {
 
+    /**
+     * UserListService.
+     */
     @Resource
     private UserListService userListService;
 
-    @Operation(summary = "登录")
+    /**
+     * 登录.
+     *
+     * @param userName     用户名
+     * @param userPassword 密码
+     * @return 用户封装
+     * @throws CustomException CustomException
+     */
     @PostMapping("/login")
     @SaIgnore
-    public UserVO login(@RequestParam String userName,
-                        @RequestParam String userPassword) throws CustomException {
+    public UserVO login(
+            @RequestParam final String userName,
+            @RequestParam final String userPassword) throws CustomException {
         return userListService.checkOrAddUser(userName, userPassword);
     }
 
-    @Operation(summary = "登出")
+    /**
+     * 登出.
+     *
+     * @return 登出成功
+     */
     @GetMapping("/logout")
     public String logout() {
         StpUtil.logout();

+ 46 - 0
src/main/java/cn/jlsxwkj/moudles/user_list/UserListMapper.java

@@ -0,0 +1,46 @@
+package cn.jlsxwkj.moudles.user_list;
+
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * @author zh
+ */
+@Mapper
+public interface UserListMapper {
+
+    /**
+     * 注册用户.
+     *
+     * @param user 用户实体
+     * @return 插入条数
+     */
+    @Insert("""
+            insert into user_list(
+                user_id,
+                user_name,
+                user_password)
+            values (
+                #{user.userId},
+                #{user.userName},
+                #{user.userPassword})
+            """)
+    Integer authUser(@Param("user") UserList user);
+
+    /**
+     * 查询用户是否存在.
+     *
+     * @param userName 用户名
+     * @return 用户实体
+     */
+    @Select("""
+            select *
+            from user_list
+            where user_name = #{userName}
+            and is_deleted = 0
+            limit 1
+            """)
+    UserList checkUser(@Param("userName") String userName);
+}

+ 31 - 12
src/main/java/cn/jlsxwkj/moudles/userlist/UserListService.java → src/main/java/cn/jlsxwkj/moudles/user_list/UserListService.java

@@ -1,4 +1,4 @@
-package cn.jlsxwkj.moudles.userlist;
+package cn.jlsxwkj.moudles.user_list;
 
 import cn.dev33.satoken.secure.SaSecureUtil;
 import cn.dev33.satoken.stp.StpUtil;
@@ -15,19 +15,36 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class UserListService {
 
+    /**
+     * UserListMapper.
+     */
     @Resource
     private UserListMapper userListMapper;
 
+    /**
+     * 雪花id.
+     */
     private final Snowflake snowflake = new Snowflake();
 
+    /**
+     * 注册或登录.
+     *
+     * @param userName     用户名
+     * @param userPassword 密码
+     * @return 用户封装
+     * @throws CustomException CustomException
+     */
     @Transactional(rollbackFor = AccountAuthFailException.class)
-    public UserVO checkOrAddUser(String userName, String userPassword) throws CustomException {
+    public UserVO checkOrAddUser(
+            final String userName,
+            final String userPassword) throws CustomException {
         if (!CheckPassword.checkPassword(userPassword)) {
-            throw new AccountPasswordCheckFailException("密码长度为8到20位,必须包含字母和数字,字母区分大小写");
+            throw new AccountPasswordCheckFailException(
+                    "密码长度为8到20位,必须包含字母和数字,字母区分大小写"
+            );
         }
         String sha512pwd = SaSecureUtil.sha512(userPassword);
         UserList userList = userListMapper.checkUser(userName);
-        UserVO userVO = new UserVO();
         String userId;
         if (userList != null) {
             if (!userList.getUserPassword().contains(sha512pwd)) {
@@ -36,10 +53,11 @@ public class UserListService {
             if (!StpUtil.isLogin()) {
                 userId = userList.getUserId();
                 StpUtil.login(userId, false);
-                userVO.setUserId(userId);
-                userVO.setUserName(userList.getUserName());
-                userVO.setMessage("登录成功");
-                return userVO;
+                return new UserVO(
+                        userId,
+                        userList.getUserName(),
+                        "登录成功"
+                );
             }
             throw new LoginAccountAlreadyLoginException("请勿重复登录");
         }
@@ -51,10 +69,11 @@ public class UserListService {
         if (rows > 0) {
             userId = userList.getUserId();
             StpUtil.login(userId, false);
-            userVO.setUserId(userId);
-            userVO.setUserName(userList.getUserName());
-            userVO.setMessage("注册成功");
-            return userVO;
+            return new UserVO(
+                    userId,
+                    userList.getUserName(),
+                    "注册成功"
+            );
 
         }
         throw new AccountAuthFailException("注册失败");

+ 12 - 0
src/main/java/cn/jlsxwkj/moudles/user_list/UserVO.java

@@ -0,0 +1,12 @@
+package cn.jlsxwkj.moudles.user_list;
+
+/**
+ * @param userId   用户id
+ * @param userName 用户名
+ * @param message  用户消息
+ */
+public record UserVO(
+        String userId,
+        String userName,
+        String message) {
+}

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/user_list/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * user_list 包.
+ */
+package cn.jlsxwkj.moudles.user_list;

+ 0 - 28
src/main/java/cn/jlsxwkj/moudles/userlist/UserListMapper.java

@@ -1,28 +0,0 @@
-package cn.jlsxwkj.moudles.userlist;
-
-import org.apache.ibatis.annotations.Insert;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
-
-/**
- * @author zh
- */
-@Mapper
-public interface UserListMapper {
-
-    @Insert("""
-            insert into user_list(user_id, user_name, user_password) 
-            values (#{user.userId}, #{user.userName}, #{user.userPassword})
-            """)
-    Integer authUser(@Param("user") UserList user);
-
-    @Select("""
-            select * 
-            from user_list
-            where user_name = #{userName} 
-            and is_deleted = 0
-            limit 1
-            """)
-    UserList checkUser(@Param("userName") String userName);
-}

+ 0 - 13
src/main/java/cn/jlsxwkj/moudles/userlist/UserVO.java

@@ -1,13 +0,0 @@
-package cn.jlsxwkj.moudles.userlist;
-
-import lombok.Data;
-
-/**
- * @author zh
- */
-@Data
-public class UserVO {
-    private String userId;
-    private String userName;
-    private String message;
-}

+ 12 - 0
src/main/java/cn/jlsxwkj/moudles/weather_demo/Request.java

@@ -0,0 +1,12 @@
+package cn.jlsxwkj.moudles.weather_demo;
+
+import com.fasterxml.jackson.annotation.JsonPropertyDescription;
+
+/**
+ * @param sheng 省
+ * @param place 地区
+ */
+public record Request(
+        @JsonPropertyDescription("省") String sheng,
+        @JsonPropertyDescription("地区") String place) {
+}

+ 65 - 0
src/main/java/cn/jlsxwkj/moudles/weather_demo/WeatherService.java

@@ -0,0 +1,65 @@
+package cn.jlsxwkj.moudles.weather_demo;
+
+import cn.hutool.http.HttpRequest;
+import cn.jlsxwkj.common.utils.Log;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.function.Function;
+
+/**
+ * @author zh
+ */
+@Service
+public class WeatherService implements Function<Request, String> {
+
+    /**
+     * @param request Request
+     * @return 天气
+     */
+    @Override
+    public String apply(Request request) {
+        Log.info(this.getClass(),
+                "省 : {},  地区 {}", request.sheng(), request.place());
+        HashMap<String, Object> kv = new HashMap<>();
+        kv.put("id", 88888888);
+        kv.put("key", 88888888);
+        kv.put("sheng", request.sheng());
+        kv.put("place", request.place());
+        String body = HttpRequest.get(
+                "https://cn.apihz.cn/api/tianqi/tqyb.php?")
+                .form(kv).execute().body();
+        Log.info(this.getClass(), body);
+        return body;
+        /*
+        JSONObject weather = new JSONObject(body)
+            .setDateFormat("yyyy-mm-dd HH:MM:ss");
+        String format = """
+                降水: %s
+                温度: %s
+                气压: %s
+                湿度: %s
+                风向: %s
+                风向度: %s
+                风速: %s
+                风力等级: %s
+                地区: %s
+                天气: %s - %s
+                """;
+
+        return String.format(format,
+                weather.get("precipitation"),
+                weather.get("temperature"),
+                weather.get("pressure"),
+                weather.get("humidity"),
+                weather.get("windDirection"),
+                weather.get("windDirectionDegree"),
+                weather.get("windSpeed"),
+                weather.get("windScale"),
+                weather.get("place"),
+                weather.get("weather1"),
+                weather.get("weather2"));
+        */
+    }
+}
+

+ 4 - 0
src/main/java/cn/jlsxwkj/moudles/weather_demo/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * 天气包.
+ */
+package cn.jlsxwkj.moudles.weather_demo;

+ 15 - 6
src/main/resources/application-dev.yml

@@ -1,27 +1,36 @@
 spring:
   datasource:
-    url: jdbc:postgresql://localhost:5433/postgres
-    username: postgres
-    password: postgres
+      url: jdbc:postgresql://localhost:5433/postgres
+      username: postgres
+      password: postgres
   ai:
     vectorstore:
       pgvector:
-        #embedding的向量维度,这里的768是根据nomic-embed-text返回的向量维度配置的
+        # embedding 的向量维度,这里的 768 是根据 nomic-embed-text 返回的向量维度配置的
         dimensions: 768
     ollama:
       base-url: http://localhost:11434
       chat:
-        model: qwen2:7b
+        model: sam4096/qwen2tools:1.5b
         options:
+          # 上下文 token 数
           num-ctx: 10240
+          # 模型在线时长
           keep-alive: 24h
+          # 是否开启 gpu 1 代表开启
+          num-g-p-u: 0
+          temperature: 0.5
       embedding:
-        model: mofanke/dmeta-embedding-zh
+        model: shaw/dmeta-embedding-zh
 customer:
   cnocr-url: "http://www.jlsxwkj.cn:8501/ocr"
   sys-message: "Always say you're an ai or 大模型 from 玄武科技"
+  # 历史消息最大长度
   max-list-message-length: 12
+  # 每条消息最大长度
   max-message-length: 512
+  # api 执行时间, 超过打印在控制台
   exec-time: 100
+  # 限流, 每 5 秒 可以请求 2 次
   rate-limit-sec: 5
   gen-tokens: 2