@myassis/gateway 1.0.90 → 1.0.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config/index.js
CHANGED
|
@@ -121,8 +121,23 @@ exports.appConfig = {
|
|
|
121
121
|
enablePrecompression: process.env.ENABLE_PRECOMPRESSION !== 'false',
|
|
122
122
|
/** 回复结束后延迟多久启动预压缩(毫秒),留出时间给用户连续追问 */
|
|
123
123
|
precompressionDelay: parseInt(process.env.PRECOMPRESSION_DELAY || '3000', 10),
|
|
124
|
-
/**
|
|
125
|
-
|
|
124
|
+
/**
|
|
125
|
+
* 触发上下文压缩的字符阈值。
|
|
126
|
+
*
|
|
127
|
+
* 口径是「实际入参字符数」(历史工具输出已按 oldToolContentLimit 折算),
|
|
128
|
+
* 因此可以贴着 contextMaxChars 设,而不必为截断留出巨大余量。
|
|
129
|
+
* 旧默认值 60000 是按原始体积设的,换算到实际入参口径后过早触发,
|
|
130
|
+
* 表现为「没聊几句就开始压缩」。
|
|
131
|
+
*/
|
|
132
|
+
summaryTriggerChars: parseInt(process.env.SUMMARY_TRIGGER_CHARS || '120000', 10),
|
|
133
|
+
/**
|
|
134
|
+
* 触发上下文压缩的消息条数阈值。
|
|
135
|
+
*
|
|
136
|
+
* 一轮「用户提问 + 助手带工具回复」就占 2 条,旧值 10 意味着第 5 轮对话
|
|
137
|
+
* 必定压缩,与内容多少无关 —— 这是「没聊几句就压缩」最直接的原因。
|
|
138
|
+
* 条数只作为体积估算失真时的兜底,阈值应远高于正常对话轮数。
|
|
139
|
+
*/
|
|
140
|
+
summaryThreshold: parseInt(process.env.SUMMARY_THRESHOLD || '60', 10),
|
|
126
141
|
appName: '我的助手'
|
|
127
142
|
};
|
|
128
143
|
/**
|
|
@@ -31,10 +31,9 @@ const dataService_js_1 = require("../dataService.js");
|
|
|
31
31
|
const index_js_1 = require("../../stores/index.js");
|
|
32
32
|
const LLMClient_js_1 = require("../llm/LLMClient.js");
|
|
33
33
|
const index_js_2 = require("../../config/index.js");
|
|
34
|
-
const ContextBuilder_js_1 = require("./ContextBuilder.js");
|
|
35
34
|
const ToolLedger_js_1 = require("./ToolLedger.js");
|
|
36
35
|
const DEFAULT_CONFIG = {
|
|
37
|
-
summaryThreshold:
|
|
36
|
+
summaryThreshold: index_js_2.appConfig.summaryThreshold,
|
|
38
37
|
summaryTriggerChars: index_js_2.appConfig.summaryTriggerChars,
|
|
39
38
|
enabled: true,
|
|
40
39
|
};
|
|
@@ -74,6 +73,43 @@ const sendSSE = (res, data) => {
|
|
|
74
73
|
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
75
74
|
res.flush?.();
|
|
76
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* 估算「会话消息实际进入上下文后」的字符数。
|
|
78
|
+
*
|
|
79
|
+
* 不能直接用 estimateChars:它算的是原始体积,而历史消息里的工具输出
|
|
80
|
+
* 在 LLMClient.mapMessages 中每条只保留 oldToolContentLimit(默认 500)字符。
|
|
81
|
+
* 用原始体积判断压缩,会把一条 8000 字符的工具输出按 8000 计,
|
|
82
|
+
* 而它实际只占 500 —— 于是「没聊几句就开始压缩」:一轮 11 次工具调用的
|
|
83
|
+
* 会话,原始体积轻松破 6 万,实际入参却不到 1 万。
|
|
84
|
+
*
|
|
85
|
+
* 这里按真实入参口径折算,让压缩阈值和它想控制的对象是同一个东西。
|
|
86
|
+
*/
|
|
87
|
+
function estimateContextChars(messages) {
|
|
88
|
+
const limit = index_js_2.appConfig.oldToolContentLimit;
|
|
89
|
+
let total = 0;
|
|
90
|
+
for (const message of messages || []) {
|
|
91
|
+
if (typeof message.content === 'string')
|
|
92
|
+
total += message.content.length;
|
|
93
|
+
else if (message.content)
|
|
94
|
+
total += JSON.stringify(message.content).length;
|
|
95
|
+
if (message.reasoning_content)
|
|
96
|
+
total += String(message.reasoning_content).length;
|
|
97
|
+
for (const group of (message.toolCalls || [])) {
|
|
98
|
+
total += (group?.content?.length || 0) + (group?.reasoningContent?.length || 0);
|
|
99
|
+
for (const item of (group?.toolCalls || [])) {
|
|
100
|
+
total += (item?.toolName?.length || 0);
|
|
101
|
+
// 参数会被 clipJsonArguments 截断,但下限就是 limit 量级,按 limit 计
|
|
102
|
+
total += Math.min(String(item?.input ?? '').length, limit);
|
|
103
|
+
// 输出在 mapMessages 里被硬截断到 limit
|
|
104
|
+
total += Math.min(String(item?.output ?? '').length, limit);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const att of (message.attachments || [])) {
|
|
108
|
+
total += (att?.url?.length || 0) + (att?.name?.length || 0);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return total;
|
|
112
|
+
}
|
|
77
113
|
/**
|
|
78
114
|
* 记忆管理器
|
|
79
115
|
* 实现总结式记忆:当对话超过一定长度时,自动生成对话摘要
|
|
@@ -134,8 +170,9 @@ class MemoryManager {
|
|
|
134
170
|
return false;
|
|
135
171
|
if (messages.length >= this.config.summaryThreshold)
|
|
136
172
|
return true;
|
|
137
|
-
//
|
|
138
|
-
|
|
173
|
+
// 单条工具结果可能极大,条数少也可能远超上下文预算。
|
|
174
|
+
// 按「实际入参口径」估算:历史工具输出会被截断,用原始体积会严重高估。
|
|
175
|
+
return estimateContextChars(messages) >= this.config.summaryTriggerChars;
|
|
139
176
|
}
|
|
140
177
|
/**
|
|
141
178
|
* 取得“最后一条被摘要消息”的时间戳作为摘要边界。
|