Files
JChatGPT/src/main/kotlin/PluginConfig.kt
T
jie65535andClaude Opus 4.8 826dc460df Add chat endpoint failover for resilience against unstable LLM APIs
Configure a list of fallback chat endpoints (chatFallbacks); each blank
field inherits the primary, so you can swap just the API key, just the
model, or the whole vendor. On LLM streaming failure the retry loop
advances to the next endpoint, and a failed endpoint enters a cooldown
(fallbackCooldownMinutes) so a dead primary is skipped instead of
wasting a timeout on every message.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 22:23:43 +08:00

168 lines
7.6 KiB
Kotlin

package top.jie65535.mirai
import kotlinx.serialization.Serializable
import net.mamoe.mirai.console.data.AutoSavePluginConfig
import net.mamoe.mirai.console.data.ValueDescription
import net.mamoe.mirai.console.data.value
/**
* 聊天模型备用接入点。用于主接入点(openAiApi/openAiToken/chatModel)连续失败时容灾切换。
* 任一字段留空则继承主接入点对应配置,因此可只换 API KEY、只换模型、或整体换一个服务商。
*/
@Serializable
data class ChatFallbackEndpoint(
val api: String = "",
val token: String = "",
val model: String = "",
val extraBody: String = "",
)
object PluginConfig : AutoSavePluginConfig("Config") {
@ValueDescription("主人QQ,AI可以通过工具向主人发起请求,会等待一段时间")
val ownerId: Long by value()
@ValueDescription("OpenAI API base url")
val openAiApi: String by value("https://dashscope.aliyuncs.com/compatible-mode/v1/")
@ValueDescription("OpenAI API Token")
var openAiToken: String by value("")
@ValueDescription("Chat模型")
var chatModel: String by value("qwen-max")
@ValueDescription("Chat模型温度,默认为null")
var chatTemperature: Double? by value(null)
@ValueDescription("推理模型API")
var reasoningModelApi: String by value("https://dashscope.aliyuncs.com/compatible-mode/v1/")
@ValueDescription("推理模型Token")
var reasoningModelToken: String by value("")
@ValueDescription("推理模型")
var reasoningModel: String by value("qwq-plus")
@ValueDescription("视觉模型API")
var visualModelApi: String by value("https://dashscope.aliyuncs.com/compatible-mode/v1/")
@ValueDescription("视觉模型Token")
var visualModelToken: String by value("")
@ValueDescription("视觉模型")
var visualModel: String by value("qwen-vl-plus")
@ValueDescription("聊天模型额外请求体JSON,会合并到请求体中。例如DeepSeek关闭思维: {\"thinking\": {\"type\": \"disabled\"}}")
val chatModelExtraBody: String by value("")
@ValueDescription("聊天模型备用接入点列表(容灾)。主接入点连续失败时按顺序切换;每项留空的字段会继承主接入点,例如只换API KEY就只填token,只换模型就只填model")
val chatFallbacks: List<ChatFallbackEndpoint> by value()
@ValueDescription("备用接入点冷却时间(分钟)。某接入点失败后在此时间内会被排到重试队尾,避免每条消息都先卡在故障接入点上。设为0禁用,默认5分钟")
val fallbackCooldownMinutes: Long by value(5L)
@ValueDescription("推理模型额外请求体JSON,会合并到请求体中。例如DeepSeek启用思维: {\"thinking\": {\"type\": \"enabled\"}}")
val reasoningModelExtraBody: String by value("")
@ValueDescription("视觉模型额外请求体JSON,会合并到请求体中。")
val visualModelExtraBody: String by value("")
@ValueDescription("百炼平台API KEY")
val dashScopeApiKey: String by value("")
@ValueDescription("百炼平台图像模型,支持文生图与图像编辑。可选:qwen-image-2.0 / qwen-image-2.0-pro / qwen-image-edit-max / qwen-image-edit-plus 等")
val imageModel: String by value("qwen-image-2.0")
@ValueDescription("是否在生成的图片右下角添加 Qwen-Image 水印")
val imageWatermark: Boolean by value(false)
@ValueDescription("百炼平台TTS模型。qwen3-tts-instruct-flash 支持 instructions 指令控制;纯发音可用 qwen3-tts-flash 或 qwen-tts")
val ttsModel: String by value("qwen3-tts-instruct-flash")
@ValueDescription("Jina API Key")
val jinaApiKey by value("")
@ValueDescription("SearXNG 搜索引擎地址,如 http://127.0.0.1:8080/search 必须启用允许json格式返回")
val searXngUrl: String by value("")
@ValueDescription("在线运行代码 glot.io 的 api token,在官网注册账号即可获取。")
val glotToken: String by value("")
@ValueDescription("群管理是否自动拥有对话权限,默认是")
val groupOpHasChatPermission: Boolean by value(true)
@ValueDescription("好友是否自动拥有对话权限,默认是")
val friendHasChatPermission: Boolean by value(true)
@ValueDescription("机器人是否可以禁言别人,默认禁止")
val canMute: Boolean by value(false)
@ValueDescription("群荣誉等级权限门槛,达到这个等级相当于自动拥有对话权限。")
val temperaturePermission: Int by value(50)
@ValueDescription("等待响应超时时间(整个请求的总超时与socket读超时),单位毫秒,默认60秒")
val timeout: Long by value(60000L)
@ValueDescription("首块响应超时时间,单位毫秒,默认10秒。若连接建立后在此时间内没收到首块data:则中断走重试")
val firstChunkTimeout: Long by value(10000L)
@Deprecated("使用外部文件而不是在配置文件内保存提示词")
@ValueDescription("系统提示词,该字段已弃用,使用提示词文件而不是在这里修改")
var prompt: String by value("你是一个乐于助人的助手")
@ValueDescription("系统提示词文件路径,相对于插件配置目录")
val promptFile: String by value("SystemPrompt.md")
@ValueDescription("创建Prompt时取最近多少分钟内的消息")
val historyWindowMin: Int by value(10)
@ValueDescription("创建Prompt时取最多几条消息")
val historyMessageLimit: Int by value(20)
@ValueDescription("启用对话上下文内存缓存,允许在短时间内保持上下文连续")
val enableContextCache by value(true)
@ValueDescription("上下文缓存有效期(分钟),超过此时间未活动则重新创建上下文")
val contextCacheTimeoutMinutes by value(10)
@ValueDescription("是否打印Prompt便于调试")
val logPrompt by value(false)
@ValueDescription("达到需要合并转发消息的阈值")
val messageMergeThreshold by value(150)
@ValueDescription("最大循环次数,至少2次")
val retryMax: Int by value(5)
@ValueDescription("关键字呼叫,支持正则表达式")
val callKeyword by value("[小筱][林淋月玥]")
@ValueDescription("是否显示工具调用消息,默认是")
val showToolCallingMessage by value(true)
@ValueDescription("是否启用记忆编辑功能,记忆存在data目录,提示词中需要加上{memory}来填充记忆,每个群都有独立记忆")
val memoryEnabled by value(true)
@ValueDescription("是否启用技能系统,技能存在data/skills目录(全局跨群),提示词中需要加上{skills}来注入技能索引")
val skillsEnabled by value(true)
@ValueDescription("是否启用好感度系统")
val enableFavorabilitySystem by value(true)
@ValueDescription("好感度每日基础偏移速度(点/天)")
val favorabilityBaseShiftSpeed by value(2.0)
@ValueDescription("表情包路径,配置后会加载目录下的文件名,提示词中需要用{meme}来插入上下文")
val memeDir: String by value("")
@ValueDescription("请求主人回复等待时间,单位毫秒,默认300秒")
val requestOwnerWaitTimeout: Long by value(300000L)
@ValueDescription("单个工具调用返回内容的最大字符数,超过将被截断并标注")
val maxToolOutputLength: Int by value(15000)
@ValueDescription("聊天记录搜索最大天数")
val searchHistoryMaxDays: Int by value(30)
@ValueDescription("聊天记录搜索最大查询条数,防止内存溢出")
val searchHistoryMaxRecords: Int by value(5000)
}