UNPKG

@cognigy/rest-api-client

Version:

Cognigy REST-Client

203 lines (199 loc) 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertChatToPrompt = exports.writeLLMDebugLogs = exports.createLastUserInputString = exports.createLastConversationChatObject = exports.createLastConverationString = exports.createInvalidAnswerPrompt = exports.createQuestionPrompt = exports.createExtractionPrompt = void 0; const createExtractionPrompt = (slots, lastConversationEntries) => { const userInput = lastConversationEntries.filter(entry => entry.source === "user").map(entry => "- " + entry.text).join("\n"); const conversation = (0, exports.createLastConverationString)(lastConversationEntries); let slotDescriptions = ""; let foundSlotDescriptions = ""; for (const slot of slots) { if (!slot.value || slot.invalid) { slotDescriptions += `- KEY: ${slot.tag}, DESCRIPTION: ${slot.optional ? "(if explicitly mentioned) " : ""}${slot.description}\n`; } else { foundSlotDescriptions += `- KEY: ${slot.tag}, DESCRIPTION: ${slot.description}, FOUND: ${slot.value}\n`; } } const prompt = `A USER has interacted with a BOT, this is the conversation so far: ${conversation} ${foundSlotDescriptions.length > 0 ? `\nSo far, the BOT has found the following entities:\n${foundSlotDescriptions}` : ""} Try to fill the following entities from the USER input, each entity has to match the given description field. If the value does not strictly match this description, leave the value empty: ${slotDescriptions} Return the extracted entities as a valid JSON object, where the keys are the entity tags and the values are the extracted values.`; return prompt; }; exports.createExtractionPrompt = createExtractionPrompt; const createQuestionPrompt = (foundSlots, missingSlots, lastConversationEntries) => { const conversation = (0, exports.createLastConverationString)(lastConversationEntries); const missingSlotDescriptions = missingSlots.map(slot => `- KEY: ${slot.tag}, DESCRIPTION: ${slot.description}`).join("\n"); const foundSlotDescriptions = foundSlots.map(slot => `- KEY: ${slot.tag}, DESCRIPTION: ${slot.description}, FOUND: ${slot.value}`).join("\n"); const prompt = `A user has interacted with a bot, this is the conversation so far: ${conversation} ${foundSlots.length > 0 ? `So far, the BOT has found the following entities:\n${foundSlotDescriptions}` : ""} The BOT wants to find the following entities: ${missingSlotDescriptions} The BOT asks the user to for this information, based on the conversation so far. The BOT outputs should not be repetitive. BOT: `; return prompt; }; exports.createQuestionPrompt = createQuestionPrompt; const createInvalidAnswerPrompt = (invalidSlots, lastConversationEntries) => { const userInput = (0, exports.createLastConverationString)(lastConversationEntries); const invalidSlotDescription = `- KEY: ${invalidSlots[0].tag}, DESCRIPTION: ${invalidSlots[0].description}, USER INPUT: ${invalidSlots[0].value}, INVALID BECAUSE: ${invalidSlots[0].validation.invalidReason}\n`; const prompt = `A user has interacted with a bot, this is the conversation so far: ${userInput} The USER has provided the following entities, but the USER INPUT was INVALID BECAUSE: ${invalidSlotDescription} The BOT explains the answer why he can't use the answer and asks the USER again for this information, based on the conversation so far. The BOT does not give explicit alternatives.: BOT: `; invalidSlots[0].invalid = false; invalidSlots[0].value = ""; return prompt; }; exports.createInvalidAnswerPrompt = createInvalidAnswerPrompt; /* returns recentConversation as a multiline string: - BOT: Hello - USER: Hi */ const createLastConverationString = (lastConversationEntries, turnLimit = 100) => { const conversation = lastConversationEntries === null || lastConversationEntries === void 0 ? void 0 : lastConversationEntries.map(entry => "- " + (entry.source === "user" ? "USER: " : "BOT: ") + entry.text).slice(0, turnLimit).reverse().join("\n"); return conversation || ""; }; exports.createLastConverationString = createLastConverationString; /* returns recentConversation as an openai formatted chat prompt, e.g. [ { "role": "system", "content": "Imagine you're Michael and you're working in a agency for insurance sales for CNP Santander Insurance Europe. Your job is to call customers who have just gotten a loan from a bank. Your job is to sell them loan default insurance.\n\nIt's important you act tactfully and slowly approach the topic. Your main goal is to get the customer to confirm they want to the insurance, but don't be pushy.\n\nThe customer name is Vito Volpe. The loan amount for this customer is 10000 and the cost for the insurance is 0.89% of the loan amount per year, paid with the insurance payments. The customer can opt out at any time. \n\nOnce the customer is has confirmed they want the insurance, answer with \"SUCCESS\" only.\nIf the customer wants to reschedule the call, confirm the time and then answer with \"RESCHEDULE\" only.\n\nDon't immediately start with the offer. Make sure the customer is comfortable first.\n\nDon't discuss other insurance products. Don't negotiate on pricing.\n\nUse simple wording only. Speak in short sentences." }, { "role": "user", "content": "Hello?" }, { "role": "assistant", "content": "Good day, is this Mr. Vito Volpe I am speaking with?" } ] */ const createLastConversationChatObject = (lastConversationEntries, systemMessage, turnLimit = 100, limitToOnlyUserMessages) => { const conversation = []; if (systemMessage) { conversation.push({ role: "system", content: systemMessage }); } if (limitToOnlyUserMessages) { // limit the conversation entries to the last X messages with source user lastConversationEntries === null || lastConversationEntries === void 0 ? void 0 : lastConversationEntries.filter(entry => entry.source === "user").slice(0, turnLimit).reverse().map(entry => { var _a, _b; if ((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.text) === null || _a === void 0 ? void 0 : _a.trim()) === null || _b === void 0 ? void 0 : _b.length) { conversation.push({ role: "user", content: entry.text.trim() }); } }); } else { lastConversationEntries === null || lastConversationEntries === void 0 ? void 0 : lastConversationEntries.slice(0, turnLimit).reverse().map(entry => { var _a, _b; // if text exists, add to conversation // necessary to prevent data only messages from being added if ((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.text) === null || _a === void 0 ? void 0 : _a.trim()) === null || _b === void 0 ? void 0 : _b.length) { conversation.push({ role: entry.source === "user" ? "user" : "assistant", content: entry.text.trim() }); } }); } return conversation; }; exports.createLastConversationChatObject = createLastConversationChatObject; /* returns recentUserInput as a multiline string: - Hi - I want to order... */ const createLastUserInputString = (lastConversationEntries, turnLimit = 100) => { const userInput = lastConversationEntries.filter(entry => entry.source === "user").map(entry => "- " + entry.text).slice(0, turnLimit).reverse().join("\n"); return userInput || ""; }; exports.createLastUserInputString = createLastUserInputString; /** * Writes debug logs for LLM calls * @param label the label of the log * @param prompt the prompt used for the LLM call * @param response the response of the LLM call * @param debugLogTokenCount whether to log the token count * @param debugLogRequestAndCompletion whether to log the request and completion * @param cognigy the cognigy object (input, api, etc) */ const writeLLMDebugLogs = async (label, prompt, response, debugLogTokenCount, debugLogRequestAndCompletion, cognigy) => { var _a, _b, _c, _d; const { api, input } = cognigy; if (input.endpointType !== "adminconsole" && !api.getMetadata().isFollowSessionActive) { // only return logs if in interaction panel or following session return; } // stringify the response if it is an object const responseOutputFormatted = typeof response === "object" ? JSON.stringify(response.result || response, null, 4) : response; // debug logs are only processed for the interaction panel if (debugLogRequestAndCompletion) { try { let requestTokenMessage = ""; let completionTokenMessage = ""; if (debugLogTokenCount) { if (prompt) { const requestTokens = (_a = response === null || response === void 0 ? void 0 : response.tokenUsage) === null || _a === void 0 ? void 0 : _a.inputTokens; requestTokenMessage = ` (${requestTokens} Tokens)`; } if (response) { const completionTokens = (_b = response === null || response === void 0 ? void 0 : response.tokenUsage) === null || _b === void 0 ? void 0 : _b.outputTokens; completionTokenMessage = ` (${completionTokens} Tokens)`; } } api.logDebugMessage(`UI__DEBUG_MODE__LLM_PROMPT__FULL_REQUEST__REQUEST${requestTokenMessage}:<br>${prompt}<br><br>UI__DEBUG_MODE__LLM_PROMPT__FULL_REQUEST__COMPLETION${completionTokenMessage}:<br>${responseOutputFormatted}`, "UI__DEBUG_MODE__LLM_PROMPT__FULL_REQUEST__HEADER"); } catch (err) { } } else if (debugLogTokenCount) { try { let requestTokens = 0; let completionTokens = 0; requestTokens = (_c = response.tokenUsage) === null || _c === void 0 ? void 0 : _c.inputTokens; completionTokens = (_d = response.tokenUsage) === null || _d === void 0 ? void 0 : _d.outputTokens; const requestTokenMessage = requestTokens || "unknown"; const completionTokenMessage = completionTokens || "unknown"; const totalTokens = (requestTokens + completionTokens) || "unknown"; const completionMessage = response ? `<br>UI__DEBUG_MODE__LLM_PROMPT__TOKEN_COUNT__COMPLETION_TOKENS: ${completionTokenMessage}<br>UI__DEBUG_MODE__LLM_PROMPT__TOKEN_COUNT__TOTAL_TOKENS: ${totalTokens}` : ""; api.logDebugMessage(`UI__DEBUG_MODE__LLM_PROMPT__TOKEN_COUNT__REQUEST_TOKENS: ${requestTokenMessage}${completionMessage}`, "UI__DEBUG_MODE__LLM_PROMPT__TOKEN_COUNT__HEADER"); } catch (err) { } } }; exports.writeLLMDebugLogs = writeLLMDebugLogs; /** * Converts an OpenAI chat object to a prompt string * @param chat The OpenAI Chat Object * @returns The concatenated string */ const convertChatToPrompt = (chat) => { let prompt = ""; for (const message of chat) { if (message.role === "system") { prompt += `${message.content}\n`; } else if (message.role === "user") { prompt += `user: ${message.content}\n`; } else if (message.role === "assistant") { prompt += `assistant: ${message.content}\n`; } } prompt += "assistant: "; return prompt; }; exports.convertChatToPrompt = convertChatToPrompt; //# sourceMappingURL=prompt.js.map