UNPKG

@jackhua/mini-langchain

Version:

A lightweight TypeScript implementation of LangChain with cost optimization features

201 lines • 6.07 kB
"use strict"; /** * Built-in debugging and development tools */ Object.defineProperty(exports, "__esModule", { value: true }); exports.LLMInspector = exports.ChainDebugger = void 0; /** * Chain debugger for development */ class ChainDebugger { constructor() { this.logs = []; this.breakpoints = new Set(); } /** * Wrap a chain with debugging capabilities */ wrap(chain) { const debugChain = Object.create(chain); const originalCall = chain.call.bind(chain); debugChain.call = async (inputs) => { const startTime = Date.now(); const chainName = chain.constructor.name; this.log({ type: 'chain-start', chainName, inputs, timestamp: new Date() }); // Check breakpoint if (this.breakpoints.has(chainName)) { await this.pause(chainName, inputs); } try { const result = await originalCall(inputs); this.log({ type: 'chain-end', chainName, outputs: result, duration: Date.now() - startTime, timestamp: new Date() }); return result; } catch (error) { this.log({ type: 'chain-error', chainName, error: error.message || String(error), timestamp: new Date() }); throw error; } }; return debugChain; } /** * Set a breakpoint on a chain */ setBreakpoint(chainName) { this.breakpoints.add(chainName); } /** * Remove a breakpoint */ removeBreakpoint(chainName) { this.breakpoints.delete(chainName); } /** * Pause execution at breakpoint */ async pause(chainName, inputs) { console.log(`\nšŸ”“ Breakpoint hit in ${chainName}`); console.log('Inputs:', JSON.stringify(inputs, null, 2)); console.log('\nPress Enter to continue...'); // Wait for user input in Node.js environment if (typeof process !== 'undefined' && process.stdin) { await new Promise(resolve => { process.stdin.once('data', resolve); }); } } /** * Log debug information */ log(entry) { this.logs.push(entry); if (process.env.DEBUG === 'true') { this.printLog(entry); } } /** * Print formatted log */ printLog(entry) { const timestamp = entry.timestamp.toISOString(); switch (entry.type) { case 'chain-start': console.log(`[${timestamp}] šŸ”µ ${entry.chainName} started`); console.log(` Inputs: ${JSON.stringify(entry.inputs)}`); break; case 'chain-end': console.log(`[${timestamp}] 🟢 ${entry.chainName} completed (${entry.duration}ms)`); console.log(` Outputs: ${JSON.stringify(entry.outputs)}`); break; case 'chain-error': console.log(`[${timestamp}] šŸ”“ ${entry.chainName} failed`); console.log(` Error: ${entry.error}`); break; } } /** * Get all logs */ getLogs() { return this.logs; } /** * Clear logs */ clearLogs() { this.logs = []; } /** * Export logs to file */ exportLogs(filepath) { const fs = require('fs'); fs.writeFileSync(filepath, JSON.stringify(this.logs, null, 2)); } } exports.ChainDebugger = ChainDebugger; /** * LLM call inspector */ class LLMInspector { constructor() { this.callHistory = []; } /** * Wrap an LLM with inspection capabilities */ wrap(llm) { const inspectedLLM = Object.create(llm); const originalGenerate = llm.generate.bind(llm); inspectedLLM.generate = async (messages, options) => { const startTime = Date.now(); const call = { provider: llm.constructor.name, messages, startTime: new Date(), success: false, tokenCount: this.estimateTokens(messages) }; try { const result = await originalGenerate(messages, options); call.response = result; call.duration = Date.now() - startTime; call.success = true; this.callHistory.push(call); this.printCall(call); return result; } catch (error) { call.error = error.message || String(error); call.success = false; call.duration = Date.now() - startTime; this.callHistory.push(call); this.printCall(call); throw error; } }; return inspectedLLM; } /** * Estimate token count (simple approximation) */ estimateTokens(messages) { const text = messages.map(m => m.content).join(' '); // Rough estimation: 1 token ā‰ˆ 4 characters return Math.ceil(text.length / 4); } /** * Print LLM call details */ printCall(call) { if (process.env.DEBUG_LLM === 'true') { console.log('\n=== LLM Call ==='); console.log(`Provider: ${call.provider}`); console.log(`Start: ${call.startTime.toISOString()}`); console.log(`Duration: ${call.duration}ms`); console.log(`Success: ${call.success}`); if (call.error) { console.log(`Error: ${call.error}`); } console.log('================\n'); } } } exports.LLMInspector = LLMInspector; //# sourceMappingURL=debugger.js.map