mateclaw/mateclaw-server/src/main/java/vip/mate/config/ConversationWindowProperties.java

76 lines
3.1 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.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 会话历史上下文窗口管理配置
*
* @author MateClaw Team
*/
@Data
@ConfigurationProperties(prefix = "mate.agent.conversation.window")
public class ConversationWindowProperties {
/** 全局默认最大输入 token上下文窗口 */
private int defaultMaxInputTokens = 128000;
/** 历史 token 占比达此阈值触发压缩0-1 */
private double compactTriggerRatio = 0.75;
/** 压缩后保留最近 N 轮对话user+assistant 算一轮) */
private int preserveRecentPairs = 5;
/** 摘要自身最大 token 数(仅作 LLM maxToken 参数上限,实际预算由动态计算) */
private int summaryMaxTokens = 800;
// ==================== 动态压缩配置 ====================
/** 尾部保护的最小消息数(即使 token 预算用完也至少保留这么多) */
private int protectLastMinMessages = 10;
/** 摘要 token 预算占被压缩内容的比例 (0-1)。被压缩内容越多,摘要越长。 */
private double summaryBudgetRatio = 0.20;
/** 摘要 token 预算上限(字数,非 token */
private int summaryBudgetCeiling = 3000;
/** 摘要 token 预算下限(字数) */
private int summaryBudgetFloor = 500;
/**
* Minimum prefix size (in messages) the pair-safe boundary must leave
* before compaction is allowed to run. After enforcing tool-call/response
* pair integrity the boundary may collapse so far forward that only a
* handful of messages remain in the prefix — at that point the
* compaction cost (a structured-summary LLM call) outweighs any token
* savings, and we may as well skip this turn.
*
* <p>Default 2 means "at least two old messages worth condensing".
* Set to 0 to always attempt compaction whenever a pair-safe cut exists.
*/
private int pairSafeMinPrefixToCompact = 2;
/**
* After compaction, re-inject the first user message of the compressed
* prefix so the original goal stays anchored in the prompt even when a
* long task has paged through dozens of turns. Without an anchor the
* structured summary alone can drift, and the model may forget what was
* being asked. Injected as a {@link org.springframework.ai.chat.messages.UserMessage}
* (never SystemMessage) so historical user input cannot be promoted to a
* system-level instruction.
*/
private boolean firstUserAnchorEnabled = true;
/**
* Maximum tokens the anchor body is allowed to consume in the prompt.
* The first user message is often short ("write me a CLI tool that…"),
* but power users sometimes paste multi-KB specs. When the body fits
* the budget it stays verbatim; when it is up to 3× over, it is
* head+tail truncated to this budget; when it is more than 3× over,
* it degrades to a 200-char pointer line so the model still knows the
* original goal existed without blowing prompt-cache or summary budget.
*/
private int firstUserAnchorMaxTokens = 400;
}