UNPKG

@copilotkit/runtime

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

189 lines (187 loc) 5.87 kB
import "reflect-metadata"; import { parseJson } from "@copilotkit/shared"; //#region src/service-adapters/openai/utils.ts /** * Type guard: checks whether the OpenAI client has the v4-era `beta.chat` * namespace. Returns `false` for v5+ clients where `beta.chat` was removed. */ function hasV4BetaChat(beta) { return beta != null && "chat" in beta && beta.chat != null; } /** * Detects whether the provided OpenAI client is v5+ by checking for the * removal of the `beta.chat` namespace (which was promoted to `chat` in v5). */ function isOpenAIV5(openai) { return !hasV4BetaChat(openai.beta); } /** * Returns the chat completions object that supports `.stream()`. * In v4 this lives under `openai.beta.chat.completions`; * in v5 it was promoted to `openai.chat.completions`. */ function getChatCompletionsForStreaming(openai) { if (hasV4BetaChat(openai.beta)) return openai.beta.chat.completions; return openai.chat.completions; } /** * Retrieves a thread run, handling the v4→v5 API signature change. * v4: retrieve(threadId, runId) * v5: retrieve(runId, { thread_id: threadId }) */ async function retrieveThreadRun(openai, threadId, runId) { if (isOpenAIV5(openai)) { const retrieve = openai.beta.threads.runs.retrieve; return retrieve(runId, { thread_id: threadId }); } return openai.beta.threads.runs.retrieve(threadId, runId); } /** * Submits tool outputs as a stream, handling the v4→v5 API signature change. * v4: submitToolOutputsStream(threadId, runId, body) * v5: submitToolOutputsStream(runId, { thread_id, ...body }) */ function submitToolOutputsStream(openai, threadId, runId, body) { if (isOpenAIV5(openai)) { const submit = openai.beta.threads.runs.submitToolOutputsStream; return submit(runId, { thread_id: threadId, ...body }); } return openai.beta.threads.runs.submitToolOutputsStream(threadId, runId, body); } function limitMessagesToTokenCount(messages, tools, model, maxTokens) { maxTokens ||= maxTokensForOpenAIModel(model); const result = []; const toolsNumTokens = countToolsTokens(model, tools); if (toolsNumTokens > maxTokens) throw new Error(`Too many tokens in function definitions: ${toolsNumTokens} > ${maxTokens}`); maxTokens -= toolsNumTokens; for (const message of messages) if (["system", "developer"].includes(message.role)) { const numTokens = countMessageTokens(model, message); maxTokens -= numTokens; if (maxTokens < 0) throw new Error("Not enough tokens for system message."); } let cutoff = false; const reversedMessages = [...messages].toReversed(); for (const message of reversedMessages) { if (["system", "developer"].includes(message.role)) { result.unshift(message); continue; } else if (cutoff) continue; let numTokens = countMessageTokens(model, message); if (maxTokens < numTokens) { cutoff = true; continue; } result.unshift(message); maxTokens -= numTokens; } return result; } function maxTokensForOpenAIModel(model) { return maxTokensByModel[model] || DEFAULT_MAX_TOKENS; } const DEFAULT_MAX_TOKENS = 128e3; const maxTokensByModel = { o1: 2e5, "o1-2024-12-17": 2e5, "o1-mini": 128e3, "o1-mini-2024-09-12": 128e3, "o1-preview": 128e3, "o1-preview-2024-09-12": 128e3, "o3-mini": 2e5, "o3-mini-2025-01-31": 2e5, "gpt-4o": 128e3, "chatgpt-4o-latest": 128e3, "gpt-4o-2024-08-06": 128e3, "gpt-4o-2024-05-13": 128e3, "gpt-4o-mini": 128e3, "gpt-4o-mini-2024-07-18": 128e3, "gpt-4-turbo": 128e3, "gpt-4-turbo-2024-04-09": 128e3, "gpt-4-0125-preview": 128e3, "gpt-4-turbo-preview": 128e3, "gpt-4-1106-preview": 128e3, "gpt-4-vision-preview": 128e3, "gpt-4-1106-vision-preview": 128e3, "gpt-4-32k": 32768, "gpt-4-32k-0613": 32768, "gpt-4-32k-0314": 32768, "gpt-4": 8192, "gpt-4-0613": 8192, "gpt-4-0314": 8192, "gpt-3.5-turbo-0125": 16385, "gpt-3.5-turbo": 16385, "gpt-3.5-turbo-1106": 16385, "gpt-3.5-turbo-instruct": 4096, "gpt-3.5-turbo-16k": 16385, "gpt-3.5-turbo-0613": 4096, "gpt-3.5-turbo-16k-0613": 16385, "gpt-3.5-turbo-0301": 4097 }; function countToolsTokens(model, tools) { if (tools.length === 0) return 0; return countTokens(model, JSON.stringify(tools)); } function countMessageTokens(model, message) { return countTokens(model, message.content || ""); } function countTokens(model, text) { return text.length / 3; } function convertActionInputToOpenAITool(action) { return { type: "function", function: { name: action.name, description: action.description, parameters: parseJson(action.jsonSchema, {}) } }; } function convertMessageToOpenAIMessage(message, options) { const { keepSystemRole } = options || { keepSystemRole: false }; if (message.isTextMessage()) { let role = message.role; if (message.role === "system" && !keepSystemRole) role = "developer"; return { role, content: message.content }; } else if (message.isImageMessage()) return { role: "user", content: [{ type: "image_url", image_url: { url: `data:image/${message.format};base64,${message.bytes}` } }] }; else if (message.isActionExecutionMessage()) return { role: "assistant", tool_calls: [{ id: message.id, type: "function", function: { name: message.name, arguments: JSON.stringify(message.arguments) } }] }; else if (message.isResultMessage()) return { role: "tool", content: message.result, tool_call_id: message.actionExecutionId }; } function convertSystemMessageToAssistantAPI(message) { return { ...message, ...["system", "developer"].includes(message.role) && { role: "assistant", content: "THE FOLLOWING MESSAGE IS A SYSTEM MESSAGE: " + message.content } }; } //#endregion export { convertActionInputToOpenAITool, convertMessageToOpenAIMessage, convertSystemMessageToAssistantAPI, getChatCompletionsForStreaming, limitMessagesToTokenCount, retrieveThreadRun, submitToolOutputsStream }; //# sourceMappingURL=utils.mjs.map