当前位置: 首页 > news >正文

基于ollama,langchain,springboot从零搭建知识库四【设计通用rag系统】

需求:

        1:可以自定义管理大模型,可自行选择ollama,openai,千问等大模型

        2:自定义向量数据库,支持pgvector,elasticsearch,milvus(这三个目前比较常用,且支持过滤元数据)

        3:自定义管理知识库,知识库中可以支持创建文档,文档切片,修改切片,向量搜索等功能

        4:系统可以根据不同的知识库检索用户需要的内容

表设计:

用户表:

CREATE TABLE `rag_user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL COMMENT '用户名 ',`password` varchar(255) NOT NULL COMMENT '用户密码',`phone` varchar(15) NOT NULL COMMENT '用户手机号',`cover` varchar(255) NOT NULL COMMENT '用户头像',`status` tinyint NOT NULL COMMENT '用户状态0:不可用  1:可用',`ctime` datetime DEFAULT NULL,`utime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`delete_flag` tinyint DEFAULT NULL,`cby` tinyint DEFAULT NULL,`uby` tinyint DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

模型表:

CREATE TABLE `rag_model` (`id` bigint NOT NULL AUTO_INCREMENT,`code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '唯一键(用于唯一确定bean)',`model_name` varchar(255) NOT NULL COMMENT '模型名',`type` varchar(10) NOT NULL COMMENT '类型(MODEL:模型  EMBEDDING:向量)',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '名称',`supplier` varchar(10) NOT NULL COMMENT '模型厂商 OLLAMA:ollama  QWEN:千问   OPENAI:openAi',`response_length` int DEFAULT NULL COMMENT '响应结果长度',`temperature` double DEFAULT NULL COMMENT '温度',`top` double DEFAULT NULL COMMENT '匹配数',`api_key` varchar(255) DEFAULT NULL COMMENT '模型的key(ollama不需要)',`secret_key` varchar(255) DEFAULT NULL COMMENT '模型secret',`url` varchar(255) DEFAULT NULL COMMENT '模型url',`dimensions` int DEFAULT NULL COMMENT '向量模型维度数',`ctime` datetime DEFAULT NULL,`utime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`delete_flag` tinyint DEFAULT NULL COMMENT '是否删除  0:否  1:是',`cby` bigint DEFAULT NULL COMMENT '创建人',`uby` bigint DEFAULT NULL COMMENT '创建人',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

向量库表:

CREATE TABLE `rag_embedding_store` (`id` bigint NOT NULL AUTO_INCREMENT,`code` varchar(255) NOT NULL COMMENT '用于唯一确定bean',`name` varchar(255) NOT NULL COMMENT '向量数据库名称',`supplier` varchar(10) NOT NULL COMMENT '向量数据库类型(PG:pgvector , MILVUS:Milvus  ES:Elasticsearch)',`port` int NOT NULL COMMENT '端口号',`host` varchar(255) NOT NULL COMMENT '数据库ip',`user_name` varchar(255) NOT NULL COMMENT '用户名',`password` varchar(255) NOT NULL COMMENT '密码',`database` varchar(255) NOT NULL COMMENT '数据库名',`table_name` varchar(255) NOT NULL COMMENT '表名',`dimensions` int DEFAULT NULL COMMENT '向量维度',`ctime` datetime DEFAULT NULL,`utime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`delete_flag` tinyint DEFAULT NULL,`cby` bigint DEFAULT NULL,`uby` bigint DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

知识库表:

CREATE TABLE `rag_knowledge` (`id` bigint NOT NULL AUTO_INCREMENT,`code` varchar(255) NOT NULL,`embedding_store_id` bigint NOT NULL COMMENT '向量数据库id',`embedding_model_id` bigint NOT NULL COMMENT '向量模型id',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '知识库名称',`descr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '知识库描述',`ctime` datetime DEFAULT NULL,`utime` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,`delete_flag` tinyint NOT NULL,`cby` bigint DEFAULT NULL,`uby` bigint DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

文档表:

CREATE TABLE `rag_doc` (`id` bigint NOT NULL AUTO_INCREMENT,`code` varchar(255) NOT NULL,`knowledge_id` bigint NOT NULL COMMENT '知识库id',`name` varchar(255) NOT NULL COMMENT '文档名称',`path` varchar(255) NOT NULL COMMENT '文档路径',`url` varchar(255) NOT NULL COMMENT '文档url',`source` tinyint NOT NULL COMMENT '0:本地上传  1:网页',`size` int NOT NULL COMMENT '文档大小',`slice_num` int DEFAULT NULL COMMENT '切片数',`slice_status` tinyint DEFAULT NULL COMMENT '切片状态(0:未处理 , 1:已处理)',`ctime` datetime DEFAULT NULL,`utime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`delete_flag` tinyint DEFAULT NULL,`cby` tinyint DEFAULT NULL,`uby` tinyint DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

会话表:

CREATE TABLE `rag_message` (`id` bigint NOT NULL AUTO_INCREMENT,`user_id` bigint NOT NULL,`chat_id` bigint NOT NULL COMMENT '聊天id(每个会话一个id)',`user_name` varchar(255) NOT NULL COMMENT '用户名',`message` varchar(1000) DEFAULT NULL COMMENT '会话内容',`knowledge_id` bigint DEFAULT NULL COMMENT '知识库id',`model_id` bigint DEFAULT NULL COMMENT '模型id',`tokens` int DEFAULT NULL COMMENT '消耗的token数',`promote_tokens` int DEFAULT NULL COMMENT '请求token数',`ctime` datetime DEFAULT NULL,`utime` datetime DEFAULT NULL,`delete_flag` tinyint DEFAULT NULL,`cby` tinyint DEFAULT NULL,`uby` tinyint DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

基础框架搭建:

pom依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>studyLlm</artifactId><version>0.0.1-SNAPSHOT</version><name>studyLlm</name><description>studyLlm</description><url/><properties><java.version>17</java.version><langchain4j.version>0.35.0</langchain4j.version><mybatis.plus.version>3.4.3</mybatis.plus.version><mysql.connector.version>8.0.17</mysql.connector.version><mapstruct.version>1.2.0.Final</mapstruct.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><!-- langchain4j --><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-core</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-dashscope</artifactId><version>${langchain4j.version}</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId></exclusion></exclusions></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-redis</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-pgvector</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.5.8</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-embedding-store-filter-parser-sql</artifactId><version>${langchain4j.version}</version><exclusions><exclusion><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId></exclusion></exclusions></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-document-parser-apache-tika</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-pgvector</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-ollama</artifactId><version>${langchain4j.version}</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-reactor</artifactId><version>0.35.0</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency><!-- end langchain4j --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope></dependency><!--mybatis-plus 3.3.1.tmp--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis.plus.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-typehandlers-jsr310</artifactId><version>1.0.1</version></dependency><dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.8.7</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.connector.version}</version><scope>runtime</scope></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version><scope>compile</scope></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

统一返回格式设置:

        ResultEnum枚举


import lombok.AllArgsConstructor;
import lombok.Getter;/*** 返回code枚举* @author wang**/
@Getter
@AllArgsConstructor
public enum ResultEnum {// 成功SUCCESS(200, "SUCCESS"),// crud异常,4开头BAD_REQUEST(400, "BAD_REQUEST"),UN_AUTH(401, "UN_AUTH"),// crud异常,5开头// 默认错误ERROR(500, "ERROR"),DB_CONNECT_ERROR(501, "DB_CONNECT_ERROR");private Integer code;private String desc;}

        统一返回格式Result


import com.example.studyllm.enums.ResultEnum;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.io.Serializable;/*** 统一返回格式* @author wang* @param <T>*/
@Slf4j
@Data
@JsonInclude(JsonInclude.Include.ALWAYS)
public final class Result<T> implements Serializable {private static final long serialVersionUID = -5816713866887895850L;/*** 错误码*//*** 错误信息*/private String msg = null;private Integer code = ResultEnum.ERROR.getCode();private boolean success;/*** 返回结果实体*/private T data = null;public Result() {}public Result(int code, String msg, T data, boolean success) {this.code = code;this.msg = msg;this.data = data;this.success = success;}public static <T> Result<T> error(String msg) {log.debug("返回默认错误:, msg={}",  msg);return new Result<>(ResultEnum.ERROR.getCode(), msg, null,false);}public static <T> Result<T> error(){return error(ResultEnum.ERROR.getDesc());}public static <T> Result<T> error(String msg , int code){log.debug("返回默认错误:, msg={}",  msg);return new Result<>(code, msg, null,false);}public static Result<String> error(ResultEnum resultEnum) {log.debug("返回错误:code={}, msg={}", resultEnum.getCode(), resultEnum.getDesc());return new Result<>(resultEnum.getCode(), resultEnum.getDesc(), resultEnum.getDesc(),false);}public static <T> Result<T> error(ResultEnum resultEnum, String msg) {log.debug("返回错误:code={}, msg={}", resultEnum.getCode(), msg);return new Result<T>(resultEnum.getCode(), msg, null,false);}public static <T> Result<T> errorForData(ResultEnum resultEnum, T data) {log.debug("返回错误:code={}, msg={}, data={}", resultEnum.getCode(), resultEnum.getDesc(), data);return new Result<>(resultEnum.getCode(), resultEnum.getDesc(), data,false);}public static <T> Result<T> success(T data) {return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getDesc(), data,true);}public static  <T> Result<T> success(){return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getDesc(),null,true);}}

统一异常:

        业务异常类定义:

import com.example.studyllm.enums.ResultEnum;import java.text.MessageFormat;public class BusinessException extends RuntimeException {private static final long serialVersionUID = 1L;private Integer code;private ResultEnum enumType;public BusinessException(String msg) {super(msg);this.code = 500;}public BusinessException(Integer code , String msg){super(msg);this.code = code;}public BusinessException(ResultEnum baseEnumType) {super(baseEnumType.getDesc());this.code = baseEnumType.getCode();this.enumType = baseEnumType;}public BusinessException(String msg, Object... arguments) {super(MessageFormat.format(msg, arguments));this.code = 500;}public BusinessException(ResultEnum baseEnumType, Object... arguments) {super(MessageFormat.format(baseEnumType.getDesc(), arguments));this.code = baseEnumType.getCode();this.enumType = baseEnumType;}public ResultEnum getEnumType() {return enumType;}public void setEnumType(ResultEnum enumType) {this.enumType = enumType;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}
}

           统一异常处理类


import cn.hutool.core.util.StrUtil;
import com.example.studyllm.enums.ResultEnum;
import com.example.studyllm.vo.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.nio.file.AccessDeniedException;
import java.sql.SQLTransientConnectionException;
import java.util.List;/*** @author wk*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {@Value("${spring.profiles.active:dev}")private String active ;/*** 校验错误拦截处理** @param exception 错误信息集合* @return 错误信息*/@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.OK)public Result<String> validationBodyException(MethodArgumentNotValidException exception) {BindingResult result = exception.getBindingResult();String message = "";if (result.hasErrors()) {List<ObjectError> errors = result.getAllErrors();if (errors != null) {errors.forEach(p -> {FieldError fieldError = (FieldError) p;log.error("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +"},errorMessage{" + fieldError.getDefaultMessage() + "}");});if (errors.size() > 0) {FieldError fieldError = (FieldError) errors.get(0);message = fieldError.getDefaultMessage();}}}return Result.error("".equals(message) ? "请填写正确信息" : message);}/*** 业务错误拦截* @param exception* @return*/@ExceptionHandler(AccessDeniedException.class)@ResponseStatus(HttpStatus.OK)public Result<String> accessDeniedException(AccessDeniedException exception){log.error("无权限访问:", exception);return Result.error(ResultEnum.UN_AUTH);}/*** 业务错误拦截* @param exception* @return*/@ExceptionHandler(BusinessException.class)@ResponseStatus(HttpStatus.OK)public Result<String> businessException(BusinessException exception){if(exception.getEnumType()!=null){return Result.error(exception.getEnumType().getDesc());}log.error("捕获业务异常:", exception);if(StrUtil.isNotEmpty(exception.getMessage())){return Result.error(exception.getMessage());}return Result.error();}/*** IllegalArgumentException错误拦截* @param exception* @return*/@ExceptionHandler(IllegalArgumentException.class)@ResponseStatus(HttpStatus.OK)public Result<String> illegalArgumentException(IllegalArgumentException exception){log.error("捕获业务异常:", exception);return Result.error(exception.getMessage());}@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.OK)public Result<String> exception(Exception exception){log.error("globalException:", exception);if(active.equals("dev")){return Result.error();}return Result.error(exception.getMessage());}/*** 拦截捕获 @RequestBody required=true 绑定请求参数异常**/@ExceptionHandler(value = HttpMessageNotReadableException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<String> validExceptionHandler(HttpMessageNotReadableException ex) {log.error("", ex);return Result.error(ResultEnum.BAD_REQUEST,ResultEnum.BAD_REQUEST.getDesc());}/*** 拦截捕获 @RequestBody required=true 绑定请求参数异常**/@ExceptionHandler(value = BindException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<String> validExceptionHandler(BindException ex) {log.error("", ex);return Result.error(ResultEnum.BAD_REQUEST,ResultEnum.BAD_REQUEST.getDesc());}@ExceptionHandler(value = SQLTransientConnectionException.class)@ResponseStatus(HttpStatus.OK)public Result<String> cannotGetJdbcConnectionExceptionHandle(SQLTransientConnectionException ex){log.error("", ex);return Result.error(ResultEnum.DB_CONNECT_ERROR);}}

mybatis-plus配置:

        自动填充设置(用户还没做,先写死返回1)


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.example.studyllm.constants.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.util.ClassUtils;import java.nio.charset.Charset;
import java.time.LocalDateTime;/*** MybatisPlus 自动填充配置** @author L.cm*/
@Slf4j
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.debug("mybatis plus start insert fill ....");LocalDateTime now = LocalDateTime.now();// 审计字段自动填充fillValIfNullByName("ctime", now, metaObject, false);fillValIfNullByName("utime", now, metaObject, false);fillValIfNullByName("cby", getUserId(), metaObject, false);fillValIfNullByName("uby", getUserId(), metaObject, false);// 删除标记自动填充fillValIfNullByName("deleteFlag", CommonConstant.UN_DELETE_FLAG, metaObject, false);}@Overridepublic void updateFill(MetaObject metaObject) {log.debug("mybatis plus start update fill ....");fillValIfNullByName("utime", LocalDateTime.now(), metaObject, false);fillValIfNullByName("uby", getUserId(), metaObject, false);}/*** 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置* @param fieldName 属性名* @param fieldVal 属性值* @param metaObject MetaObject* @param isCover 是否覆盖原有值,避免更新操作手动入参*/private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {// 0. 如果填充值为空if (fieldVal == null) {return;}// 1. 没有 get 方法if (!metaObject.hasSetter(fieldName)) {return;}// 2. 如果用户有手动设置的值Object userSetValue = metaObject.getValue(fieldName);String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset());if (StrUtil.isNotBlank(setValueStr) && !isCover) {return;}// 3. field 类型相同时设置Class<?> getterType = metaObject.getGetterType(fieldName);if (ClassUtils.isAssignableValue(getterType, fieldVal)) {metaObject.setValue(fieldName, fieldVal);}}/*** 获取 spring security 当前的用户名* @return 当前用户名*/private Long getUserId() {return 1L;}}

        mybatis配置类


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.example.studyllm.constants.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Author kw* @Description 集成mybatisplus,注意扫包这里规定好**/
@Configuration
@Slf4j
public class MybatisPlusConfig implements ApplicationContextAware {private ApplicationContext applicationContext ;private final static Long MAX_LIMIT = Long.MAX_VALUE ;@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();scannerConfigurer.setBasePackage("com.example.studyllm.mapper");return scannerConfigurer;}@Beanpublic GlobalConfig globalConfig() {GlobalConfig globalConfig = new GlobalConfig();GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();dbConfig.setLogicDeleteField("delFlag").setLogicDeleteValue(String.valueOf(CommonConstant.DELETED_FLAG)).setLogicNotDeleteValue(String.valueOf(CommonConstant.UN_DELETE_FLAG));globalConfig.setDbConfig(dbConfig);return globalConfig;}/*** 审计字段自动填充* @return {@link MetaObjectHandler}*/@Beanpublic MybatisPlusMetaObjectHandler mybatisPlusMetaObjectHandler() {return new MybatisPlusMetaObjectHandler();}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext ;}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);paginationInnerInterceptor.setMaxLimit(MAX_LIMIT);//分页插件interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}
}

        yml配置

server:tomcat:uri-encoding: utf-8port: 8888
spring:application:name: studyllmmain:allow-bean-definition-overriding: truedatasource:driver-class-name: com.p6spy.engine.spy.P6SpyDriverurl: jdbc:p6spy:mysql://${MYSQL_URL:127.0.0.1:3306}/studyllm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&rewriteBatchedStatements=trueusername: ${MYSQL_USER_NAME:root}password: ${MYSQL_PASSWORD:root}type: com.zaxxer.hikari.HikariDataSourcehikari:register-mbeans: true# 最小连接minimum-idle: 5# 最大连接maximum-pool-size: 10# 自动提交auto-commit: true# 最大空闲时间idle-timeout: 30000# 连接池名称pool-name: DatebookHikariCP# 最大生命周期max-lifetime: 900000# 连接超时时间connection-timeout: 30000

好了,简单的开发框架搭好了,写不动了。。。

相关文章:

基于ollama,langchain,springboot从零搭建知识库四【设计通用rag系统】

需求&#xff1a; 1&#xff1a;可以自定义管理大模型&#xff0c;可自行选择ollama&#xff0c;openai&#xff0c;千问等大模型 2&#xff1a;自定义向量数据库&#xff0c;支持pgvector&#xff0c;elasticsearch&#xff0c;milvus&#xff08;这三个目前比较常用&#xff…...

【Go面试】工作经验篇 (持续整合)

这里写目录标题 什么是逃逸分析服务端怎么接受客户端上传的文件说一下对gin框架的理解gin有哪些常用中间件gin怎么用swagger写接口文档nginx一般是用来做什么如果调用方法经常超时怎么办gin中怎么和mysql通信从mysql调数据到redis,如何同步延时双删redis ,mysql都不存在用户请求…...

“腾讯、钉钉、飞书” 会议开源平替,免费功能强大

在数字化时代&#xff0c;远程办公和线上协作越来越火。然而&#xff0c;市面上的视频会议工具要么贵得离谱&#xff0c;要么功能受限&#xff0c;甚至还有些在数据安全和隐私保护上让人不放心。 今天开源君给大家安利一个超棒的开源项目 - Jitsi Meet&#xff0c;这可是我在网…...

怎样使用树莓派自己搭建一套ADS-B信号接收系统

0 我们知道&#xff0c;ADS-B全称广播式自动相关监视系统&#xff0c;其实就是飞机发出的广播信号&#xff0c;用明码来对外发送自己的位置、高度、速度、航向等信息&#xff0c;是公开信息。连续接收到一架飞机发出的ADS-B信息后&#xff0c;可以通过其坐标点来描绘出飞机的航…...

终极的复杂,是简单

软件仿真拥有最佳的信号可见性和调试灵活性,能够高效捕获很多显而易见的常见错误,被大多数工程师熟练使用。 空间领域应用的一套数据处理系统(Data Handling System),采用抗辐FPGA作为主处理器,片上资源只包含10752个寄存器,软仿也是个挺花时间的事。 Few ms might take …...

粒子群算法 笔记 数学建模

引入: 如何找到全局最大值&#xff1a;如果只是贪心的话&#xff0c;容易被局部最大解锁定 方法有&#xff1a;盲目搜索&#xff0c;启发式搜索 盲目搜索&#xff1a;枚举法和蒙特卡洛模拟&#xff0c;但是样例太多花费巨量时间 所以启发式算法就来了&#xff0c;通过经验和规…...

Vue.js 嵌套路由和动态路由

Vue.js 嵌套路由和动态路由 在 Vue.js 开发中&#xff0c;Vue Router 是官方提供的路由管理器&#xff0c;用于构建单页应用&#xff08;SPA&#xff09;。它支持嵌套路由和动态路由&#xff0c;帮助开发者构建复杂的应用结构。 嵌套路由 嵌套路由允许在路由配置中定义子路由…...

Docker导入镜像

使用命令行进行处理&#xff1a; docker load < onething1_wxedge.tar如下图所示 查看状态 docker images...

C# OpenCV机器视觉:红外体温检测

在一个骄阳似火的夏日&#xff0c;全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇&#xff0c;平日里熙熙攘攘的街道变得冷冷清清&#xff0c;人们戴着口罩&#xff0c;行色匆匆&#xff0c;眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人&#xff0c;看着这一…...

STM32项目分享:智能厨房安全检测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; STM32智能厨房安全检测系统 &#xff08;资料分…...

docker 安装 redis 详解

在平常的开发工作中&#xff0c;我们经常会用到 redis&#xff0c;那么 docker 下应该如何安装 redis 呢&#xff1f;简单来说&#xff1a;第一步&#xff1a;拉取redis镜像&#xff1b;第二步&#xff1a;设置 redis.conf 配置文件&#xff1b;第三步&#xff1a;编写 docker-…...

《探秘鸿蒙Next:人工智能助力元宇宙高效渲染新征程》

在元宇宙的宏大愿景中&#xff0c;高效的渲染技术是构建沉浸式虚拟世界的关键。鸿蒙Next凭借与人工智能的深度融合&#xff0c;为元宇宙的渲染带来了全新的解决方案和无限可能。 智能场景分析与优化 人工智能能够对元宇宙场景进行智能分析。鸿蒙Next可以利用AI技术对场景中的…...

nginx分发请求超时切换服务

nginx的upstream模块实现超时自动切换服务 upstream testfail {server 192.168.1.218 max_fails1 fail_timeout10s;server 192.168.1.129 max_fails1 fail_timeout10s;} max_fails代表失败尝试次数&#xff0c;达到设置的次数则视为该服务不可用&#xff0c; fail_timeout代…...

vulfocus/fastjson-cnvd_2017_02833复现

漏洞概述 Fastjson 是阿里巴巴开发的一个高性能的 Java 库&#xff0c;用于将 Java 对象转换成 JSON 格式&#xff08;序列化&#xff09;&#xff0c;以及将 JSON 字符串转换回 Java 对象&#xff08;反序列化&#xff09;。 fastjson在解析json的过程中,支持使用type字段来指…...

.Net Core微服务入门全纪录(五)——Ocelot-API网关(下)

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…...

OpenCV imread函数读取图像__实例详解

OpenCV imread函数读取图像__实例详解 本文目录&#xff1a; 零、时光宝盒 一、imread函数定义 二、imread函数支持的文件格式 三、imread函数flags参数详解 &#xff08;3.1&#xff09;、Flags-1时&#xff0c;样返回加载的图像&#xff08;使用alpha通道&#xff0c;否…...

GPSd定时检测保活TCP GPS源

为了在 TCP GPS 源丢失连接时自动重新连接&#xff0c;可以编写一个监控脚本&#xff0c;定期检查 gpspipe 输出中的 TCP 源数据是否存在。如果检测到丢失&#xff0c;则使用 gpsdctl 或直接命令重新添加 TCP 源。 1、工具 检查并安装必要工具&#xff0c;本例需要使用 gpspi…...

得物App亮相第七届进博会,科技赋能打造消费新热点

在2024年11月5日至11月10日举办的第七届进博会舞台上&#xff0c;上海交易团虹口分团表现亮眼&#xff0c;其中得物作为来自虹口品质电商的践行者&#xff0c;备受众多参观者关注。 上海得物信息集团有限公司自2015年于上海虹口创立以来&#xff0c;始终坚守“满足年轻人对美好…...

单片机内存管理剖析

一、概述 在单片机系统中&#xff0c;内存资源通常是有限的&#xff0c;因此高效的内存管理至关重要。合理地分配和使用内存可以提高系统的性能和稳定性&#xff0c;避免内存泄漏和碎片化问题。单片机的内存主要包括程序存储器&#xff08;如 Flash&#xff09;和数据存储器&a…...

用Python绘制一只懒羊羊

目录 一、准备工作 二、Turtle库简介 三、绘制懒羊羊的步骤 1. 导入Turtle库并设置画布 2. 绘制头部 3. 绘制眼睛 4. 绘制嘴巴 5. 绘制身体 6. 绘制四肢 7. 完成绘制 五、运行代码与结果展示 六、总结 在这个趣味盎然的技术实践中,我们将使用Python和Turtle图形…...

Python 预训练:打通视觉与大语言模型应用壁垒——Python预训练视觉和大语言模型

大语言模型是一种由包含数百亿甚至更多参数的深度神经网络构建的语言模型&#xff0c;通常使用自监督学习方法通过大量无标签文本进行训练&#xff0c;是深度学习之后的又一大人工智能技术革命。 大语言模型的发展主要经历了基础模型阶段(2018 年到2021年)、能力探索阶段(2019年…...

神经网络梯度爆炸的原因及解决方案

在深度学习中&#xff0c;梯度爆炸&#xff08;gradient exploding&#xff09;是一种常见的训练问题&#xff0c;尤其是在深层神经网络中。梯度爆炸指的是在反向传播过程中&#xff0c;梯度值呈指数级增长&#xff0c;导致网络权重的大幅更新&#xff0c;从而使得网络变得不稳…...

WPS不登录无法使用基本功能的解决方案

前言 WPS不登录无法使用基本功能的原因通常是为了同步数据、提供更多高级功能或满足软件授权要求。‌然而&#xff0c;一些用户可能出于隐私或便捷性的考虑&#xff0c;不愿意登录账号。在这种情况下&#xff0c;WPS可能会限制未登录用户的使用权限&#xff0c;导致工具栏变灰…...

蓝桥杯lesson3---string的使用

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” string的概念 string字符串是一种更加高级的封装&#xff0c;string字符串中包含了大量的方法&#xff0c;这些方法使得字符串的操作变得更加简单&#xff0c;string的使用&…...

Java设计模式 三 工厂方法模式 (Factory Method Pattern)

工厂方法模式 (Factory Method Pattern) 是一种常见的创建型设计模式&#xff0c;旨在通过定义一个接口来创建对象&#xff0c;而将实例化对象的具体类延迟到子类中。工厂方法模式允许客户端通过工厂方法来创建对象&#xff0c;而不需要直接调用构造函数&#xff0c;这样可以减…...

日志收集Day005

1.filebeat的input类型之filestream实战案例: 在7.16版本中已经弃用log类型,之后需要使用filebeat,与log不同&#xff0c;filebeat的message无需设置就是顶级字段 1.1简单使用&#xff1a; filebeat.inputs: - type: filestreamenabled: truepaths:- /tmp/myfilestream01.lo…...

java开发,IDEA转战VSCODE配置(mac)

一、基本java开发环境配置 前提&#xff1a;已经安装了jdk、maven、vscode&#xff0c;且配置了环境变量 1、安装java相关的插件 2、安装spring相关的插件 3、vscode配置maven环境 打开 VsCode -> 首选项 -> 设置&#xff0c;也可以在setting.json文件中直接编辑&…...

Effective C++读书笔记——item23(用非成员,非友元函数取代成员函数)

一、主要观点&#xff1a; 在某些情况下&#xff0c;使用 non-member、non-friend 函数来替换 member 函数可以增强封装性和可扩展性&#xff0c;提供更好的软件设计。 二、详细解释&#xff1a; 封装性&#xff1a; 类成员函数的封装性考量&#xff1a;成员函数可以访问类的…...

(3)STM32 USB设备开发-USB存储设备

例程&#xff1a;STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为使用芯片内部flash作为USB存储设备的例程&#xff0c;没有知识&#xff0c;全是实操&#xff0c;按照步骤就能获得一个STM32的U盘。本例子是在野火F103MINI开发板上验证的&#xff0c;如果代码…...

考研408笔记之数据结构(五)——图

数据结构&#xff08;五&#xff09;——图 1. 图的基本概念 1.1 图的定义 1.2 有向图和无向图 在有向图中&#xff0c;使用圆括号表示一条边&#xff0c;圆括号里元素位置互换没有影响。 在无向图中&#xff0c;使用尖括号表示一条边&#xff0c;尖括号里元素位置互换则表示…...

【博客之星】年度总结:在云影与墨香中探寻成长的足迹

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、年度回顾 1、创作历程 2、个人成长 3、个人生活与博客事业 二、技术总结 1、赛道选择 2、技术工具 3、实战项目 三、前景与展望 1、云原生未来…...

springboot 调用 c++生成的so库文件

一、创建c文件 SoTest.h #pragma once class SoTest {int Add(int a,int b); };SoTest.cpp #include "SoTest.h"int SoTest::Add(int a, int b) {return a b; }二、创建so文件 /home/ubuntu/projects/SoTest/bin/x64/Debug/libSoTest.so 三、java代码 Maven依…...

简识JVM栈帧中的操作数栈

在JVM&#xff08;Java虚拟机&#xff09;中&#xff0c;栈帧&#xff08;Stack Frame&#xff09;是方法执行时的数据结构&#xff0c;用于存储局部变量、操作数栈、方法返回地址等信息。 其中&#xff0c;操作数栈&#xff08;Operand Stack&#xff09;是栈帧中的一个重要组…...

在 Kubernetes 上快速安装 KubeSphere v4.1.2

目录标题 安装文档配置repo安装使用插件 安装文档 在 Kubernetes 上快速安装 KubeSphere 配置repo export https_proxy10.10.x.x:7890 helm repo add stable https://charts.helm.sh/stable helm repo update安装 helm upgrade --install -n kubesphere-system --create-name…...

腾讯 Hunyuan3D-2: 高分辨率3D 资产生成

腾讯 Hunyuan3D-2&#xff1a;高分辨率 3D 资产生成的突破 前言 在当今数字化时代&#xff0c;3D 资产生成技术正变得越来越重要。无论是游戏开发、影视制作还是虚拟现实领域&#xff0c;高质量的 3D 模型和纹理都是创造沉浸式体验的关键。然而&#xff0c;传统的 3D 资产制作…...

论文阅读--Qwen22.5技术报告

Qwen2 1 引言 所有模型都是在超过7 trillion token&#xff08;7万亿&#xff09;的高质量、大规模数据集上预训练的 2 Tokenizer & Model 2.1 Tokenizer 沿用Qwen&#xff08;Bai等人&#xff0c;2023a&#xff09;的做法&#xff0c;我们采用了基于字节级字节对编码…...

python如何导出数据到excel文件

python导出数据到excel文件的方法&#xff1a; 1、调用Workbook()对象中的add_sheet()方法 wb xlwt.Workbook() ws wb.add_sheet(A Test Sheet) 2、通过add_sheet()方法中的write()函数将数据写入到excel中&#xff0c;然后使用save()函数保存excel文件 ws.write(0, 0, 1234…...

pyhton学习笔记(三)

目录 1.变量 2.变量的命名规则 3.常用函数汇总 4.常用数据类型汇总 5.算术运算符 6.比较运算符和逻辑运算符 7.常见的三种格式化输出方法 8.分支语句 1.变量 变量就是可以变化的量&#xff0c;可以理解为是一个存储东西的盒子&#xff0c;盒子里面可以放一些程序里需要…...

时间类型数据处理:基于Python的datetime库和pandas库

一、datetime库常用方法 日期的数据类型主要有两种&#xff1a;一是包含时间的datetime类型&#xff0c;二是不包含时间的date类型。这里的时间指具体的时、分、秒、甚至毫秒。 1、自定义日期、时间、获取本地时间、获取本地日期、获取年份、月份、月号、小时、分钟、秒、星期…...

CPU 缓存基础知识

并发编程首先需要简单了解下现代CPU相关知识。通过一些简单的图&#xff0c;简单的代码&#xff0c;来认识CPU以及一些常见的问题。 目录 CPU存储与缓存的引入常见的三级缓存结构缓存一致性协议MESI协议缓存行 cache line 通过代码实例认识缓存行的重要性 CPU指令的乱序执行通过…...

vue3 中如何监听 props 中的值的变化

在 Vue 3 中&#xff0c;你可以使用 watch 函数来监听组件的 props 值的变化。watch 函数允许你观察一个或多个响应式数据源&#xff0c;并在这些数据源发生变化时执行回调函数。 以下是一个示例&#xff0c;展示了如何在 Vue 3 中使用 watch 来监听 props 中的值的变化&#…...

煤矿场景下矿工行为检测数据集VOC+YOLO格式24709张8类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;24709 标注数量(xml文件个数)&#xff1a;24709 标注数量(txt文件个数)&#xff1a;2470…...

Git处理冲突详解

文章目录 Git处理冲突详解一、引言二、冲突产生的原因三、解决冲突的步骤1. 手动解决冲突1.1 查看冲突文件1.2 编辑冲突文件1.3 提交解决冲突 2. 使用合并工具解决冲突 四、使用示例五、总结 Git处理冲突详解 一、引言 在团队协作开发中&#xff0c;Git冲突是不可避免的。当多…...

Jetson Orin Nano Super之jetson-fpv开源代码下载

Jetson Orin Nano Super之jetson-fpv开源代码下载 1. 源由2. 方法2.1 优化配置方案一&#xff1a;增加缓冲方案二&#xff1a;降低并发数方案三&#xff1a;临时禁用深度克隆 2.2 路径更换方案一&#xff1a;设置代理方案二&#xff1a;替换git协议方案三&#xff1a;替换https…...

gitlab使用多数据库

1. 说明 默认情况下&#xff0c;GitLab 使用一个单一的应用数据库&#xff0c;称为主数据库。为了扩展 GitLab&#xff0c;您可以将 GitLab 配置为使用多个应用数据库。 设置多个数据库后&#xff0c;GitLab 将使用第二个应用数据库用于 CI/CD 功能&#xff0c;称为 CI 数据库…...

【Redis】事务

前言&#xff1a; 对比MySQL事务:【MySQL篇】事务的认识以及四大特性-CSDN博客 弱化的原子性: redis 没有 "回滚机制". 只能做到这些操作 "批量执行". 不能做到 "一个失败就恢复到初始状态". 不保证一致性: 不涉及 "约束". 也没有…...

在vue3中使用datav完整引入时卡在加载页面的解决方法

文件修改 文件&#xff1a;node_modules/dataview\datav-vue3/package.json // "module": "./es/index.js","module": "./es/index.mjs", // 修改后使用完整引入&#xff0c;需要为datav配置文件添加相应方法 文件&#xff1a;node…...

WPA_cli P2P命令详解及使用

目录 通用命令 status scan scan_results add_network set_network enable_network reconfigure save_config quit P2P 相关命令 p2p_find p2p_peers p2p_connect [method] p2p_group_add [ssid=] [freq=] [ht40] [persistent] p2p_remove_client p2p_di…...

Kubernetes v1.28.0安装dashboard v2.6.1(k8s图形化操作界面)

准备工作 Kubernetes v1.28.0搭建教程请参考&#xff1a;Kubernetes v1.28.0集群快速搭建教程-CSDN博客 查看当前集群nodes都是ready状态 查看当前pods都是running状态 下载并修改配置文件 下载 recommended.yaml &#xff0c;下载好之后&#xff0c;进入文件编辑 下载地址…...

性能测试监控与诊断

我们依据一个HTTP请求处理的过程&#xff0c;采用主流的J2EE技术栈&#xff0c;如下图所示 1>用户的请求通过网卡传送到服务器&#xff08;中断信号&#xff09;&#xff0c;用户与服务器简历TCP/IP链接。也就是产说的TCP三次握手。既然是链接&#xff0c;就有限制&#xff…...