libre / api /app /clients /tools /util /handleTools.js
Marco Beretta
LibreChat upload repo
3b6afc0
raw
history blame
5.05 kB
const { getUserPluginAuthValue } = require('../../../../server/services/PluginService');
const { OpenAIEmbeddings } = require('langchain/embeddings/openai');
const { ZapierToolKit } = require('langchain/agents');
const { SerpAPI, ZapierNLAWrapper } = require('langchain/tools');
const { ChatOpenAI } = require('langchain/chat_models/openai');
const { Calculator } = require('langchain/tools/calculator');
const { WebBrowser } = require('langchain/tools/webbrowser');
const {
availableTools,
AIPluginTool,
GoogleSearchAPI,
WolframAlphaAPI,
StructuredWolfram,
HttpRequestTool,
OpenAICreateImage,
StableDiffusionAPI,
StructuredSD,
} = require('../');
const { loadSpecs } = require('./loadSpecs');
const validateTools = async (user, tools = []) => {
try {
const validToolsSet = new Set(tools);
const availableToolsToValidate = availableTools.filter((tool) =>
validToolsSet.has(tool.pluginKey),
);
const validateCredentials = async (authField, toolName) => {
const adminAuth = process.env[authField];
if (adminAuth && adminAuth.length > 0) {
return;
}
const userAuth = await getUserPluginAuthValue(user, authField);
if (userAuth && userAuth.length > 0) {
return;
}
validToolsSet.delete(toolName);
};
for (const tool of availableToolsToValidate) {
if (!tool.authConfig || tool.authConfig.length === 0) {
continue;
}
for (const auth of tool.authConfig) {
await validateCredentials(auth.authField, tool.pluginKey);
}
}
return Array.from(validToolsSet.values());
} catch (err) {
console.log('There was a problem validating tools', err);
throw new Error(err);
}
};
const loadToolWithAuth = async (user, authFields, ToolConstructor, options = {}) => {
return async function () {
let authValues = {};
for (const authField of authFields) {
let authValue = process.env[authField];
if (!authValue) {
authValue = await getUserPluginAuthValue(user, authField);
}
authValues[authField] = authValue;
}
return new ToolConstructor({ ...options, ...authValues });
};
};
const loadTools = async ({ user, model, functions = null, tools = [], options = {} }) => {
const toolConstructors = {
calculator: Calculator,
google: GoogleSearchAPI,
wolfram: functions ? StructuredWolfram : WolframAlphaAPI,
'dall-e': OpenAICreateImage,
'stable-diffusion': functions ? StructuredSD : StableDiffusionAPI,
};
const customConstructors = {
'web-browser': async () => {
let openAIApiKey = options.openAIApiKey ?? process.env.OPENAI_API_KEY;
openAIApiKey = openAIApiKey === 'user_provided' ? null : openAIApiKey;
openAIApiKey = openAIApiKey || (await getUserPluginAuthValue(user, 'OPENAI_API_KEY'));
return new WebBrowser({ model, embeddings: new OpenAIEmbeddings({ openAIApiKey }) });
},
serpapi: async () => {
let apiKey = process.env.SERPAPI_API_KEY;
if (!apiKey) {
apiKey = await getUserPluginAuthValue(user, 'SERPAPI_API_KEY');
}
return new SerpAPI(apiKey, {
location: 'Austin,Texas,United States',
hl: 'en',
gl: 'us',
});
},
zapier: async () => {
let apiKey = process.env.ZAPIER_NLA_API_KEY;
if (!apiKey) {
apiKey = await getUserPluginAuthValue(user, 'ZAPIER_NLA_API_KEY');
}
const zapier = new ZapierNLAWrapper({ apiKey });
return ZapierToolKit.fromZapierNLAWrapper(zapier);
},
plugins: async () => {
return [
new HttpRequestTool(),
await AIPluginTool.fromPluginUrl(
'https://www.klarna.com/.well-known/ai-plugin.json',
new ChatOpenAI({ openAIApiKey: options.openAIApiKey, temperature: 0 }),
),
];
},
};
const requestedTools = {};
let specs = null;
if (functions) {
specs = await loadSpecs({
llm: model,
user,
message: options.message,
map: true,
verbose: options?.debug,
});
console.dir(specs, { depth: null });
}
const toolOptions = {
serpapi: { location: 'Austin,Texas,United States', hl: 'en', gl: 'us' },
};
const toolAuthFields = {};
availableTools.forEach((tool) => {
if (customConstructors[tool.pluginKey]) {
return;
}
toolAuthFields[tool.pluginKey] = tool.authConfig.map((auth) => auth.authField);
});
for (const tool of tools) {
if (customConstructors[tool]) {
requestedTools[tool] = customConstructors[tool];
continue;
}
if (specs && specs[tool]) {
requestedTools[tool] = specs[tool];
continue;
}
if (toolConstructors[tool]) {
const options = toolOptions[tool] || {};
const toolInstance = await loadToolWithAuth(
user,
toolAuthFields[tool],
toolConstructors[tool],
options,
);
requestedTools[tool] = toolInstance;
}
}
return requestedTools;
};
module.exports = {
validateTools,
loadTools,
};