作者 dong

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

package org.jeecg.modules.airag.app.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
... ... @@ -14,9 +15,13 @@ import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.airag.app.config.DataSourceConfig;
import org.jeecg.modules.airag.app.entity.AiragButton;
import org.jeecg.modules.airag.app.entity.AiragLog;
import org.jeecg.modules.airag.app.entity.Embeddings;
import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
import org.jeecg.modules.airag.app.mapper.AiragButtonMapper;
import org.jeecg.modules.airag.app.service.IAiragLogService;
import org.jeecg.modules.airag.app.service.IEmbeddingsService;
import org.jeecg.modules.airag.app.service.IQuestionEmbeddingService;
import org.jeecg.modules.airag.llm.entity.AiragKnowledge;
import org.jeecg.modules.airag.llm.entity.AiragModel;
... ... @@ -58,6 +63,11 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
@Autowired
private IAiragKnowledgeService airagKnowledgeService;
@Autowired
private IEmbeddingsService embeddingsService;
@Autowired
private AiragButtonMapper airagButtonMapper;
/**
* 分页列表查询
*
... ... @@ -92,10 +102,55 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
for(AiragModel airagModel : list){
nameMap.put(airagModel.getId(), airagModel.getName());
}
// 收集所有需要查询的按钮名称
Set<String> buttonNames = new HashSet<>();
for (AiragLog log : pageList.getRecords()) {
String modelId = log.getModelId(); // 获取当前日志的 model_id
log.setName(nameMap.get(modelId)); // 从 nameMap 中匹配 name
String modelId = log.getModelId();
log.setName(nameMap.get(modelId));
// 收集快捷按钮提问的问题内容
if (log.getCodeType() == 1 && StringUtils.isNotBlank(log.getQuestion())) {
buttonNames.add(log.getQuestion());
}
}
// 批量查询按钮code
Map<String, String> buttonCodeMap = new HashMap<>();
if (!buttonNames.isEmpty()) {
LambdaQueryWrapper<AiragButton> buttonWrapper = new LambdaQueryWrapper<>();
buttonWrapper.in(AiragButton::getButtonName, buttonNames);
List<AiragButton> buttons = airagButtonMapper.selectList(buttonWrapper);
for (AiragButton button : buttons) {
buttonCodeMap.put(button.getButtonName(), button.getCode());
}
}
// 设置按钮code
for (AiragLog log : pageList.getRecords()) {
if (log.getCodeType() == 0) {
// 输入框提问,按钮code为空
log.setCode(null);
} else if (log.getCodeType() == 1) {
// 快捷按钮提问
if (StringUtils.isNotBlank(log.getQuestion())) {
String code = buttonCodeMap.get(log.getQuestion());
if (StringUtils.isNotBlank(code)) {
log.setCode(code);
airagLogService.updateById(log);
} else {
// 未找到匹配按钮
log.setCode("INPUT_QUESTION");
}
} else {
log.setCode(null);
}
}
}
return Result.OK(pageList);
}
... ... @@ -156,7 +211,7 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
/**
* 添加到知识
* 添加到问题
*
* @param airagLog
* @return
... ... @@ -182,6 +237,34 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
return Result.OK("存入问题库成功!");
}
/**
* 添加到知识库
*
* @param airagLog
* @return
*/
@AutoLog(value = "日志管理-存入知识库")
@Operation(summary = "日志管理-存入知识库")
@RequiresPermissions("airaglog:airag_log:saveToEmbeddingLibrary")
@PostMapping(value = "/saveToEmbeddingLibrary")
public Result<String> saveToEmbeddingLibrary(@RequestBody AiragLog airagLog) {
Embeddings embeddings = new Embeddings();
embeddings.setText(airagLog.getAnswer());
int embdeddingCount = embeddingsService.findEmbeddingCount(embeddings);
if(embdeddingCount > 0){
return Result.error("重复回答不能存入");
}
airagLog.setIfSaveKnowledge(1);
try {
airagLogService.saveToEmbeddingLibrary(airagLog);
}catch (Exception e){
e.printStackTrace();
}
return Result.OK("存入知识库成功!");
}
/**
* 编辑
*
... ... @@ -269,4 +352,13 @@ public class AiragLogController extends JeecgController<AiragLog, IAiragLogServi
return super.importExcel(request, response, AiragLog.class);
}
@AutoLog(value = "日志管理-获取统计信息")
@Operation(summary="日志管理-获取统计信息")
@GetMapping(value = "/getStatistics")
public Result<Map<String, Object>> getStatistics() {
Map<String, Object> result = airagLogService.getStatistics();
return Result.OK(result);
}
}
... ...
package org.jeecg.modules.airag.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
... ... @@ -64,4 +65,11 @@ public class AiragButton implements Serializable {
@Excel(name = "按钮值", width = 15)
@Schema(description = "按钮值")
private String buttonValues;
/**
* 按钮code
*/
@Excel(name = "按钮code", width = 15)
@TableField(value = "code")
private String code;
}
... ...
... ... @@ -85,12 +85,32 @@ public class AiragLog implements Serializable {
@Schema(description = "回答方式:1:问题库回答 2:模型回答 3:未命中")
private int answerType;
/**
* 回答方式
* 提问方式
*/
@Excel(name = "提问方式", width = 15)
@TableField("code_type")
@Schema(description = "提问方式:0:输入框提问 ,1:快捷按钮提问")
private int codeType;
/**
* 按钮code
*/
@Excel(name = "按钮code", width = 15)
@TableField(value = "code")
private String code;
/**
* 存入问题库
*/
@Excel(name = "是否存入问题库", width = 15)
@TableField("is_storage")
@Schema(description = "是否存入问题库 0:否 1:是")
private int isStorage;
/**
* 存入知识库
*/
@Excel(name = "是否存入知识库", width = 15)
@TableField("if_save_knowledge")
@Schema(description = "是否存入知识库 0:否 1:是")
private int ifSaveKnowledge;
// 新增:临时字段(非数据库字段)
@TableField(exist = false) // MyBatis-Plus 标记该字段不存在于数据库表中
... ...
... ... @@ -7,6 +7,7 @@ import io.lettuce.core.dynamic.annotation.Param;
import org.jeecg.modules.airag.app.entity.AiragLog;
import java.util.List;
import java.util.Map;
/**
* @Description: 日志管理
... ... @@ -21,4 +22,9 @@ public interface AiragLogMapper extends BaseMapper<AiragLog> {
int updataIsStorage(@Param("param1") int isStorage, @Param("param2") String id);
int updataIfSaveKnowledge(@Param("param1") int ifSaveKnowledge, @Param("param2") String id);
List<Map<String, Object>> getButtonRankList();
List<Map<String, Object>> getMonthlyCount();
}
... ...
... ... @@ -279,7 +279,6 @@ public class QuestionEmbeddingMapper {
// 2. 获取问题的嵌入向量
Response<Embedding> embeddingResponse = aiModelUtils.getEmbedding(embedId, question);
float[] queryVector = embeddingResponse.content().vector();
// 3. 计算最大允许距离(1 - 相似度阈值)
double maxDistance = 1 - minSimilarity;
... ...
... ... @@ -12,7 +12,8 @@
select
id, create_by, create_time,
update_by, update_time, question,
answer, model_id, answer_type, is_storage
answer, model_id, answer_type, is_storage, if_save_knowledge,
code_type, code
from airag_log
where 1=1
<if test="param1.isStorage != null and param1.isStorage != -1">
... ... @@ -38,4 +39,31 @@
set is_storage = #{isStorage}
where id = #{id}
</update>
<update id="updataIfSaveKnowledge">
update airag_log
set if_save_knowledge = #{ifSaveKnowledge}
where id = #{id}
</update>
<select id="getMonthlyCount" resultType="java.util.Map">
SELECT
DATE_FORMAT(create_time, '%Y-%m') AS month,
COUNT(*) AS count
FROM airag_log
WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY DATE_FORMAT(create_time, '%Y-%m')
ORDER BY month ASC
</select>
<select id="getButtonRankList" resultType="java.util.Map">
SELECT
question, COUNT(*) as count
FROM airag_log
WHERE code IS NOT NULL AND code != ''
GROUP BY question
ORDER BY count DESC
LIMIT 7
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -9,6 +9,7 @@ import org.apache.poi.ss.formula.functions.T;
import org.jeecg.modules.airag.app.entity.AiragLog;
import java.util.List;
import java.util.Map;
/**
* @Description: 日志管理
... ... @@ -20,9 +21,13 @@ public interface IAiragLogService extends IService<AiragLog> {
// List<AiragLog> getLogListWithModelName();
void saveToQuestionLibrary(AiragLog log) throws JsonProcessingException;
void saveToEmbeddingLibrary(AiragLog log) throws JsonProcessingException;
IPage<AiragLog> list1(AiragLog airagLog,Page<AiragLog> page);
IPage<AiragLog> pageList(AiragLog airagLog, Page<AiragLog> page);
Map<String, Object> getStatistics();
// List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper);
}
... ...
... ... @@ -4,6 +4,7 @@ package org.jeecg.modules.airag.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.modules.airag.app.entity.Embeddings;
import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
import java.util.ArrayList;
import java.util.List;
... ... @@ -22,4 +23,6 @@ public interface IEmbeddingsService {
int update(Embeddings record);
Embeddings findById(String id);
int removeByIds(List<String> ids);
Integer findEmbeddingCount(Embeddings embeddings);
}
... ...
package org.jeecg.modules.airag.app.service.impl;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
... ... @@ -9,11 +10,13 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ObjectBuffer;
import io.minio.messages.Metadata;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.jeecg.modules.airag.app.entity.AiragButton;
import org.jeecg.modules.airag.app.entity.AiragLog;
import org.jeecg.modules.airag.app.entity.Embeddings;
import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
import org.jeecg.modules.airag.app.mapper.AiragLogMapper;
import org.jeecg.modules.airag.app.mapper.QuestionEmbeddingMapper;
import org.jeecg.modules.airag.app.mapper.*;
import org.jeecg.modules.airag.app.service.IAiragLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
... ... @@ -36,6 +39,12 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
private QuestionEmbeddingMapper questionEmbeddingMapper;
@Autowired
private AiragButtonMapper airagButtonMapper;
@Autowired
private PgVectorMapper pgVectorMapper;
@Autowired
private AiragLogMapper airagLogMapper;
... ... @@ -60,7 +69,24 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
questionEmbedding.setMetadata(metadataJson);
questionEmbeddingMapper.insert(questionEmbedding);
airagLogMapper.updataIsStorage(log.getIsStorage(),log.getId());
System.out.println("1");
}
@Override
public void saveToEmbeddingLibrary(AiragLog log) throws JsonProcessingException {
// 这里实现将问题和回答存入问题库数据表的逻辑
// 假设问题库数据表的实体类为 QuestionLibrary,Mapper 接口为 QuestionLibraryMapper
Embeddings embeddings = new Embeddings();
embeddings.setText(log.getAnswer());
embeddings.setKnowledgeId(log.getKnowledgeId());
Map<String, Object> metadata = new LinkedHashMap<>();
metadata.put("title", "");
metadata.put("docName", "");
metadata.put("knowledgeId", embeddings.getKnowledgeId());
metadata.put("storedFileName", ""); // 自动生成唯一文档ID
embeddings.setMetadata(metadata);
pgVectorMapper.insert(embeddings);
airagLogMapper.updataIfSaveKnowledge(log.getIfSaveKnowledge(),log.getId());
}
@Override
... ... @@ -73,6 +99,69 @@ public class AiragLogServiceImpl extends ServiceImpl<AiragLogMapper, AiragLog> i
return airagLogMapper.pageList(airagLog,page);
}
@Override
public Map<String, Object> getStatistics() {
Map<String, Object> result = new HashMap<>();
// 1. 获取今日问答次数
QueryWrapper<AiragLog> todayWrapper = new QueryWrapper<>();
todayWrapper.apply("DATE(create_time) = CURDATE()");
long todayCount = this.count(todayWrapper);
// 2. 获取昨日问答次数
QueryWrapper<AiragLog> yesterdayWrapper = new QueryWrapper<>();
yesterdayWrapper.apply("DATE(create_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)");
long yesterdayCount = this.count(yesterdayWrapper);
// 3. 计算日增长率
double growthRate = 0.0;
if (yesterdayCount > 0) {
growthRate = ((double)(todayCount - yesterdayCount) / yesterdayCount) * 100;
} else if (todayCount > 0) {
// 昨天为0,今天有数据,则增长率为100%
growthRate = 100.0;
}
// 4. 获取拒绝回答次数
QueryWrapper<AiragLog> rejectedWrapper = new QueryWrapper<>();
rejectedWrapper.eq("answer_type", 3); // 假设3表示拒绝回答
long rejectedCount = this.count(rejectedWrapper);
// 5. 获取累计问答次数
long totalCount = this.count();
// 6. 计算平均问答次数(基于有记录的天数)
QueryWrapper<AiragLog> distinctDaysWrapper = new QueryWrapper<>();
distinctDaysWrapper.select("DISTINCT DATE(create_time)");
long distinctDays = this.count(distinctDaysWrapper);
double averageCount = 0.0;
if (distinctDays > 0) {
averageCount = (double) totalCount / distinctDays;
// 保留两位小数
averageCount = Math.round(averageCount * 100.0) / 100.0;
}
// 7.获取按钮问题和按钮code次数,只获取有按钮code的问题(log.question)
List<Map<String, Object>> buttonStats = airagLogMapper.getButtonRankList();
// 8. 获取最近12个月的月度数据
List<Map<String, Object>> monthlyData = airagLogMapper.getMonthlyCount();
// 9. 添加前一天数据
result.put("yesterdayCount", yesterdayCount);
result.put("growthRate", Math.round(growthRate * 100.0) / 100.0); // 保留两位小数
result.put("todayCount", todayCount);
result.put("rejectedCount", rejectedCount);
result.put("totalCount", totalCount);
result.put("averageCount", averageCount);
result.put("buttonStats", buttonStats);
result.put("monthlyData", monthlyData);
return result;
}
/* @Override
public List<T> list(Page<AiragLog> page, QueryWrapper<AiragLog> queryWrapper) {
... ...
... ... @@ -2,6 +2,7 @@ package org.jeecg.modules.airag.app.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.modules.airag.app.entity.Embeddings;
import org.jeecg.modules.airag.app.entity.QuestionEmbedding;
import org.jeecg.modules.airag.app.mapper.PgVectorMapper;
import org.jeecg.modules.airag.app.service.IEmbeddingsService;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -25,6 +26,11 @@ public class IEmbeddingsServiceImpl implements IEmbeddingsService {
return pgVectorMapper.findAll(embeddings,pageNo,pageSize);
}
@Override
public Integer findEmbeddingCount(Embeddings embeddings) {
return pgVectorMapper.findEmbeddingCount(embeddings);
}
public int deleteById(String id) {
return pgVectorMapper.deleteById(id);
}
... ...