mateclaw/mateclaw-server/src/main/java/vip/mate/llm/model/ModelFamily.java
2026-05-25 09:58:38 +08:00

185 lines
6.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package vip.mate.llm.model;
/**
* 模型族分类 — 收敛所有 provider/model 差异到统一的参数适配策略。
* <p>
* 按 provider+model 维度管理生成参数,
* 将 MateClaw 中散落在 isThinkingModel / requiresFixedTemperatureOne 等多处的判断
* 收敛到一个 enum每个族声明自己的参数约束。
* <p>
* 约束维度:
* <ul>
* <li>useMaxCompletionTokens — 是否必须用 max_completion_tokens 替代 max_tokens</li>
* <li>suppressMaxTokens — 是否禁止发送 max_tokens</li>
* <li>supportsReasoningEffort — 是否支持 reasoning_effort 参数</li>
* <li>fixedTemperatureOne — 是否强制 temperature=1.0</li>
* <li>suppressTopP — 是否禁止发送 top_p</li>
* <li>thinking — 是否为 thinking/reasoning 模型(影响 reasoningContent patch</li>
* </ul>
*
* @author MateClaw Team
*/
public enum ModelFamily {
/**
* OpenAI reasoning 模型gpt-5*, o1*, o3*, o4*
* <p>
* 约束:禁 max_tokens必须 max_completion_tokens支持 reasoning_effort
* 强制 temperature=1.0;禁 top_p。
*/
OPENAI_REASONING(true, true, true, true, true, true),
/**
* Kimi thinking 模型kimi-k2* 系列
* <p>
* 约束:保留 max_tokensMoonshot API 兼容旧格式);不支持 reasoning_effort会报参数不识别
* 强制 temperature=1.0;禁 top_p。
* 注意kimi-k2.5 天然开启 thinkingkimi-k2-thinking* 显式 thinking。
*/
KIMI_THINKING(false, false, false, true, true, true),
/**
* DeepSeek reasoning 模型deepseek-reasoner
* <p>
* 约束:保留 max_tokensDeepSeek API 兼容);不支持 reasoning_effort
* temperature 固定 1.0DeepSeek reasoner 约束);禁 top_p。
*/
DEEPSEEK_REASONER(false, false, false, true, true, true),
/**
* DeepSeek V4 reasoning 模型deepseek-v4-flash / deepseek-v4-pro。
* <p>
* 与 {@link #DEEPSEEK_REASONER}v3.2的关键差异V4 接受 {@code reasoning_effort} 字段,
* 也不强制 temperature=1。OpenClaw 实现参考 {@code extensions/deepseek/models.ts:28-81} 标记
* {@code supportsReasoningEffort: true}。<br>
* 约束:保留 max_tokens支持 reasoning_efforttemperature/topP 用配置值。
* thinking=true 让 {@link vip.mate.llm.chatmodel.DeepSeekV4ThinkingDecorator}
* 在请求体注入 OpenAI 协议外的 {@code thinking: {type: enabled|disabled}} 字段。
*/
DEEPSEEK_V4_REASONING(false, false, true, false, false, true),
/**
* Xiaomi MiMo thinking 模型MiMo-VL-*、mimo-* 系列。
* <p>
* MiMo 的 thinking 模式与 DeepSeek 类似:响应返回 {@code reasoning_content}
* 后续多轮请求必须将 {@code reasoning_content} 传回,否则 API 返回 400 错误。
* 约束:保留 max_tokens不支持 reasoning_efforttemperature/topP 用配置值。
*/
MIMO_THINKING(false, false, false, false, false, true),
/**
* 通用 thinking 模型(名称含 "thinking" 或 "reasoner" 但不匹配上述族):
* 如 qwen3-235b-a22b-thinking-2507
* <p>
* 约束:保留 max_tokens不支持 reasoning_effort保守策略
* temperature/topP 使用配置值。
*/
GENERIC_THINKING(false, false, false, false, false, true),
/**
* 标准模型:所有不匹配上述族的模型
* <p>
* 无特殊约束,全部参数正常传递。
*/
STANDARD(false, false, false, false, false, false);
private final boolean useMaxCompletionTokens;
private final boolean suppressMaxTokens;
private final boolean supportsReasoningEffort;
private final boolean fixedTemperatureOne;
private final boolean suppressTopP;
private final boolean thinking;
ModelFamily(boolean useMaxCompletionTokens, boolean suppressMaxTokens,
boolean supportsReasoningEffort, boolean fixedTemperatureOne,
boolean suppressTopP, boolean thinking) {
this.useMaxCompletionTokens = useMaxCompletionTokens;
this.suppressMaxTokens = suppressMaxTokens;
this.supportsReasoningEffort = supportsReasoningEffort;
this.fixedTemperatureOne = fixedTemperatureOne;
this.suppressTopP = suppressTopP;
this.thinking = thinking;
}
/** 是否必须用 max_completion_tokens 替代 max_tokens */
public boolean useMaxCompletionTokens() {
return useMaxCompletionTokens;
}
/** 是否禁止发送 max_tokens */
public boolean suppressMaxTokens() {
return suppressMaxTokens;
}
/** 是否支持 reasoning_effort 参数 */
public boolean supportsReasoningEffort() {
return supportsReasoningEffort;
}
/** 是否强制 temperature=1.0 */
public boolean fixedTemperatureOne() {
return fixedTemperatureOne;
}
/** 是否禁止发送 top_p */
public boolean suppressTopP() {
return suppressTopP;
}
/** 是否为 thinking/reasoning 模型 */
public boolean isThinking() {
return thinking;
}
/**
* 根据模型名称检测所属模型族。
* <p>
* 匹配优先级:精确族 > 通用 thinking > 标准。
*
* @param modelName 模型名称(如 "gpt-5.2", "kimi-k2.5", "deepseek-reasoner"
* @return 对应的 ModelFamily
*/
public static ModelFamily detect(String modelName) {
if (modelName == null || modelName.isBlank()) {
return STANDARD;
}
String normalized = modelName.trim().toLowerCase();
// OpenAI reasoning 族gpt-5*, o1*, o3*, o4*
if (normalized.startsWith("gpt-5")
|| normalized.startsWith("o1")
|| normalized.startsWith("o3")
|| normalized.startsWith("o4")) {
return OPENAI_REASONING;
}
// Kimi thinking 族kimi-k2* 全系列 + kimi-for-coding底层为 kimi-k2.5
if (normalized.startsWith("kimi-k2") || normalized.equals("kimi-for-coding")) {
return KIMI_THINKING;
}
// DeepSeek V4 reasoning 族deepseek-v4-flash / deepseek-v4-pro
// 优先匹配(在 DEEPSEEK_REASONER 之前),因为两者都含 "deepseek" 前缀但 V4 接受 reasoning_effort。
if (normalized.equals("deepseek-v4-flash") || normalized.equals("deepseek-v4-pro")) {
return DEEPSEEK_V4_REASONING;
}
// DeepSeek reasoning 族:仅 deepseek-reasoner
if (normalized.equals("deepseek-reasoner")) {
return DEEPSEEK_REASONER;
}
// Xiaomi MiMo thinking 族mimo-* / MiMo-VL-* 系列
if (normalized.startsWith("mimo")) {
return MIMO_THINKING;
}
// 通用 thinking 族:名称含 thinking / reasoner 关键词
if (normalized.contains("thinking") || normalized.contains("reasoner")) {
return GENERIC_THINKING;
}
return STANDARD;
}
}