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, };