UNPKG

langchain

Version:
199 lines (198 loc) 8.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.SqlDatabase = void 0; const serializable_1 = require("@langchain/core/load/serializable"); const sql_utils_js_1 = require("./util/sql_utils.cjs"); /** * Class that represents a SQL database in the LangChain framework. * * @security **Security Notice** * This class generates SQL queries for the given database. * The SQLDatabase class provides a getTableInfo method that can be used * to get column information as well as sample data from the table. * To mitigate risk of leaking sensitive data, limit permissions * to read and scope to the tables that are needed. * Optionally, use the includesTables or ignoreTables class parameters * to limit which tables can/cannot be accessed. * * @link See https://js.langchain.com/docs/security for more information. */ class SqlDatabase extends serializable_1.Serializable { toJSON() { return this.toJSONNotImplemented(); } constructor(fields) { super(...arguments); Object.defineProperty(this, "lc_namespace", { enumerable: true, configurable: true, writable: true, value: ["langchain", "sql_db"] }); Object.defineProperty(this, "appDataSourceOptions", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "appDataSource", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "allTables", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "includesTables", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "ignoreTables", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "sampleRowsInTableInfo", { enumerable: true, configurable: true, writable: true, value: 3 }); Object.defineProperty(this, "customDescription", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.appDataSource = fields.appDataSource; this.appDataSourceOptions = fields.appDataSource.options; if (fields?.includesTables && fields?.ignoreTables) { throw new Error("Cannot specify both includeTables and ignoreTables"); } this.includesTables = fields?.includesTables ?? []; this.ignoreTables = fields?.ignoreTables ?? []; this.sampleRowsInTableInfo = fields?.sampleRowsInTableInfo ?? this.sampleRowsInTableInfo; } static async fromDataSourceParams(fields) { const sqlDatabase = new SqlDatabase(fields); if (!sqlDatabase.appDataSource.isInitialized) { await sqlDatabase.appDataSource.initialize(); } sqlDatabase.allTables = await (0, sql_utils_js_1.getTableAndColumnsName)(sqlDatabase.appDataSource); sqlDatabase.customDescription = Object.fromEntries(Object.entries(fields?.customDescription ?? {}).filter(([key, _]) => sqlDatabase.allTables .map((table) => table.tableName) .includes(key))); (0, sql_utils_js_1.verifyIncludeTablesExistInDatabase)(sqlDatabase.allTables, sqlDatabase.includesTables); (0, sql_utils_js_1.verifyIgnoreTablesExistInDatabase)(sqlDatabase.allTables, sqlDatabase.ignoreTables); return sqlDatabase; } static async fromOptionsParams(fields) { const { DataSource } = await Promise.resolve().then(() => __importStar(require("typeorm"))); const dataSource = new DataSource(fields.appDataSourceOptions); return SqlDatabase.fromDataSourceParams({ ...fields, appDataSource: dataSource, }); } /** * Get information about specified tables. * * Follows best practices as specified in: Rajkumar et al, 2022 * (https://arxiv.org/abs/2204.00498) * * If `sample_rows_in_table_info`, the specified number of sample rows will be * appended to each table description. This can increase performance as * demonstrated in the paper. */ async getTableInfo(targetTables) { let selectedTables = this.includesTables.length > 0 ? this.allTables.filter((currentTable) => this.includesTables.includes(currentTable.tableName)) : this.allTables; if (this.ignoreTables.length > 0) { selectedTables = selectedTables.filter((currentTable) => !this.ignoreTables.includes(currentTable.tableName)); } if (targetTables && targetTables.length > 0) { (0, sql_utils_js_1.verifyListTablesExistInDatabase)(this.allTables, targetTables, "Wrong target table name:"); selectedTables = this.allTables.filter((currentTable) => targetTables.includes(currentTable.tableName)); } return (0, sql_utils_js_1.generateTableInfoFromTables)(selectedTables, this.appDataSource, this.sampleRowsInTableInfo, this.customDescription); } /** * Execute a SQL command and return a string representing the results. * If the statement returns rows, a string of the results is returned. * If the statement returns no rows, an empty string is returned. */ async run(command, fetch = "all") { // TODO: Potential security issue here const res = await this.appDataSource.query(command); if (fetch === "all") { return JSON.stringify(res); } if (res?.length > 0) { return JSON.stringify(res[0]); } return ""; } serialize() { return { _type: "sql_database", appDataSourceOptions: this.appDataSourceOptions, includesTables: this.includesTables, ignoreTables: this.ignoreTables, sampleRowsInTableInfo: this.sampleRowsInTableInfo, }; } /** @ignore */ static async imports() { try { const { DataSource } = await Promise.resolve().then(() => __importStar(require("typeorm"))); return { DataSource }; } catch (e) { console.error(e); throw new Error("Failed to load typeorm. Please install it with eg. `yarn add typeorm`."); } } } exports.SqlDatabase = SqlDatabase;