@maximai/maxim-js-langchain
Version:
This is the langchain wrapper built for (Maxim JS SDK)[https://www.npmjs.com/package/@maximai/maxim-js].
369 lines (368 loc) • 16.4 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseLangchainModelAndParameters = parseLangchainModelAndParameters;
exports.determineProvider = determineProvider;
exports.parseMessage = parseMessage;
exports.convertLLMResultToCompletionResult = convertLLMResultToCompletionResult;
exports.parseTokenUsageForResult = parseTokenUsageForResult;
exports.parseLangchainLLMError = parseLangchainLLMError;
exports.maybeParseJSON = maybeParseJSON;
exports.parseLangchainMessages = parseLangchainMessages;
const messages_1 = require("@langchain/core/messages");
const uuid_1 = require("uuid");
function parseLangchainModelAndParameters(llm, metadata, extraParams) {
let modelParams = (extraParams === null || extraParams === void 0 ? void 0 : extraParams["invocation_params"]) || {};
// bedrock returns inferenceConfig in extraParams
if ("inferenceConfig" in modelParams && typeof modelParams["inferenceConfig"] === "object") {
const { inferenceConfig } = modelParams, rest = __rest(modelParams, ["inferenceConfig"]);
modelParams = Object.assign(Object.assign({}, inferenceConfig), rest);
}
let model = "unknown";
if ("model_name" in modelParams) {
model = modelParams["model_name"];
modelParams === null || modelParams === void 0 ? true : delete modelParams["model_name"];
}
else if ("model" in modelParams) {
model = modelParams["model"];
modelParams === null || modelParams === void 0 ? true : delete modelParams["model"];
}
else if ("model_id" in modelParams) {
model = modelParams["model_id"];
modelParams === null || modelParams === void 0 ? true : delete modelParams["model_id"];
}
if (model === "unknown") {
if (metadata && "ls_model_name" in metadata && typeof metadata["ls_model_name"] === "string") {
model = metadata["ls_model_name"];
}
}
return [model, Object.assign({}, modelParams)];
}
function determineProvider(ids, metadata) {
const mapper = (param) => {
if (param.includes("azure"))
return "azure";
if (param.includes("azure_openai"))
return "azure";
if (param.includes("amazon_bedrock"))
return "bedrock";
if (param.includes("bedrock"))
return "bedrock";
if (param.includes("huggingface"))
return "huggingface";
if (param.includes("together"))
return "together";
if (param.includes("openai"))
return "openai";
if (param.includes("anthropic"))
return "anthropic";
if (param.includes("google"))
return "google";
if (param.includes("groq"))
return "groq";
return null;
};
const provider = mapper(ids);
if (provider !== null) {
return provider;
}
if (metadata && "ls_provider" in metadata && typeof metadata["ls_provider"] === "string") {
const lsProvider = metadata["ls_provider"];
const provider = mapper(lsProvider);
if (provider !== null) {
return provider;
}
}
return "openai";
}
function parseMessage(generation) {
var _a;
if (!("message" in generation)) {
return undefined;
}
const message = generation.message;
if (!message) {
return undefined;
}
let toolCalls = undefined;
if ((0, messages_1.isAIMessage)(message)) {
const aiMessage = new messages_1.AIMessage(message);
toolCalls = (_a = aiMessage["tool_calls"]) === null || _a === void 0 ? void 0 : _a.map((toolCall) => {
return {
type: "function",
id: toolCall.id,
function: {
name: toolCall.name,
arguments: JSON.stringify(toolCall.args),
},
};
});
}
return {
role: "assistant",
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
tool_calls: toolCalls,
function_call: toolCalls,
};
}
function convertLLMResultToCompletionResult(result) {
var _a, _b, _c, _d;
let model = "unknown";
if (result.generations.length === 0) {
return {
id: (0, uuid_1.v4)(),
object: "chat_completion",
created: Math.floor(Date.now() / 1000),
model,
choices: [],
usage: {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0,
},
};
}
let finishReason = "stop";
if ((_a = result.llmOutput) === null || _a === void 0 ? void 0 : _a["stop_reason"]) {
finishReason = result.llmOutput["stop_reason"]; // anthropic
}
const choices = result.generations[0].map((gen, index) => {
var _a, _b;
return ({
index,
text: gen.text.trim() === "" ? undefined : gen.text.trim(),
message: parseMessage(gen),
logprobs: null,
finish_reason: (_b = (_a = gen.generationInfo) === null || _a === void 0 ? void 0 : _a["finish_reason"]) !== null && _b !== void 0 ? _b : finishReason,
});
});
const [gen] = result.generations[0];
if ("message" in gen) {
const message = gen.message;
model = (_c = (_b = message.response_metadata) === null || _b === void 0 ? void 0 : _b["model_name"]) !== null && _c !== void 0 ? _c : "unknown";
}
return {
id: (0, uuid_1.v4)(),
object: ((_d = choices === null || choices === void 0 ? void 0 : choices[0]) === null || _d === void 0 ? void 0 : _d.text) ? "text_completion" : "chat_completion",
created: Math.floor(Date.now() / 1000),
model: model,
choices,
usage: parseTokenUsageForResult(result),
};
}
function parseTokenUsageForResult(result) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
let usage = (_a = result.llmOutput) === null || _a === void 0 ? void 0 : _a["tokenUsage"];
if (usage) {
const promptTokens = (_b = usage.promptTokens) !== null && _b !== void 0 ? _b : 0;
const completionTokens = (_c = usage.completionTokens) !== null && _c !== void 0 ? _c : 0;
const totalTokens = promptTokens + completionTokens;
return {
prompt_tokens: promptTokens,
completion_tokens: completionTokens,
total_tokens: totalTokens,
};
}
const llm_usage = (_d = result.llmOutput) === null || _d === void 0 ? void 0 : _d["usage"];
if (llm_usage) {
if (llm_usage.input_tokens !== undefined) {
usage = {
prompt_tokens: (_e = llm_usage.input_tokens) !== null && _e !== void 0 ? _e : 0,
completion_tokens: (_f = llm_usage.output_tokens) !== null && _f !== void 0 ? _f : 0,
total_tokens: ((_g = llm_usage.input_tokens) !== null && _g !== void 0 ? _g : 0) + ((_h = llm_usage.output_tokens) !== null && _h !== void 0 ? _h : 0),
};
}
else if (llm_usage.prompt_tokens !== undefined) {
usage = {
prompt_tokens: (_j = llm_usage.prompt_tokens) !== null && _j !== void 0 ? _j : 0,
completion_tokens: (_k = llm_usage.completion_tokens) !== null && _k !== void 0 ? _k : 0,
total_tokens: ((_l = llm_usage.prompt_tokens) !== null && _l !== void 0 ? _l : 0) + ((_m = llm_usage.completion_tokens) !== null && _m !== void 0 ? _m : 0),
};
}
}
if (usage) {
return usage;
}
// Process individual generations if no top-level usage is found
let prompt_tokens = 0;
let output_tokens = 0;
let total_tokens = 0;
const generations = result.generations;
if (generations) {
for (const generation of generations) {
for (const gen of generation) {
const message = "message" in gen ? gen.message : undefined;
const usage_data = message === null || message === void 0 ? void 0 : message.usage_metadata;
if (usage_data) {
if (usage_data.input_tokens !== undefined) {
prompt_tokens += (_o = usage_data.input_tokens) !== null && _o !== void 0 ? _o : 0;
output_tokens += (_p = usage_data.output_tokens) !== null && _p !== void 0 ? _p : 0;
total_tokens += ((_q = usage_data.input_tokens) !== null && _q !== void 0 ? _q : 0) + ((_r = usage_data.output_tokens) !== null && _r !== void 0 ? _r : 0);
continue;
}
else if (usage_data.prompt_tokens !== undefined) {
prompt_tokens += (_s = usage_data.prompt_tokens) !== null && _s !== void 0 ? _s : 0;
output_tokens += (_t = usage_data.completion_tokens) !== null && _t !== void 0 ? _t : 0;
total_tokens += ((_u = usage_data.prompt_tokens) !== null && _u !== void 0 ? _u : 0) + ((_v = usage_data.completion_tokens) !== null && _v !== void 0 ? _v : 0);
continue;
}
}
const resp_metadata = message === null || message === void 0 ? void 0 : message.response_metadata;
if (resp_metadata) {
const metadata_usage = resp_metadata.usage;
if (metadata_usage) {
if (metadata_usage.input_tokens !== undefined) {
prompt_tokens += (_w = metadata_usage.input_tokens) !== null && _w !== void 0 ? _w : 0;
output_tokens += (_x = metadata_usage.output_tokens) !== null && _x !== void 0 ? _x : 0;
total_tokens += ((_y = metadata_usage.input_tokens) !== null && _y !== void 0 ? _y : 0) + ((_z = metadata_usage.output_tokens) !== null && _z !== void 0 ? _z : 0);
continue;
}
else if (metadata_usage.prompt_tokens !== undefined) {
prompt_tokens += (_0 = metadata_usage.prompt_tokens) !== null && _0 !== void 0 ? _0 : 0;
output_tokens += (_1 = metadata_usage.completion_tokens) !== null && _1 !== void 0 ? _1 : 0;
total_tokens += ((_2 = metadata_usage.prompt_tokens) !== null && _2 !== void 0 ? _2 : 0) + ((_3 = metadata_usage.completion_tokens) !== null && _3 !== void 0 ? _3 : 0);
continue;
}
}
// Handle Amazon Bedrock case
const bedrock_usage = resp_metadata["amazon-bedrock-invocationMetrics"];
if (bedrock_usage) {
prompt_tokens += (_4 = bedrock_usage.inputTokenCount) !== null && _4 !== void 0 ? _4 : 0;
output_tokens += (_5 = bedrock_usage.outputTokenCount) !== null && _5 !== void 0 ? _5 : 0;
total_tokens += ((_6 = bedrock_usage.inputTokenCount) !== null && _6 !== void 0 ? _6 : 0) + ((_7 = bedrock_usage.outputTokenCount) !== null && _7 !== void 0 ? _7 : 0);
}
}
}
}
}
return {
prompt_tokens,
completion_tokens: output_tokens,
total_tokens,
};
}
function parseLangchainLLMError(error) {
if (error instanceof Error) {
return {
message: error.message,
type: error.name,
code: error.code,
};
}
else if (typeof error === "object" && error !== null) {
const errorObj = error;
return {
message: String(errorObj["message"] || "Unknown error"),
type: String(errorObj["type"] || errorObj["name"] || "Unknown"),
code: String(errorObj["code"] || undefined),
};
}
else if (typeof error === "string") {
return {
message: error,
type: "Unknown",
};
}
else {
return {
message: "An unknown error occurred",
type: "Unknown",
};
}
}
function maybeParseJSON(input = "") {
try {
return JSON.parse(input);
}
catch (e) {
return input;
}
}
function parseLangchainMessages(input, defaultRole = "user") {
try {
const delimiterToRole = {
System: "system",
Human: "user",
User: "user",
Assistant: "assistant",
Model: "assistant",
};
const messages = [];
if (Array.isArray(input[0])) {
input.forEach((messageList) => {
messageList.forEach((message) => {
if (typeof message === "string") {
return;
}
const messageType = message.constructor.name;
if (messageType === "SystemMessage") {
messages.push({ role: "system", content: maybeParseJSON(message.content) });
}
else if (messageType === "HumanMessage") {
messages.push({ role: "user", content: maybeParseJSON(message.content) });
}
else if (messageType === "AIMessage") {
messages.push(Object.assign({ role: "assistant", content: maybeParseJSON(message.content) }, ("tool_calls" in message ? { tool_calls: message.tool_calls } : {})));
}
else if (messageType === "ToolMessage") {
messages.push({ role: "assistant", content: maybeParseJSON(message.content) });
}
else {
console.error(`Invalid message type: ${messageType}`, { message });
throw new Error(`Invalid message type: ${messageType}`);
}
});
});
}
else {
input.forEach((message) => {
if (typeof message !== "string") {
console.error(`Invalid message type: ${typeof message}`);
throw new Error(`Invalid message type: ${typeof message}`);
}
const pattern = /(System:|Human:|User:|Assistant:|Model:)/;
const splits = message.split(pattern).filter((s) => s.trim());
for (let i = 0; i < splits.length; i += 2) {
if (i + 1 < splits.length) {
const delimiter = splits[i].replace(":", "").trim();
const content = splits[i + 1].trim();
messages.push({
role: delimiterToRole[delimiter] || "user",
content: maybeParseJSON(content),
});
}
else {
if (splits[i].indexOf(":") === -1) {
messages.push({
role: delimiterToRole[defaultRole] || "user",
content: maybeParseJSON(splits[i]),
});
}
else {
const delimiter = splits[i].replace(":", "").trim();
messages.push({
role: delimiterToRole[delimiter] || "user",
content: "",
});
}
}
}
});
}
return messages;
}
catch (e) {
console.error(`Error parsing messages: ${e}`);
throw new Error(`Error parsing messages: ${e}`);
}
}