UNPKG

@microsoft/teams-ai

Version:

SDK focused on building AI based applications for Microsoft Teams.

127 lines 5.73 kB
"use strict"; /** * @module teams-ai */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PromptSectionBase = void 0; /** * Abstract Base class for most prompt sections. * @remarks * This class provides a default implementation of `renderAsText()` so that derived classes only * need to implement `renderAsMessages()`. */ class PromptSectionBase { required; tokens; separator; textPrefix; /** * Creates a new 'PromptSectionBase' instance. * @param {number} tokens - Optional. Sizing strategy for this section. Defaults to -1, 'auto'. * @param {boolean} required - Optional. Indicates if this section is required. Defaults to `true`. * @param {string} separator - Optional. Separator to use between sections when rendering as text. Defaults to `\n`. * @param {string} textPrefix - Optional. Prefix to use for text output. Defaults to an empty string. */ constructor(tokens = -1, required = true, separator = '\n', textPrefix = '') { this.required = required; this.tokens = tokens; this.separator = separator; this.textPrefix = textPrefix; } /** * Renders the prompt section as a string of text. * @param {TurnContext} context - Context for the current turn of conversation. * @param {Memory} memory - Interface for accessing state variables. * @param {PromptFunctions} functions - Functions for rendering prompts. * @param {Tokenizer} tokenizer - Tokenizer to use for encoding/decoding text. * @param {number} maxTokens - Maximum number of tokens allowed for the rendered prompt. * @returns {Promise<RenderedPromptSection<string>>} The rendered prompt section. */ async renderAsText(context, memory, functions, tokenizer, maxTokens) { // Render as messages const asMessages = await this.renderAsMessages(context, memory, functions, tokenizer, maxTokens); if (asMessages.output.length === 0) { return { output: '', length: 0, tooLong: false }; } // Convert to text let text = asMessages.output.map((message) => PromptSectionBase.getMessageText(message)).join(this.separator); // Calculate length const prefixLength = tokenizer.encode(this.textPrefix).length; const separatorLength = tokenizer.encode(this.separator).length; let length = prefixLength + asMessages.length + (asMessages.output.length - 1) * separatorLength; // Truncate if fixed length text = this.textPrefix + text; if (this.tokens > 1.0 && length > this.tokens) { const encoded = tokenizer.encode(text); text = tokenizer.decode(encoded.slice(0, this.tokens)); length = this.tokens; } return { output: text, length: length, tooLong: length > maxTokens }; } /** * Calculates the token budget for the prompt section. * @remarks * If the section has a fixed length, the budget will be the minimum of the section's length * and the maximum number of tokens. Otherwise, the budget will be the maximum number of tokens. * @param {number} maxTokens - Maximum number of tokens allowed for the rendered prompt. * @returns {number} The token budget for the prompt section. */ getTokenBudget(maxTokens) { return this.tokens > 1.0 ? Math.min(this.tokens, maxTokens) : maxTokens; } /** * Helper method for returning a list of messages from `renderAsMessages()`. * @remarks * If the section has a fixed length, the function will truncate the list of messages to * fit within the token budget. * @param {Message[]} output - List of messages to return. * @param {number} length Total number of tokens consumed by the list of messages. * @param {Tokenizer} tokenizer Tokenizer to use for encoding/decoding text. * @param {number} maxTokens Maximum number of tokens allowed for the rendered prompt. * @returns {RenderedPromptSection<Message[]>} The rendered prompt section. */ returnMessages(output, length, tokenizer, maxTokens) { // Truncate if fixed length if (this.tokens > 1.0) { while (length > this.tokens) { const msg = output.pop(); const encoded = tokenizer.encode(PromptSectionBase.getMessageText(msg)); length -= encoded.length; if (length < this.tokens) { const delta = this.tokens - length; const truncated = tokenizer.decode(encoded.slice(0, delta)); output.push({ role: msg.role, content: truncated }); length += delta; } } } return { output: output, length: length, tooLong: length > maxTokens }; } /** * Returns the content of a message as a string. * @param {Message} message - Message to get the text of. * @returns {string} The message content as a string. */ static getMessageText(message) { let text = message.content ?? ''; if (Array.isArray(text)) { text = text .filter((part) => part.type === 'text') .map((part) => part.text) .join(' '); } else if (message.function_call) { text = JSON.stringify(message.function_call); } else if (message.name) { text = `${message.name} returned ${text}`; } return text; } } exports.PromptSectionBase = PromptSectionBase; //# sourceMappingURL=PromptSectionBase.js.map