Save tool calls to visible chats.
| @@ -3571,7 +3571,9 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3571 | 3571 | } |
| 3572 | 3572 | |
| 3573 | 3573 | // Collect messages with usable content |
| 3574 | 3574 | letconst coreChatcanUseTools = chatToolManager.filterisToolCallingSupported(x => !x.is_system); |
| 3575 | + const canPerformToolCalls = !dryRun && ToolManager.canPerformToolCalls(type); | |
| 3576 | + let coreChat = chat.filter(x => !x.is_system || (canUseTools && Array.isArray(x.extra?.tool_invocations))); | |
| 3575 | 3577 | if (type === 'swipe') { |
| 3576 | 3578 | coreChat.pop(); |
| 3577 | 3579 | } |
| @@ -4406,8 +4408,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4406 | 4408 | getMessage = continue_mag + getMessage; |
| 4407 | 4409 | } |
| 4408 | 4410 | |
| 4409 | 4411 | if (ToolManager.isFunctionCallingSupported()canPerformToolCalls && Array.isArray(streamingProcessor.toolCalls) && streamingProcessor.toolCalls.length) { |
| 4410 | 4412 | const invocations = await ToolManager.checkFunctionToolCallsinvokeFunctionTools(streamingProcessor.toolCalls); |
| 4411 | 4413 | if (Array.isArray(invocations) && invocations.length) { |
| 4412 | 4414 | const lastMessage = chat[chat.length - 1]; |
| 4413 | 4415 | const shouldDeleteMessage = ['', '...'].includes(lastMessage?.mes) && ['', '...'].includes(streamingProcessor.result); |
| @@ -4455,14 +4457,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4455 | 4457 | throw new Error(data?.response); |
| 4456 | 4458 | } |
| 4457 | 4459 | |
| 4458 | - if (ToolManager.isFunctionCallingSupported()) { | |
| 4459 | - const invocations = await ToolManager.checkFunctionToolCalls(data); | |
| 4460 | - if (Array.isArray(invocations) && invocations.length) { | |
| 4461 | - ToolManager.saveFunctionToolInvocations(invocations); | |
| 4462 | - return Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName }, dryRun); | |
| 4463 | - } | |
| 4464 | - } | |
| 4465 | - | |
| 4466 | 4460 | //const getData = await response.json(); |
| 4467 | 4461 | let getMessage = extractMessageFromData(data); |
| 4468 | 4462 | let title = extractTitleFromData(data); |
| @@ -4502,6 +4496,16 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4502 | 4496 | parseAndSaveLogprobs(data, continue_mag); |
| 4503 | 4497 | } |
| 4504 | 4498 | |
| 4499 | + if (canPerformToolCalls) { | |
| 4500 | + const invocations = await ToolManager.invokeFunctionTools(data); | |
| 4501 | + if (Array.isArray(invocations) && invocations.length) { | |
| 4502 | + const shouldDeleteMessage = ['', '...'].includes(getMessage); | |
| 4503 | + shouldDeleteMessage && await deleteLastMessage(); | |
| 4504 | + ToolManager.saveFunctionToolInvocations(invocations); | |
| 4505 | + return Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName }, dryRun); | |
| 4506 | + } | |
| 4507 | + } | |
| 4508 | + | |
| 4505 | 4509 | if (type !== 'quiet') { |
| 4506 | 4510 | playMessageSound(); |
| 4507 | 4511 | } |
| @@ -703,7 +703,7 @@ async function populateChatHistory(messages, prompts, chatCompletion, type = nul | ||
| 703 | 703 | } |
| 704 | 704 | |
| 705 | 705 | const imageInlining = isImageInliningSupported(); |
| 706 | 706 | const toolCallingcanUseTools = ToolManager.isFunctionCallingSupportedisToolCallingSupported(); |
| 707 | 707 | |
| 708 | 708 | // Insert chat messages as long as there is budget available |
| 709 | 709 | const chatPool = [...messages].reverse(); |
| @@ -725,10 +725,10 @@ async function populateChatHistory(messages, prompts, chatCompletion, type = nul | ||
| 725 | 725 | await chatMessage.addImage(chatPrompt.image); |
| 726 | 726 | } |
| 727 | 727 | |
| 728 | 728 | if (toolCallingcanUseTools && Array.isArray(chatPrompt.invocations)) { |
| 729 | 729 | /** @type {import('./tool-calling.js').ToolInvocation[]} */ |
| 730 | 730 | const invocations = chatPrompt.invocations; |
| 731 | 731 | const toolCallMessage = new Message('assistant'chatMessage.role, undefined, 'toolCall-' + chatMessage.identifier); |
| 732 | 732 | toolCallMessage.setToolCalls(invocations); |
| 733 | 733 | if (chatCompletion.canAfford(toolCallMessage)) { |
| 734 | 734 | chatCompletion.reserveBudget(toolCallMessage); |
| @@ -1285,7 +1285,7 @@ export async function prepareOpenAIMessages({ | ||
| 1285 | 1285 | const eventData = { chat, dryRun }; |
| 1286 | 1286 | await eventSource.emit(event_types.CHAT_COMPLETION_PROMPT_READY, eventData); |
| 1287 | 1287 | |
| 1288 | 1288 | openai_messages_count = chat.filter(x => !x?.tool_calls && (x?.role === 'user' || x?.role === 'assistant'))?.length || 0; |
| 1289 | 1289 | |
| 1290 | 1290 | return [chat, promptManager.tokenHandler.counts]; |
| 1291 | 1291 | } |
| @@ -1886,7 +1886,7 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1886 | 1886 | generate_data['seed'] = oai_settings.seed; |
| 1887 | 1887 | } |
| 1888 | 1888 | |
| 1889 | 1889 | if (!canMultiSwipe && ToolManager.isFunctionCallingSupportedcanPerformToolCalls(type)) { |
| 1890 | 1890 | await ToolManager.registerFunctionToolsOpenAI(generate_data); |
| 1891 | 1891 | } |
| 1892 | 1892 | |
| @@ -2393,13 +2393,20 @@ class MessageCollection { | ||
| 2393 | 2393 | } |
| 2394 | 2394 | |
| 2395 | 2395 | /** |
| 2396 | 2396 | * Get chat in the format of {role, name, content, tool_calls}. |
| 2397 | 2397 | * @returns {Array} Array of objects with role, name, and content properties. |
| 2398 | 2398 | */ |
| 2399 | 2399 | getChat() { |
| 2400 | 2400 | return this.collection.reduce((acc, message) => { |
| 2401 | - const name = message.name; | |
| 2401 | + if (message.content || message.tool_calls) { | |
| 2402 | - if (message.content) acc.push({ role: message.role, ...(name && { name }), content: message.content }); | |
| 2402 | + acc.push({ | |
| 2403 | + role: message.role, | |
| 2404 | + content: message.content, | |
| 2405 | + ...(message.name && { name: message.name }), | |
| 2406 | + ...(message.tool_calls && { tool_calls: message.tool_calls }), | |
| 2407 | + ...(message.role === 'tool' && { tool_call_id: message.identifier }), | |
| 2408 | + }); | |
| 2409 | + } | |
| 2403 | 2410 | return acc; |
| 2404 | 2411 | }, []); |
| 2405 | 2412 | } |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | import { addOneMessage, chat, main_api, system_avatar, systemUserName } from '../script.js'; |
| 2 | 2 | import { chat_completion_sources, oai_settings } from './openai.js'; |
| 3 | 3 | |
| 4 | 4 | /** |
| @@ -243,12 +243,12 @@ export class ToolManager { | ||
| 243 | 243 | } |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | - static isFunctionCallingSupported() { | |
| 246 | + /** | |
| 247 | - if (main_api !== 'openai') { | |
| 247 | + * Checks if tool calling is supported for the current settings and generation type. | |
| 248 | - return false; | |
| 248 | + * @returns {boolean} Whether tool calling is supported for the given type | |
| 249 | - } | |
| 249 | + */ | |
| 250 | - | |
| 250 | + static isToolCallingSupported() { | |
| 251 | 251 | if (main_api !== 'openai' || !oai_settings.function_calling) { |
| 252 | 252 | return false; |
| 253 | 253 | } |
| 254 | 254 | |
| @@ -264,6 +264,22 @@ export class ToolManager { | ||
| 264 | 264 | return supportedSources.includes(oai_settings.chat_completion_source); |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | + /** | |
| 268 | + * Checks if tool calls can be performed for the current settings and generation type. | |
| 269 | + * @param {string} type Generation type | |
| 270 | + * @returns {boolean} Whether tool calls can be performed for the given type | |
| 271 | + */ | |
| 272 | + static canPerformToolCalls(type) { | |
| 273 | + const noToolCallTypes = ['swipe', 'impersonate', 'quiet', 'continue']; | |
| 274 | + const isSupported = ToolManager.isToolCallingSupported(); | |
| 275 | + return isSupported && !noToolCallTypes.includes(type); | |
| 276 | + } | |
| 277 | + | |
| 278 | + /** | |
| 279 | + * Utility function to get tool calls from the response data. | |
| 280 | + * @param {any} data Response data | |
| 281 | + * @returns {any[]} Tool calls from the response data | |
| 282 | + */ | |
| 267 | 283 | static #getToolCallsFromData(data) { |
| 268 | 284 | // Parsed tool calls from streaming data |
| 269 | 285 | if (Array.isArray(data) && data.length > 0) { |
| @@ -290,15 +306,11 @@ export class ToolManager { | ||
| 290 | 306 | * @param {any} data Reply data |
| 291 | 307 | * @returns {Promise<ToolInvocation[]>} Successful tool invocations |
| 292 | 308 | */ |
| 293 | 309 | static async checkFunctionToolCallsinvokeFunctionTools(data) { |
| 294 | - if (!ToolManager.isFunctionCallingSupported()) { | |
| 295 | - return []; | |
| 296 | - } | |
| 297 | - | |
| 298 | 310 | /** @type {ToolInvocation[]} */ |
| 299 | 311 | const invocations = []; |
| 300 | 312 | const toolCalls = ToolManager.#getToolCallsFromData(data); |
| 301 | 313 | const oaiCompatoaiCompatibleSources = [ |
| 302 | 314 | chat_completion_sources.OPENAI, |
| 303 | 315 | chat_completion_sources.CUSTOM, |
| 304 | 316 | chat_completion_sources.MISTRALAI, |
| @@ -306,7 +318,7 @@ export class ToolManager { | ||
| 306 | 318 | chat_completion_sources.GROQ, |
| 307 | 319 | ]; |
| 308 | 320 | |
| 309 | 321 | if (oaiCompatoaiCompatibleSources.includes(oai_settings.chat_completion_source)) { |
| 310 | 322 | if (!Array.isArray(toolCalls)) { |
| 311 | 323 | return []; |
| 312 | 324 | } |
| @@ -323,7 +335,7 @@ export class ToolManager { | ||
| 323 | 335 | |
| 324 | 336 | toastr.info('Invoking function tool: ' + name); |
| 325 | 337 | const result = await ToolManager.invokeFunctionTool(name, parameters); |
| 326 | 338 | toastrconsole.infolog('Function tool result: ' +, result); |
| 327 | 339 | |
| 328 | 340 | // Save a successful invocation |
| 329 | 341 | if (result) { |
| @@ -367,15 +379,19 @@ export class ToolManager { | ||
| 367 | 379 | * @param {ToolInvocation[]} invocations Successful tool invocations |
| 368 | 380 | */ |
| 369 | 381 | static saveFunctionToolInvocations(invocations) { |
| 370 | - for (let index = chat.length - 1; index >= 0; index--) { | |
| 382 | + const toolNames = invocations.map(i => i.name).join(', '); | |
| 371 | 383 | const message = chat[index];{ |
| 372 | - if (message.is_user) { | |
| 384 | + name: systemUserName, | |
| 373 | - if (!message.extra || typeof message.extra !== 'object') { | |
| 385 | + force_avatar: system_avatar, | |
| 374 | - message.extra = {}; | |
| 386 | + is_system: true, | |
| 375 | - } | |
| 387 | + is_user: false, | |
| 376 | - message.extra.tool_invocations = invocations; | |
| 388 | + mes: `Performed tool calls: ${toolNames}`, | |
| 377 | - break; | |
| 389 | + extra: { | |
| 378 | - } | |
| 390 | + isSmallSys: true, | |
| 379 | - } | |
| 391 | + tool_invocations: invocations, | |
| 392 | + }, | |
| 393 | + }; | |
| 394 | + chat.push(message); | |
| 395 | + addOneMessage(message); | |
| 380 | 396 | } |
| 381 | 397 | } |