75 lines
3.7 KiB
JavaScript
75 lines
3.7 KiB
JavaScript
/**
|
||
* 计算指数退避的重试延迟,并加入抖动以减少多个实例同时重试的概率。
|
||
*
|
||
* 主要逻辑:
|
||
* 1. 根据重试次数计算基础的指数延迟 (baseDelay * 2^retryCount)。
|
||
* 2. 生成一个抖动值,其范围是指数延迟的 ±10% (即 exponentialDelay * 0.2 * (Math.random() - 0.5))。
|
||
* 3. 将抖动值加到指数延迟上。
|
||
* 4. 确保总延迟不超过 `maxDelay`。
|
||
* 5. 确保总延迟不小于 `baseDelay` (以防抖动导致延迟过小)。
|
||
*
|
||
* @param {number} retryCount - 当前重试次数 (从0开始计数)。
|
||
* @param {number} baseDelay - 基础延迟时间 (毫秒),默认为 500ms。
|
||
* @param {number} maxDelay - 最大延迟时间 (毫秒),默认为 30000ms。
|
||
* @returns {number} 计算后并应用了抖动和上下限的延迟时间 (毫秒)。
|
||
*/
|
||
function getRetryDelay(retryCount, baseDelay = 500, maxDelay = 30000) {
|
||
const exponentialDelay = baseDelay * Math.pow(2, retryCount);
|
||
// 抖动: 在 ±10% 范围内随机浮动
|
||
const jitter = exponentialDelay * 0.2 * (Math.random() - 0.5);
|
||
const totalDelay = Math.min(exponentialDelay + jitter, maxDelay);
|
||
return Math.max(totalDelay, baseDelay);
|
||
}
|
||
|
||
/**
|
||
* 基于文本特性估算其 token 数量。
|
||
* 此方法为启发式估算,并非精确计数,主要针对不同语言特性采用不同策略。
|
||
*
|
||
* 主要逻辑:
|
||
* 1. 如果文本为空或未定义,直接返回 0。
|
||
* 2. 计算文本中非 ASCII 字符 (粗略地判断为 CJK 字符等) 的比例。
|
||
* 3. **CJK 语言处理**: 如果非 ASCII 字符的比例超过一个阈值 (例如 0.3),则认为文本主要由 CJK 字符构成。
|
||
* 此时,token 数大致估算为 `text.length * 1.1` (一个字符约等于 1.1 个 token)。
|
||
* 4. **其他语言处理 (如英文、代码)**: 否则,认为文本主要由 ASCII 字符构成。
|
||
* 此时,token 数大致估算为 `text.length / 3.5` (约 3-4 个字符为一个 token)。
|
||
* 5. 对估算结果向上取整。
|
||
*
|
||
* @param {string} text - 需要估算 token 数的输入文本。
|
||
* @returns {number} 估算出的 token 数量。
|
||
*/
|
||
function estimateTokenCount(text) {
|
||
if (!text) return 0;
|
||
// 针对CJK等非ASCII字符的优化估算
|
||
const nonAsciiRatio = (text.match(/[^ - ]/g) || []).length / text.length;
|
||
if (nonAsciiRatio > 0.3) { // 中日韩等语言的启发式判断
|
||
return Math.ceil(text.length * 1.1);
|
||
} else {
|
||
// 英文和代码大约3-4个字符一个token
|
||
return Math.ceil(text.length / 3.5);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 转义字符串中的正则表达式特殊字符。
|
||
* 当需要将一个普通字符串用作正则表达式的一部分进行精确匹配时,
|
||
* 该字符串中可能包含的正则表达式特殊字符 (如 `.`、`*`、`+`、`?` 等) 需要被转义,
|
||
* 以确保它们被解释为字面量字符而不是元字符。
|
||
*
|
||
* 主要逻辑:
|
||
* - 使用 `String.prototype.replace()` 方法。
|
||
* - 正则表达式 `/[.*+?^${}()|[\\]\\]/g` 匹配所有常见的正则表达式特殊字符。
|
||
* - 替换函数 `$&` 表示匹配到的整个子字符串,在其前面加上反斜杠 `\\` 进行转义。
|
||
*
|
||
* @param {string} string - 需要转义的原始字符串。
|
||
* @returns {string} 特殊字符已被转义的字符串,可以直接安全地用于构建新的正则表达式。
|
||
*/
|
||
function escapeRegex(string) {
|
||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||
}
|
||
|
||
// 将工具函数添加到processModule对象
|
||
if (typeof processModule !== 'undefined') {
|
||
processModule.getRetryDelay = getRetryDelay;
|
||
processModule.estimateTokenCount = estimateTokenCount;
|
||
processModule.escapeRegex = escapeRegex;
|
||
} |