作者 dong

首页增加统计项,日志管理增加存入知识库功能,按钮管理增加字段code,日志管理增加提问方式字段

1 package org.jeecg.modules.airag.app.controller; 1 package org.jeecg.modules.airag.app.controller;
2 2
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
3 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 import com.baomidou.mybatisplus.core.metadata.IPage; 5 import com.baomidou.mybatisplus.core.metadata.IPage;
5 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -14,9 +15,13 @@ import org.jeecg.common.aspect.annotation.AutoLog; @@ -14,9 +15,13 @@ import org.jeecg.common.aspect.annotation.AutoLog;
14 import org.jeecg.common.system.base.controller.JeecgController; 15 import org.jeecg.common.system.base.controller.JeecgController;
15 import org.jeecg.common.system.query.QueryGenerator; 16 import org.jeecg.common.system.query.QueryGenerator;
16 import org.jeecg.modules.airag.app.config.DataSourceConfig; 17 import org.jeecg.modules.airag.app.config.DataSourceConfig;
  18 +import org.jeecg.modules.airag.app.entity.AiragButton;
17 import org.jeecg.modules.airag.app.entity.AiragLog; 19 import org.jeecg.modules.airag.app.entity.AiragLog;
  20 +import org.jeecg.modules.airag.app.entity.Embeddings;
18 import org.jeecg.modules.airag.app.entity.QuestionEmbedding; 21 import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
  22 +import org.jeecg.modules.airag.app.mapper.AiragButtonMapper;
19 import org.jeecg.modules.airag.app.service.IAiragLogService; 23 import org.jeecg.modules.airag.app.service.IAiragLogService;
  24 +import org.jeecg.modules.airag.app.service.IEmbeddingsService;
20 import org.jeecg.modules.airag.app.service.IQuestionEmbeddingService; 25 import org.jeecg.modules.airag.app.service.IQuestionEmbeddingService;
21 import org.jeecg.modules.airag.llm.entity.AiragKnowledge; 26 import org.jeecg.modules.airag.llm.entity.AiragKnowledge;
22 import org.jeecg.modules.airag.llm.entity.AiragModel; 27 import org.jeecg.modules.airag.llm.entity.AiragModel;
@@ -58,6 +63,11 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi @@ -58,6 +63,11 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
58 @Autowired 63 @Autowired
59 private IAiragKnowledgeService airagKnowledgeService; 64 private IAiragKnowledgeService airagKnowledgeService;
60 65
  66 + @Autowired
  67 + private IEmbeddingsService embeddingsService;
  68 +
  69 + @Autowired
  70 + private AiragButtonMapper airagButtonMapper;
61 /** 71 /**
62 * 分页列表查询 72 * 分页列表查询
63 * 73 *
@@ -92,10 +102,55 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi @@ -92,10 +102,55 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
92 for(AiragModel airagModel : list){ 102 for(AiragModel airagModel : list){
93 nameMap.put(airagModel.getId(), airagModel.getName()); 103 nameMap.put(airagModel.getId(), airagModel.getName());
94 } 104 }
  105 +
  106 +
  107 + // 收集所有需要查询的按钮名称
  108 + Set<String> buttonNames = new HashSet<>();
95 for (AiragLog log : pageList.getRecords()) { 109 for (AiragLog log : pageList.getRecords()) {
96 - String modelId = log.getModelId(); // 获取当前日志的 model_id  
97 - log.setName(nameMap.get(modelId)); // 从 nameMap 中匹配 name 110 + String modelId = log.getModelId();
  111 + log.setName(nameMap.get(modelId));
  112 +
  113 + // 收集快捷按钮提问的问题内容
  114 + if (log.getCodeType() == 1 && StringUtils.isNotBlank(log.getQuestion())) {
  115 + buttonNames.add(log.getQuestion());
  116 + }
  117 + }
  118 +
  119 + // 批量查询按钮code
  120 + Map<String, String> buttonCodeMap = new HashMap<>();
  121 + if (!buttonNames.isEmpty()) {
  122 + LambdaQueryWrapper<AiragButton> buttonWrapper = new LambdaQueryWrapper<>();
  123 + buttonWrapper.in(AiragButton::getButtonName, buttonNames);
  124 + List<AiragButton> buttons = airagButtonMapper.selectList(buttonWrapper);
  125 +
  126 + for (AiragButton button : buttons) {
  127 + buttonCodeMap.put(button.getButtonName(), button.getCode());
98 } 128 }
  129 + }
  130 +
  131 + // 设置按钮code
  132 + for (AiragLog log : pageList.getRecords()) {
  133 + if (log.getCodeType() == 0) {
  134 + // 输入框提问,按钮code为空
  135 + log.setCode(null);
  136 + } else if (log.getCodeType() == 1) {
  137 + // 快捷按钮提问
  138 + if (StringUtils.isNotBlank(log.getQuestion())) {
  139 + String code = buttonCodeMap.get(log.getQuestion());
  140 + if (StringUtils.isNotBlank(code)) {
  141 + log.setCode(code);
  142 + airagLogService.updateById(log);
  143 + } else {
  144 + // 未找到匹配按钮
  145 + log.setCode("INPUT_QUESTION");
  146 + }
  147 + } else {
  148 + log.setCode(null);
  149 + }
  150 + }
  151 + }
  152 +
  153 +
99 return Result.OK(pageList); 154 return Result.OK(pageList);
100 } 155 }
101 156
@@ -156,7 +211,7 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi @@ -156,7 +211,7 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
156 211
157 212
158 /** 213 /**
159 - * 添加到知识 214 + * 添加到问题
160 * 215 *
161 * @param airagLog 216 * @param airagLog
162 * @return 217 * @return
@@ -182,6 +237,34 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi @@ -182,6 +237,34 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
182 return Result.OK("存入问题库成功!"); 237 return Result.OK("存入问题库成功!");
183 } 238 }
184 239
  240 +
  241 + /**
  242 + * 添加到知识库
  243 + *
  244 + * @param airagLog
  245 + * @return
  246 + */
  247 + @AutoLog(value = "日志管理-存入知识库")
  248 + @Operation(summary = "日志管理-存入知识库")
  249 + @RequiresPermissions("airaglog:airag_log:saveToEmbeddingLibrary")
  250 + @PostMapping(value = "/saveToEmbeddingLibrary")
  251 + public Result<String> saveToEmbeddingLibrary(@RequestBody AiragLog airagLog) {
  252 + Embeddings embeddings = new Embeddings();
  253 + embeddings.setText(airagLog.getAnswer());
  254 + int embdeddingCount = embeddingsService.findEmbeddingCount(embeddings);
  255 + if(embdeddingCount > 0){
  256 + return Result.error("重复回答不能存入");
  257 + }
  258 +
  259 + airagLog.setIfSaveKnowledge(1);
  260 + try {
  261 + airagLogService.saveToEmbeddingLibrary(airagLog);
  262 + }catch (Exception e){
  263 + e.printStackTrace();
  264 + }
  265 + return Result.OK("存入知识库成功!");
  266 + }
  267 +
185 /** 268 /**
186 * 编辑 269 * 编辑
187 * 270 *
@@ -269,4 +352,13 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi @@ -269,4 +352,13 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
269 return super.importExcel(request, response, AiragLog.class); 352 return super.importExcel(request, response, AiragLog.class);
270 } 353 }
271 354
  355 +
  356 +
  357 + @AutoLog(value = "日志管理-获取统计信息")
  358 + @Operation(summary="日志管理-获取统计信息")
  359 + @GetMapping(value = "/getStatistics")
  360 + public Result<Map<String, Object>> getStatistics() {
  361 + Map<String, Object> result = airagLogService.getStatistics();
  362 + return Result.OK(result);
  363 + }
272 } 364 }
1 package org.jeecg.modules.airag.app.entity; 1 package org.jeecg.modules.airag.app.entity;
2 2
3 import com.baomidou.mybatisplus.annotation.IdType; 3 import com.baomidou.mybatisplus.annotation.IdType;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
4 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
5 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
6 import com.fasterxml.jackson.annotation.JsonFormat; 7 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -64,4 +65,11 @@ public class AiragButton implements Serializable { @@ -64,4 +65,11 @@ public class AiragButton implements Serializable {
64 @Excel(name = "按钮值", width = 15) 65 @Excel(name = "按钮值", width = 15)
65 @Schema(description = "按钮值") 66 @Schema(description = "按钮值")
66 private String buttonValues; 67 private String buttonValues;
  68 +
  69 + /**
  70 + * 按钮code
  71 + */
  72 + @Excel(name = "按钮code", width = 15)
  73 + @TableField(value = "code")
  74 + private String code;
67 } 75 }
@@ -85,12 +85,32 @@ public class AiragLog implements Serializable { @@ -85,12 +85,32 @@ public class AiragLog implements Serializable {
85 @Schema(description = "回答方式:1:问题库回答 2:模型回答 3:未命中") 85 @Schema(description = "回答方式:1:问题库回答 2:模型回答 3:未命中")
86 private int answerType; 86 private int answerType;
87 /** 87 /**
88 - * 回答方式 88 + * 提问方式
  89 + */
  90 + @Excel(name = "提问方式", width = 15)
  91 + @TableField("code_type")
  92 + @Schema(description = "提问方式:0:输入框提问 ,1:快捷按钮提问")
  93 + private int codeType;
  94 + /**
  95 + * 按钮code
  96 + */
  97 + @Excel(name = "按钮code", width = 15)
  98 + @TableField(value = "code")
  99 + private String code;
  100 + /**
  101 + * 存入问题库
89 */ 102 */
90 @Excel(name = "是否存入问题库", width = 15) 103 @Excel(name = "是否存入问题库", width = 15)
91 @TableField("is_storage") 104 @TableField("is_storage")
92 @Schema(description = "是否存入问题库 0:否 1:是") 105 @Schema(description = "是否存入问题库 0:否 1:是")
93 private int isStorage; 106 private int isStorage;
  107 + /**
  108 + * 存入知识库
  109 + */
  110 + @Excel(name = "是否存入知识库", width = 15)
  111 + @TableField("if_save_knowledge")
  112 + @Schema(description = "是否存入知识库 0:否 1:是")
  113 + private int ifSaveKnowledge;
94 114
95 // 新增:临时字段(非数据库字段) 115 // 新增:临时字段(非数据库字段)
96 @TableField(exist = false) // MyBatis-Plus 标记该字段不存在于数据库表中 116 @TableField(exist = false) // MyBatis-Plus 标记该字段不存在于数据库表中
@@ -7,6 +7,7 @@ import io.lettuce.core.dynamic.annotation.Param; @@ -7,6 +7,7 @@ import io.lettuce.core.dynamic.annotation.Param;
7 import org.jeecg.modules.airag.app.entity.AiragLog; 7 import org.jeecg.modules.airag.app.entity.AiragLog;
8 8
9 import java.util.List; 9 import java.util.List;
  10 +import java.util.Map;
10 11
11 /** 12 /**
12 * @Description: 日志管理 13 * @Description: 日志管理
@@ -21,4 +22,9 @@ public interface AiragLogMapper extends BaseMapper<AiragLog> { @@ -21,4 +22,9 @@ public interface AiragLogMapper extends BaseMapper<AiragLog> {
21 22
22 int updataIsStorage(@Param("param1") int isStorage, @Param("param2") String id); 23 int updataIsStorage(@Param("param1") int isStorage, @Param("param2") String id);
23 24
  25 + int updataIfSaveKnowledge(@Param("param1") int ifSaveKnowledge, @Param("param2") String id);
  26 +
  27 + List<Map<String, Object>> getButtonRankList();
  28 +
  29 + List<Map<String, Object>> getMonthlyCount();
24 } 30 }
@@ -279,7 +279,6 @@ public class QuestionEmbeddingMapper { @@ -279,7 +279,6 @@ public class QuestionEmbeddingMapper {
279 // 2. 获取问题的嵌入向量 279 // 2. 获取问题的嵌入向量
280 Response<Embedding> embeddingResponse = aiModelUtils.getEmbedding(embedId, question); 280 Response<Embedding> embeddingResponse = aiModelUtils.getEmbedding(embedId, question);
281 float[] queryVector = embeddingResponse.content().vector(); 281 float[] queryVector = embeddingResponse.content().vector();
282 -  
283 // 3. 计算最大允许距离(1 - 相似度阈值) 282 // 3. 计算最大允许距离(1 - 相似度阈值)
284 double maxDistance = 1 - minSimilarity; 283 double maxDistance = 1 - minSimilarity;
285 284
@@ -12,7 +12,8 @@ @@ -12,7 +12,8 @@
12 select 12 select
13 id, create_by, create_time, 13 id, create_by, create_time,
14 update_by, update_time, question, 14 update_by, update_time, question,
15 - answer, model_id, answer_type, is_storage 15 + answer, model_id, answer_type, is_storage, if_save_knowledge,
  16 + code_type, code
16 from airag_log 17 from airag_log
17 where 1=1 18 where 1=1
18 <if test="param1.isStorage != null and param1.isStorage != -1"> 19 <if test="param1.isStorage != null and param1.isStorage != -1">
@@ -38,4 +39,31 @@ @@ -38,4 +39,31 @@
38 set is_storage = #{isStorage} 39 set is_storage = #{isStorage}
39 where id = #{id} 40 where id = #{id}
40 </update> 41 </update>
  42 +
  43 + <update id="updataIfSaveKnowledge">
  44 + update airag_log
  45 + set if_save_knowledge = #{ifSaveKnowledge}
  46 + where id = #{id}
  47 + </update>
  48 +
  49 +
  50 + <select id="getMonthlyCount" resultType="java.util.Map">
  51 + SELECT
  52 + DATE_FORMAT(create_time, '%Y-%m') AS month,
  53 + COUNT(*) AS count
  54 + FROM airag_log
  55 + WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
  56 + GROUP BY DATE_FORMAT(create_time, '%Y-%m')
  57 + ORDER BY month ASC
  58 + </select>
  59 +
  60 + <select id="getButtonRankList" resultType="java.util.Map">
  61 + SELECT
  62 + question, COUNT(*) as count
  63 + FROM airag_log
  64 + WHERE code IS NOT NULL AND code != ''
  65 + GROUP BY question
  66 + ORDER BY count DESC
  67 + LIMIT 7
  68 + </select>
41 </mapper> 69 </mapper>
@@ -9,6 +9,7 @@ import org.apache.poi.ss.formula.functions.T; @@ -9,6 +9,7 @@ import org.apache.poi.ss.formula.functions.T;
9 import org.jeecg.modules.airag.app.entity.AiragLog; 9 import org.jeecg.modules.airag.app.entity.AiragLog;
10 10
11 import java.util.List; 11 import java.util.List;
  12 +import java.util.Map;
12 13
13 /** 14 /**
14 * @Description: 日志管理 15 * @Description: 日志管理
@@ -20,9 +21,13 @@ public interface IAiragLogService extends IService<AiragLog> { @@ -20,9 +21,13 @@ public interface IAiragLogService extends IService<AiragLog> {
20 // List<AiragLog> getLogListWithModelName(); 21 // List<AiragLog> getLogListWithModelName();
21 void saveToQuestionLibrary(AiragLog log) throws JsonProcessingException; 22 void saveToQuestionLibrary(AiragLog log) throws JsonProcessingException;
22 23
  24 + void saveToEmbeddingLibrary(AiragLog log) throws JsonProcessingException;
  25 +
23 IPage<AiragLog> list1(AiragLog airagLog,Page<AiragLog> page); 26 IPage<AiragLog> list1(AiragLog airagLog,Page<AiragLog> page);
24 27
25 IPage<AiragLog> pageList(AiragLog airagLog, Page<AiragLog> page); 28 IPage<AiragLog> pageList(AiragLog airagLog, Page<AiragLog> page);
26 29
  30 + Map<String, Object> getStatistics();
  31 +
27 // List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper); 32 // List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper);
28 } 33 }
@@ -4,6 +4,7 @@ package org.jeecg.modules.airag.app.service; @@ -4,6 +4,7 @@ package org.jeecg.modules.airag.app.service;
4 4
5 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6 import org.jeecg.modules.airag.app.entity.Embeddings; 6 import org.jeecg.modules.airag.app.entity.Embeddings;
  7 +import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
7 8
8 import java.util.ArrayList; 9 import java.util.ArrayList;
9 import java.util.List; 10 import java.util.List;
@@ -22,4 +23,6 @@ public interface IEmbeddingsService { @@ -22,4 +23,6 @@ public interface IEmbeddingsService {
22 int update(Embeddings record); 23 int update(Embeddings record);
23 Embeddings findById(String id); 24 Embeddings findById(String id);
24 int removeByIds(List<String> ids); 25 int removeByIds(List<String> ids);
  26 +
  27 + Integer findEmbeddingCount(Embeddings embeddings);
25 } 28 }
1 package org.jeecg.modules.airag.app.service.impl; 1 package org.jeecg.modules.airag.app.service.impl;
2 2
3 import cn.hutool.core.lang.generator.SnowflakeGenerator; 3 import cn.hutool.core.lang.generator.SnowflakeGenerator;
  4 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 import com.baomidou.mybatisplus.core.metadata.IPage; 6 import com.baomidou.mybatisplus.core.metadata.IPage;
6 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,11 +10,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; @@ -9,11 +10,13 @@ import com.fasterxml.jackson.core.JsonProcessingException;
9 import com.fasterxml.jackson.databind.ObjectMapper; 10 import com.fasterxml.jackson.databind.ObjectMapper;
10 import com.fasterxml.jackson.databind.util.ObjectBuffer; 11 import com.fasterxml.jackson.databind.util.ObjectBuffer;
11 import io.minio.messages.Metadata; 12 import io.minio.messages.Metadata;
  13 +import org.apache.commons.lang3.StringUtils;
12 import org.apache.poi.ss.formula.functions.T; 14 import org.apache.poi.ss.formula.functions.T;
  15 +import org.jeecg.modules.airag.app.entity.AiragButton;
13 import org.jeecg.modules.airag.app.entity.AiragLog; 16 import org.jeecg.modules.airag.app.entity.AiragLog;
  17 +import org.jeecg.modules.airag.app.entity.Embeddings;
14 import org.jeecg.modules.airag.app.entity.QuestionEmbedding; 18 import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
15 -import org.jeecg.modules.airag.app.mapper.AiragLogMapper;  
16 -import org.jeecg.modules.airag.app.mapper.QuestionEmbeddingMapper; 19 +import org.jeecg.modules.airag.app.mapper.*;
17 import org.jeecg.modules.airag.app.service.IAiragLogService; 20 import org.jeecg.modules.airag.app.service.IAiragLogService;
18 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; 22 import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
@@ -36,6 +39,12 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i @@ -36,6 +39,12 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
36 private QuestionEmbeddingMapper questionEmbeddingMapper; 39 private QuestionEmbeddingMapper questionEmbeddingMapper;
37 40
38 @Autowired 41 @Autowired
  42 + private AiragButtonMapper airagButtonMapper;
  43 +
  44 + @Autowired
  45 + private PgVectorMapper pgVectorMapper;
  46 +
  47 + @Autowired
39 private AiragLogMapper airagLogMapper; 48 private AiragLogMapper airagLogMapper;
40 49
41 50
@@ -60,7 +69,24 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i @@ -60,7 +69,24 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
60 questionEmbedding.setMetadata(metadataJson); 69 questionEmbedding.setMetadata(metadataJson);
61 questionEmbeddingMapper.insert(questionEmbedding); 70 questionEmbeddingMapper.insert(questionEmbedding);
62 airagLogMapper.updataIsStorage(log.getIsStorage(),log.getId()); 71 airagLogMapper.updataIsStorage(log.getIsStorage(),log.getId());
  72 + System.out.println("1");
  73 + }
63 74
  75 + @Override
  76 + public void saveToEmbeddingLibrary(AiragLog log) throws JsonProcessingException {
  77 + // 这里实现将问题和回答存入问题库数据表的逻辑
  78 + // 假设问题库数据表的实体类为 QuestionLibrary,Mapper 接口为 QuestionLibraryMapper
  79 + Embeddings embeddings = new Embeddings();
  80 + embeddings.setText(log.getAnswer());
  81 + embeddings.setKnowledgeId(log.getKnowledgeId());
  82 + Map<String, Object> metadata = new LinkedHashMap<>();
  83 + metadata.put("title", "");
  84 + metadata.put("docName", "");
  85 + metadata.put("knowledgeId", embeddings.getKnowledgeId());
  86 + metadata.put("storedFileName", ""); // 自动生成唯一文档ID
  87 + embeddings.setMetadata(metadata);
  88 + pgVectorMapper.insert(embeddings);
  89 + airagLogMapper.updataIfSaveKnowledge(log.getIfSaveKnowledge(),log.getId());
64 } 90 }
65 91
66 @Override 92 @Override
@@ -73,6 +99,69 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i @@ -73,6 +99,69 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
73 return airagLogMapper.pageList(airagLog,page); 99 return airagLogMapper.pageList(airagLog,page);
74 } 100 }
75 101
  102 +
  103 + @Override
  104 + public Map<String, Object> getStatistics() {
  105 + Map<String, Object> result = new HashMap<>();
  106 +
  107 + // 1. 获取今日问答次数
  108 + QueryWrapper<AiragLog> todayWrapper = new QueryWrapper<>();
  109 + todayWrapper.apply("DATE(create_time) = CURDATE()");
  110 + long todayCount = this.count(todayWrapper);
  111 +
  112 + // 2. 获取昨日问答次数
  113 + QueryWrapper<AiragLog> yesterdayWrapper = new QueryWrapper<>();
  114 + yesterdayWrapper.apply("DATE(create_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)");
  115 + long yesterdayCount = this.count(yesterdayWrapper);
  116 +
  117 + // 3. 计算日增长率
  118 + double growthRate = 0.0;
  119 + if (yesterdayCount > 0) {
  120 + growthRate = ((double)(todayCount - yesterdayCount) / yesterdayCount) * 100;
  121 + } else if (todayCount > 0) {
  122 + // 昨天为0,今天有数据,则增长率为100%
  123 + growthRate = 100.0;
  124 + }
  125 +
  126 + // 4. 获取拒绝回答次数
  127 + QueryWrapper<AiragLog> rejectedWrapper = new QueryWrapper<>();
  128 + rejectedWrapper.eq("answer_type", 3); // 假设3表示拒绝回答
  129 + long rejectedCount = this.count(rejectedWrapper);
  130 +
  131 + // 5. 获取累计问答次数
  132 + long totalCount = this.count();
  133 +
  134 + // 6. 计算平均问答次数(基于有记录的天数)
  135 + QueryWrapper<AiragLog> distinctDaysWrapper = new QueryWrapper<>();
  136 + distinctDaysWrapper.select("DISTINCT DATE(create_time)");
  137 + long distinctDays = this.count(distinctDaysWrapper);
  138 +
  139 + double averageCount = 0.0;
  140 + if (distinctDays > 0) {
  141 + averageCount = (double) totalCount / distinctDays;
  142 + // 保留两位小数
  143 + averageCount = Math.round(averageCount * 100.0) / 100.0;
  144 + }
  145 +
  146 + // 7.获取按钮问题和按钮code次数,只获取有按钮code的问题(log.question)
  147 + List<Map<String, Object>> buttonStats = airagLogMapper.getButtonRankList();
  148 +
  149 + // 8. 获取最近12个月的月度数据
  150 + List<Map<String, Object>> monthlyData = airagLogMapper.getMonthlyCount();
  151 +
  152 + // 9. 添加前一天数据
  153 + result.put("yesterdayCount", yesterdayCount);
  154 + result.put("growthRate", Math.round(growthRate * 100.0) / 100.0); // 保留两位小数
  155 + result.put("todayCount", todayCount);
  156 + result.put("rejectedCount", rejectedCount);
  157 + result.put("totalCount", totalCount);
  158 + result.put("averageCount", averageCount);
  159 + result.put("buttonStats", buttonStats);
  160 + result.put("monthlyData", monthlyData);
  161 +
  162 + return result;
  163 + }
  164 +
76 /* @Override 165 /* @Override
77 public List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper) { 166 public List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper) {
78 167
@@ -2,6 +2,7 @@ package org.jeecg.modules.airag.app.service.impl; @@ -2,6 +2,7 @@ package org.jeecg.modules.airag.app.service.impl;
2 2
3 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 3 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
4 import org.jeecg.modules.airag.app.entity.Embeddings; 4 import org.jeecg.modules.airag.app.entity.Embeddings;
  5 +import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
5 import org.jeecg.modules.airag.app.mapper.PgVectorMapper; 6 import org.jeecg.modules.airag.app.mapper.PgVectorMapper;
6 import org.jeecg.modules.airag.app.service.IEmbeddingsService; 7 import org.jeecg.modules.airag.app.service.IEmbeddingsService;
7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,6 +26,11 @@ public class IEmbeddingsServiceImpl implements IEmbeddingsService { @@ -25,6 +26,11 @@ public class IEmbeddingsServiceImpl implements IEmbeddingsService {
25 return pgVectorMapper.findAll(embeddings,pageNo,pageSize); 26 return pgVectorMapper.findAll(embeddings,pageNo,pageSize);
26 } 27 }
27 28
  29 + @Override
  30 + public Integer findEmbeddingCount(Embeddings embeddings) {
  31 + return pgVectorMapper.findEmbeddingCount(embeddings);
  32 + }
  33 +
28 public int deleteById(String id) { 34 public int deleteById(String id) {
29 return pgVectorMapper.deleteById(id); 35 return pgVectorMapper.deleteById(id);
30 } 36 }