mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-09-12 15:09:27 +00:00
【issues/9871】AI聊天助手访问限流配置统一到ai-chat,空或非正数时关闭对应限流
This commit is contained in:
parent
45f7be38d5
commit
169872c4b4
@ -49,6 +49,29 @@ public class AiChatConfig {
|
|||||||
*/
|
*/
|
||||||
private ModelConfig aiModelEmbed = new ModelConfig();
|
private ModelConfig aiModelEmbed = new ModelConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI 聊天助手访问限流配置
|
||||||
|
*/
|
||||||
|
private RateLimitConfig rateLimit = new RateLimitConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI 聊天助手访问限流参数
|
||||||
|
*
|
||||||
|
* @author scott
|
||||||
|
* @since 2026-09-01 issues/9871 AI聊天助手访问限流配置优化
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class RateLimitConfig {
|
||||||
|
/** 每会话每分钟最多发送消息次数,为空或小于等于 0 时不限制 */
|
||||||
|
private Integer sendPerSessionPerMinute;
|
||||||
|
|
||||||
|
/** 每 IP 每分钟最多发送消息次数,为空或小于等于 0 时不限制 */
|
||||||
|
private Integer sendPerIpPerMinute;
|
||||||
|
|
||||||
|
/** 每会话每小时最多上传文件次数,为空或小于等于 0 时不限制 */
|
||||||
|
private Integer uploadPerSessionPerHour;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class ModelConfig {
|
public static class ModelConfig {
|
||||||
/**
|
/**
|
||||||
@ -102,4 +125,4 @@ public class AiChatConfig {
|
|||||||
private double volume = 0.0;
|
private double volume = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,7 @@ package org.jeecg.modules.airag.app.service.impl;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.jeecg.common.exception.JeecgBootException;
|
import org.jeecg.common.exception.JeecgBootException;
|
||||||
import org.jeecg.common.util.IpUtils;
|
import org.jeecg.common.util.IpUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.jeecg.config.AiChatConfig;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -22,30 +21,25 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Service
|
@Service
|
||||||
public class AiragChatRateLimitService {
|
public class AiragChatRateLimitService {
|
||||||
|
|
||||||
@Autowired
|
private final RedisTemplate redisTemplate;
|
||||||
private RedisTemplate redisTemplate;
|
private final AiChatConfig.RateLimitConfig rateLimit;
|
||||||
|
|
||||||
/**
|
|
||||||
* 每会话每分钟最多发送消息次数
|
|
||||||
*/
|
|
||||||
@Value("${jeecg.airag.rate-limit.send-per-session-per-minute:20}")
|
|
||||||
private int sendPerSessionPerMinute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每 IP 每分钟最多发送消息次数
|
|
||||||
*/
|
|
||||||
@Value("${jeecg.airag.rate-limit.send-per-ip-per-minute:60}")
|
|
||||||
private int sendPerIpPerMinute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每会话每小时最多上传文件次数
|
|
||||||
*/
|
|
||||||
@Value("${jeecg.airag.rate-limit.upload-per-session-per-hour:20}")
|
|
||||||
private int uploadPerSessionPerHour;
|
|
||||||
|
|
||||||
private static final DateTimeFormatter MINUTE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
|
private static final DateTimeFormatter MINUTE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
|
||||||
private static final DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHH");
|
private static final DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHH");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 AI 聊天助手访问限流服务
|
||||||
|
*
|
||||||
|
* @param redisTemplate Redis 操作模板
|
||||||
|
* @param aiChatConfig AI 聊天配置
|
||||||
|
* @author scott
|
||||||
|
* @since 2026-09-01 issues/9871 AI聊天助手访问限流配置优化
|
||||||
|
*/
|
||||||
|
public AiragChatRateLimitService(RedisTemplate redisTemplate, AiChatConfig aiChatConfig) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
this.rateLimit = aiChatConfig.getRateLimit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验 /airag/chat/send 调用频次
|
* 校验 /airag/chat/send 调用频次
|
||||||
*
|
*
|
||||||
@ -56,9 +50,9 @@ public class AiragChatRateLimitService {
|
|||||||
String clientIp = IpUtils.getIpAddr(request);
|
String clientIp = IpUtils.getIpAddr(request);
|
||||||
String minute = LocalDateTime.now().format(MINUTE_FORMAT);
|
String minute = LocalDateTime.now().format(MINUTE_FORMAT);
|
||||||
|
|
||||||
checkLimit("airag:rate:send:session:" + sessionId + ":" + minute, sendPerSessionPerMinute, 120,
|
checkLimit("airag:rate:send:session:" + sessionId + ":" + minute, rateLimit.getSendPerSessionPerMinute(), 120,
|
||||||
"发送消息过于频繁,请稍后再试");
|
"发送消息过于频繁,请稍后再试");
|
||||||
checkLimit("airag:rate:send:ip:" + clientIp + ":" + minute, sendPerIpPerMinute, 120,
|
checkLimit("airag:rate:send:ip:" + clientIp + ":" + minute, rateLimit.getSendPerIpPerMinute(), 120,
|
||||||
"发送消息过于频繁,请稍后再试");
|
"发送消息过于频繁,请稍后再试");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +66,9 @@ public class AiragChatRateLimitService {
|
|||||||
String clientIp = IpUtils.getIpAddr(request);
|
String clientIp = IpUtils.getIpAddr(request);
|
||||||
String hour = LocalDateTime.now().format(HOUR_FORMAT);
|
String hour = LocalDateTime.now().format(HOUR_FORMAT);
|
||||||
|
|
||||||
checkLimit("airag:rate:upload:session:" + sessionId + ":" + hour, uploadPerSessionPerHour, 7200,
|
checkLimit("airag:rate:upload:session:" + sessionId + ":" + hour, rateLimit.getUploadPerSessionPerHour(), 7200,
|
||||||
"上传文件过于频繁,请稍后再试");
|
"上传文件过于频繁,请稍后再试");
|
||||||
checkLimit("airag:rate:upload:ip:" + clientIp + ":" + hour, uploadPerSessionPerHour, 7200,
|
checkLimit("airag:rate:upload:ip:" + clientIp + ":" + hour, rateLimit.getUploadPerSessionPerHour(), 7200,
|
||||||
"上传文件过于频繁,请稍后再试");
|
"上传文件过于频繁,请稍后再试");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +79,10 @@ public class AiragChatRateLimitService {
|
|||||||
* @param limit 窗口上限
|
* @param limit 窗口上限
|
||||||
* @param expireSeconds key 过期时间(秒)
|
* @param expireSeconds key 过期时间(秒)
|
||||||
*/
|
*/
|
||||||
private void checkLimit(String key, int limit, int expireSeconds, String errorMessage) {
|
private void checkLimit(String key, Integer limit, int expireSeconds, String errorMessage) {
|
||||||
|
if (limit == null || limit <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Long count = redisTemplate.opsForValue().increment(key, 1);
|
Long count = redisTemplate.opsForValue().increment(key, 1);
|
||||||
if (count == null) {
|
if (count == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -190,6 +190,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -254,15 +262,6 @@ jeecg:
|
|||||||
# Unipush配置 云函数调用 URL 化地址
|
# Unipush配置 云函数调用 URL 化地址
|
||||||
unicloud:
|
unicloud:
|
||||||
pushUrl:
|
pushUrl:
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -166,6 +166,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -225,15 +233,6 @@ jeecg:
|
|||||||
endpoint: https://api.search.brave.com/res/v1/web/search
|
endpoint: https://api.search.brave.com/res/v1/web/search
|
||||||
count: 10
|
count: 10
|
||||||
timeout: 15
|
timeout: 15
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -188,6 +188,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -377,4 +385,4 @@ justauth:
|
|||||||
cache:
|
cache:
|
||||||
type: default
|
type: default
|
||||||
prefix: 'demo::'
|
prefix: 'demo::'
|
||||||
timeout: 1h
|
timeout: 1h
|
||||||
|
|||||||
@ -183,6 +183,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -245,15 +253,6 @@ jeecg:
|
|||||||
# Unipush配置 云函数调用 URL 化地址
|
# Unipush配置 云函数调用 URL 化地址
|
||||||
unicloud:
|
unicloud:
|
||||||
pushUrl:
|
pushUrl:
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -180,6 +180,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -239,15 +247,6 @@ jeecg:
|
|||||||
endpoint: https://api.search.brave.com/res/v1/web/search
|
endpoint: https://api.search.brave.com/res/v1/web/search
|
||||||
count: 10
|
count: 10
|
||||||
timeout: 15
|
timeout: 15
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -193,6 +193,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -252,15 +260,6 @@ jeecg:
|
|||||||
endpoint: https://api.search.brave.com/res/v1/web/search
|
endpoint: https://api.search.brave.com/res/v1/web/search
|
||||||
count: 10
|
count: 10
|
||||||
timeout: 15
|
timeout: 15
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -186,6 +186,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
|
|||||||
@ -175,6 +175,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
@ -234,15 +242,6 @@ jeecg:
|
|||||||
endpoint: https://api.search.brave.com/res/v1/web/search
|
endpoint: https://api.search.brave.com/res/v1/web/search
|
||||||
count: 10
|
count: 10
|
||||||
timeout: 15
|
timeout: 15
|
||||||
airag:
|
|
||||||
# AI聊天助手访问限流配置
|
|
||||||
rate-limit:
|
|
||||||
# 单 session 每分钟上限
|
|
||||||
send-per-session-per-minute: 10
|
|
||||||
# 单 IP 每分钟上限
|
|
||||||
send-per-ip-per-minute: 20
|
|
||||||
# 单 session 每小时上限
|
|
||||||
upload-per-session-per-hour: 20
|
|
||||||
# 平台上线安全配置
|
# 平台上线安全配置
|
||||||
firewall:
|
firewall:
|
||||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||||
|
|||||||
@ -190,6 +190,14 @@ jeecg:
|
|||||||
timeout: 60
|
timeout: 60
|
||||||
skills-dir:
|
skills-dir:
|
||||||
skills-shell-dir:
|
skills-shell-dir:
|
||||||
|
# AI聊天助手访问限流配置
|
||||||
|
rate-limit:
|
||||||
|
# 单 session 每分钟上限
|
||||||
|
send-per-session-per-minute: 10
|
||||||
|
# 单 IP 每分钟上限
|
||||||
|
send-per-ip-per-minute: 20
|
||||||
|
# 单 session 每小时上限
|
||||||
|
upload-per-session-per-hour: 20
|
||||||
# AI文生图绘画
|
# AI文生图绘画
|
||||||
ai-model-draw:
|
ai-model-draw:
|
||||||
# 提供商 OPENAI/ZHIPU/QWEN
|
# 提供商 OPENAI/ZHIPU/QWEN
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user