UNPKG

@botpress/adk-cli

Version:

Command-line interface for the Botpress Agent Development Kit (ADK)

167 lines (164 loc) 6.2 kB
// @bun import { getTokenizer } from "./chunk-na956zz3.js"; // ../../node_modules/.bun/llmz@0.0.79+b49d396f5ed96e7f/node_modules/llmz/dist/chunk-M4WTTARE.js var DEFAULT_REMOVE_CHUNK = 250; var WRAP_OPEN_TAG_1 = "\u3010TRUNCATE"; var WRAP_OPEN_TAG_2 = "\u3011"; var WRAP_CLOSE_TAG = "\u3010/TRUNCATE\u3011"; var REGEXP = `(${WRAP_OPEN_TAG_1}(?:\\s+[\\w:]+)*\\s*${WRAP_OPEN_TAG_2})([\\s\\S]*?)(${WRAP_CLOSE_TAG})`; var DEFAULT_TRUNCATE_OPTIONS = { preserve: "top", flex: 1, minTokens: 0 }; function wrapContent(content, options) { const preserve = (options == null ? undefined : options.preserve) ?? DEFAULT_TRUNCATE_OPTIONS.preserve; const flex = (options == null ? undefined : options.flex) ?? DEFAULT_TRUNCATE_OPTIONS.flex; const minTokens = (options == null ? undefined : options.minTokens) ?? DEFAULT_TRUNCATE_OPTIONS.minTokens; return `${WRAP_OPEN_TAG_1} preserve:${preserve} flex:${flex} min:${minTokens} ${WRAP_OPEN_TAG_2}${content}${WRAP_CLOSE_TAG}`; } function truncateWrappedContent({ messages, tokenLimit, throwOnFailure = true }) { var _a, _b, _c; const tokenizer = getTokenizer(); const parts = []; for (const msg of messages) { const current = []; const content = typeof msg.content === "string" ? msg.content : ""; let match; const parser = new _MessageContentParser; while ((match = parser.parse(content)) !== null) { const { attributes, nonTruncatableContent, wrappedContent } = match; if (nonTruncatableContent) { current.push({ content: nonTruncatableContent, tokens: tokenizer.count(nonTruncatableContent), truncatable: false }); } current.push({ content: wrappedContent, tokens: tokenizer.count(wrappedContent), truncatable: true, attributes: { preserve: attributes.preserve, flex: Number(attributes.flex) || DEFAULT_TRUNCATE_OPTIONS.flex, minTokens: Number(attributes.min) || DEFAULT_TRUNCATE_OPTIONS.minTokens } }); } const remainingContent = parser.getRemainingContent(content); if (remainingContent) { current.push({ content: remainingContent, tokens: tokenizer.count(remainingContent), truncatable: false }); } parts.push(current); } let currentCount = _countTotalTokens(parts); while (currentCount > tokenLimit) { const { biggest, secondBiggest } = _getTwoBiggestTruncables(parts); if (!biggest || !biggest.truncatable || biggest.tokens <= 0) { if (throwOnFailure) { throw new Error(`Cannot truncate further, current count: ${currentCount}`); } else { break; } } const delta = Math.max(biggest.tokens - ((secondBiggest == null ? undefined : secondBiggest.tokens) ?? 0), DEFAULT_REMOVE_CHUNK); const room = Math.min(delta, biggest.tokens); let toRemove = Math.min(room, currentCount - tokenLimit); if (toRemove <= 0) { if (throwOnFailure) { throw new Error(`Cannot truncate further, current count: ${currentCount}`); } else { break; } } if (biggest.tokens - toRemove < (((_a = biggest.attributes) == null ? undefined : _a.minTokens) ?? 0)) { toRemove = biggest.tokens - (((_b = biggest.attributes) == null ? undefined : _b.minTokens) ?? 0); } const preserve = ((_c = biggest.attributes) == null ? undefined : _c.preserve) ?? DEFAULT_TRUNCATE_OPTIONS.preserve; const split = tokenizer.splitAndSlice(biggest.content); if (preserve === "bottom") { biggest.content = split.slice(toRemove).join(""); } else if (preserve === "top") { biggest.content = split.slice(0, -toRemove).join(""); } else { const anchor = Math.ceil(split.length / 2); const radius = Math.ceil(toRemove / 2); const left = anchor - radius; const right = anchor + radius; biggest.content = split.slice(0, left).join("") + split.slice(right).join(""); } biggest.tokens -= toRemove; currentCount -= toRemove; } return messages.map((msg, i) => { const p = parts[i]; return { ...msg, content: typeof msg.content === "string" ? _renderRemainingWrappers(p.map((part) => part.content).join("")) : msg.content }; }); } var _MessageContentParser = class { _regex; _lastIndex = 0; constructor() { this._regex = _createRegex(); } parse(content) { const match = this._regex.exec(content); if (!match) { return null; } const attributes = match[1].split(/\s+/).slice(1).filter((x) => x !== WRAP_OPEN_TAG_2).map((x) => x.split(":")).reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); let nonTruncatableContent = undefined; if (match.index > this._lastIndex) { nonTruncatableContent = content.slice(this._lastIndex, match.index); } const wrappedContent = match[2]; this._lastIndex = this._regex.lastIndex; return { attributes, nonTruncatableContent, wrappedContent }; } getRemainingContent(content) { if (this._lastIndex < content.length) { const remainingContent = content.slice(this._lastIndex); return remainingContent; } return null; } }; var _createRegex = () => new RegExp(REGEXP, "g"); var _renderRemainingWrappers = (content) => content.replace(_createRegex(), "$2"); var _countTotalTokens = (parts) => parts.reduce((acc, x) => acc + x.reduce((acc2, y) => acc2 + y.tokens, 0), 0); var _getTwoBiggestTruncables = (parts) => { var _a, _b; let biggest = null; let secondBiggest = null; for (const part of parts.flat()) { if (part.truncatable) { if (part.tokens <= (((_a = part.attributes) == null ? undefined : _a.minTokens) ?? 0)) { continue; } const flex = ((_b = part.attributes) == null ? undefined : _b.flex) ?? DEFAULT_TRUNCATE_OPTIONS.flex; const tokens = part.tokens * flex; if (!biggest || tokens > biggest.tokens) { secondBiggest = biggest; biggest = part; } else if (!secondBiggest || tokens > secondBiggest.tokens) { secondBiggest = part; } } } return { biggest, secondBiggest }; }; export { wrapContent, truncateWrappedContent };