wow, this actually does something

This commit is contained in:
perf3ct 2025-04-07 22:46:54 +00:00
parent b8a6da6d52
commit 2d745c12c8
No known key found for this signature in database
GPG Key ID: 569C4EEC436F5232
3 changed files with 101 additions and 26 deletions

View File

@ -26,6 +26,8 @@ export class ToolCallingStage extends BasePipelineStage<ToolExecutionInput, { re
log.info(`========== TOOL CALLING STAGE ENTRY ==========`);
log.info(`Response provider: ${response.provider}, model: ${response.model || 'unknown'}`);
log.info(`LLM requested ${response.tool_calls?.length || 0} tool calls from provider: ${response.provider}`);
// Check if the response has tool calls
if (!response.tool_calls || response.tool_calls.length === 0) {
// No tool calls, return original response and messages
@ -34,8 +36,6 @@ export class ToolCallingStage extends BasePipelineStage<ToolExecutionInput, { re
return { response, needsFollowUp: false, messages };
}
log.info(`LLM requested ${response.tool_calls.length} tool calls from provider: ${response.provider}`);
// Log response details for debugging
if (response.text) {
log.info(`Response text: "${response.text.substring(0, 200)}${response.text.length > 200 ? '...' : ''}"`);
@ -45,6 +45,12 @@ export class ToolCallingStage extends BasePipelineStage<ToolExecutionInput, { re
const availableTools = toolRegistry.getAllTools();
log.info(`Available tools in registry: ${availableTools.length}`);
// Log available tools for debugging
if (availableTools.length > 0) {
const availableToolNames = availableTools.map(t => t.definition.function.name).join(', ');
log.info(`Available tools: ${availableToolNames}`);
}
if (availableTools.length === 0) {
log.error(`No tools available in registry, cannot execute tool calls`);
// Try to initialize tools as a recovery step
@ -70,8 +76,12 @@ export class ToolCallingStage extends BasePipelineStage<ToolExecutionInput, { re
// Execute each tool call and add results to messages
log.info(`========== STARTING TOOL EXECUTION ==========`);
log.info(`Executing ${response.tool_calls.length} tool calls in parallel`);
const executionStartTime = Date.now();
const toolResults = await Promise.all(response.tool_calls.map(async (toolCall, index) => {
try {
log.info(`========== TOOL CALL ${index + 1} OF ${response.tool_calls.length} ==========`);
log.info(`Tool call ${index + 1} received - Name: ${toolCall.function.name}, ID: ${toolCall.id || 'unknown'}`);
// Log parameters
@ -176,6 +186,10 @@ export class ToolCallingStage extends BasePipelineStage<ToolExecutionInput, { re
}
}));
const totalExecutionTime = Date.now() - executionStartTime;
log.info(`========== TOOL EXECUTION COMPLETE ==========`);
log.info(`Completed execution of ${toolResults.length} tools in ${totalExecutionTime}ms`);
// Add tool results as messages
toolResults.forEach(result => {
// Format the result content based on type

View File

@ -530,28 +530,78 @@ class RestChatService {
log.info(`Tool calls details: ${JSON.stringify(response.tool_calls)}`);
try {
// Execute the tools
const toolResults = await this.executeToolCalls(response);
log.info(`Successfully executed ${toolResults.length} tool calls in advanced context flow`);
let currentMessages = [...aiMessages];
let hasMoreToolCalls = true;
let iterationCount = 0;
const MAX_ITERATIONS = 3; // Prevent infinite loops
// Build updated messages with tool results
const toolMessages = [...aiMessages, {
// Add initial assistant response with tool calls
currentMessages.push({
role: 'assistant',
content: response.text || '',
tool_calls: response.tool_calls
}, ...toolResults];
// Make a follow-up request with the tool results
log.info(`Making follow-up request with ${toolResults.length} tool results`);
const followUpOptions = {...chatOptions, enableTools: false}; // Disable tools for follow-up
const followUpResponse = await service.generateChatCompletion(toolMessages, followUpOptions);
// Update the session with the final response
session.messages.push({
role: 'assistant',
content: followUpResponse.text || '',
timestamp: new Date()
});
while (hasMoreToolCalls && iterationCount < MAX_ITERATIONS) {
iterationCount++;
log.info(`Tool iteration ${iterationCount}/${MAX_ITERATIONS}`);
// Execute the tools
const toolResults = await this.executeToolCalls(response);
log.info(`Successfully executed ${toolResults.length} tool calls in iteration ${iterationCount}`);
// Add tool results to messages
currentMessages = [...currentMessages, ...toolResults];
// Make a follow-up request with the tool results
log.info(`Making follow-up request with ${toolResults.length} tool results`);
const followUpOptions = {...chatOptions, enableTools: iterationCount < MAX_ITERATIONS}; // Enable tools for follow-up but limit iterations
const followUpResponse = await service.generateChatCompletion(currentMessages, followUpOptions);
// Check if the follow-up response has more tool calls
if (followUpResponse.tool_calls && followUpResponse.tool_calls.length > 0) {
log.info(`Follow-up response has ${followUpResponse.tool_calls.length} more tool calls`);
// Add this response to messages for next iteration
currentMessages.push({
role: 'assistant',
content: followUpResponse.text || '',
tool_calls: followUpResponse.tool_calls
});
// Update response for next iteration
response.tool_calls = followUpResponse.tool_calls;
} else {
// No more tool calls, add final response and break loop
log.info(`No more tool calls in follow-up response`);
hasMoreToolCalls = false;
// Update the session with the final response
session.messages.push({
role: 'assistant',
content: followUpResponse.text || '',
timestamp: new Date()
});
}
}
// If we reached the max iterations, add the last response
if (iterationCount >= MAX_ITERATIONS && hasMoreToolCalls) {
log.info(`Reached maximum tool iteration limit of ${MAX_ITERATIONS}`);
// Get the last response we received
const lastResponse = currentMessages
.filter(msg => msg.role === 'assistant')
.pop();
if (lastResponse) {
session.messages.push({
role: 'assistant',
content: lastResponse.content || '',
timestamp: new Date()
});
}
}
} catch (toolError: any) {
log.error(`Error executing tools in advanced context: ${toolError.message}`);

View File

@ -1,12 +1,16 @@
/**
* Tool Initializer
*
*
* This module initializes all available tools for the LLM to use.
*/
import toolRegistry from './tool_registry.js';
import { SearchNotesTool } from './search_notes_tool.js';
import { ReadNoteTool } from './read_note_tool.js';
import { NoteCreationTool } from './note_creation_tool.js';
import { NoteUpdateTool } from './note_update_tool.js';
import { ContentExtractionTool } from './content_extraction_tool.js';
import { RelationshipTool } from './relationship_tool.js';
import log from '../../log.js';
/**
@ -15,16 +19,23 @@ import log from '../../log.js';
export async function initializeTools(): Promise<void> {
try {
log.info('Initializing LLM tools...');
// Register basic notes tools
// Register basic note search and read tools
toolRegistry.registerTool(new SearchNotesTool());
toolRegistry.registerTool(new ReadNoteTool());
// More tools can be registered here
// Register note creation and manipulation tools
toolRegistry.registerTool(new NoteCreationTool());
toolRegistry.registerTool(new NoteUpdateTool());
// Register content analysis tools
toolRegistry.registerTool(new ContentExtractionTool());
toolRegistry.registerTool(new RelationshipTool());
// Log registered tools
const toolCount = toolRegistry.getAllTools().length;
log.info(`Successfully registered ${toolCount} LLM tools`);
const toolNames = toolRegistry.getAllTools().map(tool => tool.definition.function.name).join(', ');
log.info(`Successfully registered ${toolCount} LLM tools: ${toolNames}`);
} catch (error: any) {
log.error(`Error initializing LLM tools: ${error.message || String(error)}`);
// Don't throw, just log the error to prevent breaking the pipeline