@jackhua/mini-langchain
Version:
A lightweight TypeScript implementation of LangChain with cost optimization features
201 lines ⢠6.07 kB
JavaScript
;
/**
* 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