248 lines
8.2 KiB
JavaScript
248 lines
8.2 KiB
JavaScript
|
"use strict";
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.LLMonitorHandler = exports.convertToLLMonitorMessages = void 0;
|
||
|
const llmonitor_1 = __importDefault(require("llmonitor"));
|
||
|
const env_1 = require("@langchain/core/utils/env");
|
||
|
const base_1 = require("@langchain/core/callbacks/base");
|
||
|
// Langchain Helpers
|
||
|
// Input can be either a single message, an array of message, or an array of array of messages (batch requests)
|
||
|
const parseRole = (id) => {
|
||
|
const roleHint = id[id.length - 1];
|
||
|
if (roleHint.includes("Human"))
|
||
|
return "user";
|
||
|
if (roleHint.includes("System"))
|
||
|
return "system";
|
||
|
if (roleHint.includes("AI"))
|
||
|
return "ai";
|
||
|
if (roleHint.includes("Function"))
|
||
|
return "function";
|
||
|
if (roleHint.includes("Tool"))
|
||
|
return "tool";
|
||
|
return "ai";
|
||
|
};
|
||
|
const PARAMS_TO_CAPTURE = [
|
||
|
"stop",
|
||
|
"stop_sequences",
|
||
|
"function_call",
|
||
|
"functions",
|
||
|
"tools",
|
||
|
"tool_choice",
|
||
|
"response_format",
|
||
|
];
|
||
|
const convertToLLMonitorMessages = (input) => {
|
||
|
const parseMessage = (raw) => {
|
||
|
if (typeof raw === "string")
|
||
|
return raw;
|
||
|
// sometimes the message is nested in a "message" property
|
||
|
if ("message" in raw)
|
||
|
return parseMessage(raw.message);
|
||
|
// Serialize
|
||
|
const message = JSON.parse(JSON.stringify(raw));
|
||
|
try {
|
||
|
// "id" contains an array describing the constructor, with last item actual schema type
|
||
|
const role = parseRole(message.id);
|
||
|
const obj = message.kwargs;
|
||
|
const text = message.text ?? obj.content;
|
||
|
return {
|
||
|
role,
|
||
|
text,
|
||
|
...(obj.additional_kwargs ?? {}),
|
||
|
};
|
||
|
}
|
||
|
catch (e) {
|
||
|
// if parsing fails, return the original message
|
||
|
return message.text ?? message;
|
||
|
}
|
||
|
};
|
||
|
if (Array.isArray(input)) {
|
||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
|
// @ts-ignore Confuses the compiler
|
||
|
return input.length === 1
|
||
|
? (0, exports.convertToLLMonitorMessages)(input[0])
|
||
|
: input.map(exports.convertToLLMonitorMessages);
|
||
|
}
|
||
|
return parseMessage(input);
|
||
|
};
|
||
|
exports.convertToLLMonitorMessages = convertToLLMonitorMessages;
|
||
|
const parseInput = (rawInput) => {
|
||
|
if (!rawInput)
|
||
|
return null;
|
||
|
const { input, inputs, question } = rawInput;
|
||
|
if (input)
|
||
|
return input;
|
||
|
if (inputs)
|
||
|
return inputs;
|
||
|
if (question)
|
||
|
return question;
|
||
|
return rawInput;
|
||
|
};
|
||
|
const parseOutput = (rawOutput) => {
|
||
|
if (!rawOutput)
|
||
|
return null;
|
||
|
const { text, output, answer, result } = rawOutput;
|
||
|
if (text)
|
||
|
return text;
|
||
|
if (answer)
|
||
|
return answer;
|
||
|
if (output)
|
||
|
return output;
|
||
|
if (result)
|
||
|
return result;
|
||
|
return rawOutput;
|
||
|
};
|
||
|
const parseExtraAndName = (llm, extraParams, metadata) => {
|
||
|
const params = {
|
||
|
...(extraParams?.invocation_params ?? {}),
|
||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
|
// @ts-ignore this is a valid property
|
||
|
...(llm?.kwargs ?? {}),
|
||
|
...(metadata || {}),
|
||
|
};
|
||
|
const { model, model_name, modelName, model_id, userId, userProps, ...rest } = params;
|
||
|
const name = model || modelName || model_name || model_id || llm.id.at(-1);
|
||
|
// Filter rest to only include params we want to capture
|
||
|
const extra = Object.fromEntries(Object.entries(rest).filter(([key]) => PARAMS_TO_CAPTURE.includes(key) ||
|
||
|
["string", "number", "boolean"].includes(typeof rest[key])));
|
||
|
return { name, extra, userId, userProps };
|
||
|
};
|
||
|
/**
|
||
|
* @deprecated Please use LunaryHandler instead:
|
||
|
* ```
|
||
|
* import { LunaryHandler } from "@langchain/community/callbacks/handlers/lunary";
|
||
|
* ```
|
||
|
*/
|
||
|
class LLMonitorHandler extends base_1.BaseCallbackHandler {
|
||
|
constructor(fields = {}) {
|
||
|
super(fields);
|
||
|
Object.defineProperty(this, "name", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: "llmonitor_handler"
|
||
|
});
|
||
|
Object.defineProperty(this, "monitor", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: void 0
|
||
|
});
|
||
|
this.monitor = llmonitor_1.default;
|
||
|
if (fields) {
|
||
|
const { appId, apiUrl, verbose } = fields;
|
||
|
this.monitor.init({
|
||
|
verbose,
|
||
|
appId: appId ?? (0, env_1.getEnvironmentVariable)("LLMONITOR_APP_ID"),
|
||
|
apiUrl: apiUrl ?? (0, env_1.getEnvironmentVariable)("LLMONITOR_API_URL"),
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata) {
|
||
|
const { name, extra, userId, userProps } = parseExtraAndName(llm, extraParams, metadata);
|
||
|
await this.monitor.trackEvent("llm", "start", {
|
||
|
runId,
|
||
|
parentRunId,
|
||
|
name,
|
||
|
input: (0, exports.convertToLLMonitorMessages)(prompts),
|
||
|
extra,
|
||
|
userId,
|
||
|
userProps,
|
||
|
tags,
|
||
|
runtime: "langchain-js",
|
||
|
});
|
||
|
}
|
||
|
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata) {
|
||
|
const { name, extra, userId, userProps } = parseExtraAndName(llm, extraParams, metadata);
|
||
|
await this.monitor.trackEvent("llm", "start", {
|
||
|
runId,
|
||
|
parentRunId,
|
||
|
name,
|
||
|
input: (0, exports.convertToLLMonitorMessages)(messages),
|
||
|
extra,
|
||
|
userId,
|
||
|
userProps,
|
||
|
tags,
|
||
|
runtime: "langchain-js",
|
||
|
});
|
||
|
}
|
||
|
async handleLLMEnd(output, runId) {
|
||
|
const { generations, llmOutput } = output;
|
||
|
await this.monitor.trackEvent("llm", "end", {
|
||
|
runId,
|
||
|
output: (0, exports.convertToLLMonitorMessages)(generations),
|
||
|
tokensUsage: {
|
||
|
completion: llmOutput?.tokenUsage?.completionTokens,
|
||
|
prompt: llmOutput?.tokenUsage?.promptTokens,
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
async handleLLMError(error, runId) {
|
||
|
await this.monitor.trackEvent("llm", "error", {
|
||
|
runId,
|
||
|
error,
|
||
|
});
|
||
|
}
|
||
|
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata) {
|
||
|
const { agentName, userId, userProps, ...rest } = metadata || {};
|
||
|
// allow the user to specify an agent name
|
||
|
const name = agentName || chain.id.at(-1);
|
||
|
// Attempt to automatically detect if this is an agent or chain
|
||
|
const runType = agentName || ["AgentExecutor", "PlanAndExecute"].includes(name)
|
||
|
? "agent"
|
||
|
: "chain";
|
||
|
await this.monitor.trackEvent(runType, "start", {
|
||
|
runId,
|
||
|
parentRunId,
|
||
|
name,
|
||
|
userId,
|
||
|
userProps,
|
||
|
input: parseInput(inputs),
|
||
|
extra: rest,
|
||
|
tags,
|
||
|
runtime: "langchain-js",
|
||
|
});
|
||
|
}
|
||
|
async handleChainEnd(outputs, runId) {
|
||
|
await this.monitor.trackEvent("chain", "end", {
|
||
|
runId,
|
||
|
output: parseOutput(outputs),
|
||
|
});
|
||
|
}
|
||
|
async handleChainError(error, runId) {
|
||
|
await this.monitor.trackEvent("chain", "error", {
|
||
|
runId,
|
||
|
error,
|
||
|
});
|
||
|
}
|
||
|
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
||
|
const { toolName, userId, userProps, ...rest } = metadata || {};
|
||
|
const name = toolName || tool.id.at(-1);
|
||
|
await this.monitor.trackEvent("tool", "start", {
|
||
|
runId,
|
||
|
parentRunId,
|
||
|
name,
|
||
|
userId,
|
||
|
userProps,
|
||
|
input,
|
||
|
extra: rest,
|
||
|
tags,
|
||
|
runtime: "langchain-js",
|
||
|
});
|
||
|
}
|
||
|
async handleToolEnd(output, runId) {
|
||
|
await this.monitor.trackEvent("tool", "end", {
|
||
|
runId,
|
||
|
output,
|
||
|
});
|
||
|
}
|
||
|
async handleToolError(error, runId) {
|
||
|
await this.monitor.trackEvent("tool", "error", {
|
||
|
runId,
|
||
|
error,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
exports.LLMonitorHandler = LLMonitorHandler;
|