小布工坊.
← 回到资源库

资源详情 · 消息处理

按字符预算保留最近上下文

保留第一条system规则和连续的最近消息;输入超限时明确报错,不悄悄丢掉最新请求。

资源正文、示例和许可证保留原文。代码仅展示,不会在线执行或调用AI。

资源详情

适合学习上下文裁剪。预算只计算正文的Unicode码点数量,既不是真实tokenizer,也不包含请求封装开销,不能用它保证模型接口不超token上限。

使用前准备

适用平台
Windows · macOS · Linux
内容更新
  • 准备Node.js 24和文本编辑器;本站仅在Node.js v24.19.0本地核对。
  • 准备有role与content的虚构消息,system仅放在首条。
node context-budget.mjs

先在文件所在目录打开终端。无需 npm install;本例不联网、不读写用户文件,不能直接代替生产平台接入。

常见卡点

  • 按指定.mjs文件名保存,避免变成.mjs.txt;不需要npm install。
  • 字符预算不是真实token预算,不能保证模型请求不超限。
官方网站与安装说明 ↗

完整正文

// SPDX-License-Identifier: MIT
// 原创教学示例:按Unicode码点计算正文字符;这不是真实tokenizer或接口token上限。
export function selectContext(messages, options = {}) {
  if (!Array.isArray(messages) || messages.length > 100) throw new RangeError("消息最多100条");
  if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError("选项需为对象");
  const { maxCharacters = 2000, maxMessages = 20 } = options;
  if (!Number.isInteger(maxCharacters) || maxCharacters < 1 || maxCharacters > 60000) throw new RangeError("字符预算需为1至60000");
  if (!Number.isInteger(maxMessages) || maxMessages < 1 || maxMessages > 100) throw new RangeError("消息预算需为1至100");
  const input = messages.map((message, index) => {
    if (!message || !["system", "user", "assistant"].includes(message.role)) throw new TypeError("角色无效");
    if (message.role === "system" && index !== 0) throw new TypeError("system只能放在第一条");
    if (typeof message.content !== "string" || !message.content.trim() || message.content.length > 4000) throw new TypeError("每条正文需为1至4000字符");
    return { role: message.role, content: message.content };
  });
  const fixed = input[0]?.role === "system" ? [input[0]] : [];
  const history = input.slice(fixed.length), chosen = [];
  const lengthOf = message => Array.from(message.content).length;
  let characters = fixed.length ? lengthOf(fixed[0]) : 0;
  if (characters > maxCharacters) throw new RangeError("system已超出字符预算,请先修改预算或规则");
  if (history.length && fixed.length >= maxMessages) throw new RangeError("消息预算无法同时保留system和最新消息");
  for (let index = history.length - 1; index >= 0; index--) {
    if (chosen.length + fixed.length >= maxMessages) break;
    const cost = lengthOf(history[index]);
    if (characters + cost > maxCharacters) {
      if (!chosen.length) throw new RangeError("最新消息超出剩余预算,请先缩短输入");
      break; // 保留连续的最近片段,不跳过中间消息去拼更旧的内容。
    }
    chosen.unshift(history[index]); characters += cost;
  }
  const selected = [...fixed, ...chosen];
  return { messages: selected, characters, dropped: input.length - selected.length };
}

const context = [
  { role: "system", content: "请简洁" },
  { role: "user", content: "旧问题" },
  { role: "assistant", content: "旧回答" },
  { role: "user", content: "新问题" },
];
console.log(JSON.stringify(selectContext(context, { maxCharacters: 6, maxMessages: 3 })));

使用教程

六个正文字符的预算只够保留system“请简洁”和最新的“新问题”,两条旧消息被移除。

  1. 保存完整教学代码

    点击下载代码,或复制正文保存为context-budget.mjs。保留许可说明;不要混入Markdown三反引号,确认后缀不是.mjs.txt。

  2. 在文件夹中运行

    准备Node.js 24,在保存文件的目录打开终端,执行下方node命令;不需要账号、密钥或第三方依赖。

  3. 核对结果后再修改

    messages应只有system和最后一条user,characters为6、dropped为2。把预算改为5,会明确报错,要求先缩短最新输入或调整预算。

保存文件名
context-budget.mjs
运行环境
Node.js 24;本站运行核验为v24.19.0。保存为.mjs,无需npm install。
依赖与费用
代码不联网、不调用模型、不读写用户文件;无接口费用。设备和电力成本由使用者承担,接入实际应用后的成本另行核对。

运行命令

node context-budget.mjs

预期输出

{"messages":[{"role":"system","content":"请简洁"},{"role":"user","content":"新问题"}],"characters":6,"dropped":2}

本地核验

2026-10-22 · Node.js v24.19.0

已在本站本机运行此页原样附带的教学代码,并核对演示输出及本批注明的边界测试;不代表生产验证、全平台实测或安全审计。

适合用在哪里

  • 学习上下文窗口裁剪
  • 理解保留规则与最新输入的优先级

注意事项

  • 字符按Unicode码点计,不按字节、视觉字形或真实模型token计;中文和英文都不能据此换算精确token。
  • 不计模型系统封装、工具定义等额外开销。生产接入须使用目标模型的计数方法和安全余量。
  • 最多100条、单条正文最多4000个UTF-16代码单元;保留连续后缀,但不保证完整问答配对,生产应用需按轮次处理。

原作者与来源

署名
包子海梦 · AI辅助开发
原作者与来源
提示集贡献者

声明与修改说明

新编写的通用教学示例,发布前仍需核对来源与运行效果。

完整许可证

MIT

MIT License

Copyright (c) 2026 提示集贡献者

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

验证范围

教学代码已运行

已运行完整带许可的教学文件并核对输出;不代表生产部署、平台接入或全部边界情况都已验证。

2026-10-23 Node.js v24.19.0