LibreChat/api/app/langchain/tools/util/handleTools.js

163 lines
4.4 KiB
JavaScript

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,
HttpRequestTool,
OpenAICreateImage,
StableDiffusionAPI,
StructuredSD,
} = require('../');
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, tools = [], options = {} }) => {
const { functions } = options;
const toolConstructors = {
calculator: Calculator,
google: GoogleSearchAPI,
wolfram: WolframAlphaAPI,
'dall-e': OpenAICreateImage,
'stable-diffusion': functions ? StructuredSD : StableDiffusionAPI
};
const customConstructors = {
browser: async () => {
let openAIApiKey = process.env.OPENAI_API_KEY;
if (!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 = {};
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 (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
};