@oracle/langchain-oracledb 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/dist/document_loaders.cjs +211 -0
- package/dist/document_loaders.cjs.map +1 -0
- package/dist/document_loaders.d.cts +33 -0
- package/dist/document_loaders.d.ts +33 -0
- package/dist/document_loaders.js +181 -0
- package/dist/document_loaders.js.map +1 -0
- package/dist/embeddings.cjs +129 -0
- package/dist/embeddings.cjs.map +1 -0
- package/dist/embeddings.d.cts +35 -0
- package/dist/embeddings.d.ts +35 -0
- package/dist/embeddings.js +122 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/index.cjs +22 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/summary.cjs +63 -0
- package/dist/summary.cjs.map +1 -0
- package/dist/summary.d.cts +16 -0
- package/dist/summary.d.ts +16 -0
- package/dist/summary.js +56 -0
- package/dist/summary.js.map +1 -0
- package/dist/text_splitter.cjs +58 -0
- package/dist/text_splitter.cjs.map +1 -0
- package/dist/text_splitter.d.cts +17 -0
- package/dist/text_splitter.d.ts +17 -0
- package/dist/text_splitter.js +51 -0
- package/dist/text_splitter.js.map +1 -0
- package/dist/vectorstores.cjs +658 -0
- package/dist/vectorstores.cjs.map +1 -0
- package/dist/vectorstores.d.cts +98 -0
- package/dist/vectorstores.d.ts +98 -0
- package/dist/vectorstores.js +647 -0
- package/dist/vectorstores.js.map +1 -0
- package/index.cjs +1 -0
- package/index.d.cts +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 LangChain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# @oracle/langchain-oracledb
|
|
2
|
+
|
|
3
|
+
This package contains the LangChain.js integrations for Oracle Database.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash npm2yarn
|
|
8
|
+
npm install @oracle/langchain-oracledb @langchain/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This package, along with the main LangChain package, depends on [`@langchain/core`](https://npmjs.com/package/@langchain/core/).
|
|
12
|
+
If you are using this package with other LangChain packages, you should make sure that all of the packages depend on the same instance of @langchain/core.
|
|
13
|
+
You can do so by adding an appropriate field to your project's `package.json` like this:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"name": "your-project",
|
|
18
|
+
"version": "0.1.0",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@oracle/langchain-oracledb": "^0.1.1",
|
|
21
|
+
"@langchain/core": "^1.0.0"
|
|
22
|
+
},
|
|
23
|
+
"resolutions": {
|
|
24
|
+
"@langchain/core": "^1.0.0"
|
|
25
|
+
},
|
|
26
|
+
"overrides": {
|
|
27
|
+
"@langchain/core": "^1.0.0"
|
|
28
|
+
},
|
|
29
|
+
"pnpm": {
|
|
30
|
+
"overrides": {
|
|
31
|
+
"@langchain/core": "^1.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The field you need depends on the package manager you're using, but we recommend adding a field for the common `yarn`, `npm`, and `pnpm` to maximize compatibility.
|
|
38
|
+
|
|
39
|
+
## Document Loaders
|
|
40
|
+
|
|
41
|
+
This package includes a document loader for loading documents from different sources and file formats.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import {OracleDocLoader} from "@oracle/langchain-oracledb";
|
|
45
|
+
|
|
46
|
+
const loader = new OracleDocLoader(conn, loader_params);
|
|
47
|
+
const docs = await loader.load();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Text Splitter
|
|
51
|
+
|
|
52
|
+
This package includes a text splitter for chunking documents using the database.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import {OracleTextSplitter} from "@oracle/langchain-oracledb";
|
|
56
|
+
|
|
57
|
+
const splitter = new OracleTextSplitter(conn, splitter_params);
|
|
58
|
+
let chunks = await splitter.splitText(doc.pageContent);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Embeddings
|
|
62
|
+
|
|
63
|
+
This package includes a class for generating embeddings either inside or outside of the database.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import {OracleEmbeddings} from "@oracle/langchain-oracledb";
|
|
67
|
+
|
|
68
|
+
const embedder = new OracleEmbeddings(conn, embedder_params, proxy);
|
|
69
|
+
const embed = await embedder.embedQuery(chunk);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Summary
|
|
73
|
+
|
|
74
|
+
This package includes a class for generating summaries either inside or outside of the database.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import {OracleSummary} from "@oracle/langchain-oracledb";
|
|
78
|
+
|
|
79
|
+
const model = new OracleSummary(conn, summary_params, proxy);
|
|
80
|
+
const summary = await model.getSummary(doc.pageContent);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Vector Store
|
|
84
|
+
|
|
85
|
+
This package includes a vector store for storing, indexing, and querying data in the database.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import {OracleVS} from "@oracle/langchain-oracledb";
|
|
89
|
+
|
|
90
|
+
oraclevs = new OracleVS(embedder, dbConfig);
|
|
91
|
+
await oraclevs.initialize();
|
|
92
|
+
|
|
93
|
+
await oraclevs.addDocuments(docs);
|
|
94
|
+
const results = await oraclevs.similaritySearch("hello!", 3);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Development
|
|
98
|
+
|
|
99
|
+
To develop the `@oracle/langchain-oracledb` package, you'll need to follow these instructions:
|
|
100
|
+
|
|
101
|
+
### Install dependencies
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pnpm install
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Build the package
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pnpm build
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or from the repo root:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pnpm build --filter @oracle/langchain-oracledb
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Run tests
|
|
120
|
+
|
|
121
|
+
Test files should live within a `tests/` file in the `src/` folder. Unit tests should end in `.test.ts` and integration tests should
|
|
122
|
+
end in `.int.test.ts`:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
$ pnpm test
|
|
126
|
+
$ pnpm test:int
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Lint & Format
|
|
130
|
+
|
|
131
|
+
Run the linter & formatter to ensure your code is up to standard:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
pnpm lint && pnpm format
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Adding new entrypoints
|
|
138
|
+
|
|
139
|
+
If you add a new file to be exported, either import & re-export from `src/index.ts`, or add it to the `exports` field in the `package.json` file and run `pnpm build` to generate the new entrypoint.
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.OracleDocLoader = void 0;
|
|
30
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
31
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
32
|
+
const documents_1 = require("@langchain/core/documents");
|
|
33
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
34
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
35
|
+
const oracledb_1 = __importDefault(require("oracledb"));
|
|
36
|
+
const htmlparser2 = __importStar(require("htmlparser2"));
|
|
37
|
+
const base_1 = require("@langchain/core/document_loaders/base");
|
|
38
|
+
function* listDir(dir) {
|
|
39
|
+
const files = node_fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
if (file.isDirectory()) {
|
|
42
|
+
yield* listDir(node_path_1.default.join(dir, file.name));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
yield node_path_1.default.join(dir, file.name);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load documents from a file, a directory, or a table
|
|
51
|
+
* If the document isn't a plain text file such as a PDF,
|
|
52
|
+
* a plain text version will be extracted using utl_to_text
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const loader = new OracleDocLoader(conn, params);
|
|
56
|
+
* const docs = await loader.load();
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
class OracleDocLoader extends base_1.BaseDocumentLoader {
|
|
60
|
+
constructor(conn, pref) {
|
|
61
|
+
super();
|
|
62
|
+
Object.defineProperty(this, "conn", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true,
|
|
66
|
+
value: void 0
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(this, "pref", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
configurable: true,
|
|
71
|
+
writable: true,
|
|
72
|
+
value: void 0
|
|
73
|
+
});
|
|
74
|
+
this.conn = conn;
|
|
75
|
+
this.pref = pref;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A method that loads the text file or blob and returns a promise that
|
|
79
|
+
* resolves to an array of `Document` instances. It reads the text from
|
|
80
|
+
* the file or blob using the `readFile` function from the
|
|
81
|
+
* `node:fs/promises` module or the `text()` method of the blob. It then
|
|
82
|
+
* parses the text using the `parse()` method and creates a `Document`
|
|
83
|
+
* instance for each parsed page. The metadata includes the source of the
|
|
84
|
+
* text (file path or blob) and, if there are multiple pages, the line
|
|
85
|
+
* number of each page.
|
|
86
|
+
* @returns A promise that resolves to an array of `Document` instances.
|
|
87
|
+
*/
|
|
88
|
+
async load() {
|
|
89
|
+
const docs = [];
|
|
90
|
+
if ("file" in this.pref) {
|
|
91
|
+
const doc = await this._loadFromFile(this.pref.file);
|
|
92
|
+
if (doc != null) {
|
|
93
|
+
docs.push(doc);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if ("dir" in this.pref) {
|
|
97
|
+
for (const file of listDir(this.pref.dir)) {
|
|
98
|
+
const doc = await this._loadFromFile(file);
|
|
99
|
+
if (doc != null) {
|
|
100
|
+
docs.push(doc);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if ("tablename" in this.pref) {
|
|
105
|
+
if (!("owner" in this.pref) || !("colname" in this.pref)) {
|
|
106
|
+
throw new Error("Invalid preferences: missing owner or colname");
|
|
107
|
+
}
|
|
108
|
+
docs.push(...(await this._loadFromTable(this.pref.owner, this.pref.tablename, this.pref.colname)));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
throw new Error("Invalid preferences: missing file, dir, or tablename");
|
|
112
|
+
}
|
|
113
|
+
return docs;
|
|
114
|
+
}
|
|
115
|
+
// load from file
|
|
116
|
+
async _loadFromFile(filename) {
|
|
117
|
+
let doc = null;
|
|
118
|
+
// don't specify an encoding to use binary
|
|
119
|
+
const data = node_fs_1.default.readFileSync(filename);
|
|
120
|
+
const result = await this.conn.execute(`select dbms_vector_chain.utl_to_text(:content, :pref) text,\
|
|
121
|
+
dbms_vector_chain.utl_to_text(:content, json('{"plaintext": "false"}')) metadata from dual`, {
|
|
122
|
+
content: { val: data, dir: oracledb_1.default.BIND_IN, type: oracledb_1.default.BLOB },
|
|
123
|
+
pref: { val: this.pref, type: oracledb_1.default.DB_TYPE_JSON },
|
|
124
|
+
}, {
|
|
125
|
+
resultSet: true,
|
|
126
|
+
fetchInfo: {
|
|
127
|
+
TEXT: { type: oracledb_1.default.STRING },
|
|
128
|
+
METADATA: { type: oracledb_1.default.STRING },
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const resultSet = result.resultSet;
|
|
132
|
+
try {
|
|
133
|
+
if (resultSet) {
|
|
134
|
+
for await (const row of resultSet) {
|
|
135
|
+
const [plain_text, metadata] = await this._extract(row);
|
|
136
|
+
doc = new documents_1.Document({
|
|
137
|
+
pageContent: plain_text,
|
|
138
|
+
metadata: metadata,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
if (resultSet) {
|
|
145
|
+
await resultSet.close();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return doc;
|
|
149
|
+
}
|
|
150
|
+
// load from table
|
|
151
|
+
async _loadFromTable(owner, table, col) {
|
|
152
|
+
const docs = [];
|
|
153
|
+
// Check if names are invalid
|
|
154
|
+
const qn = `${owner}.${table}`;
|
|
155
|
+
try {
|
|
156
|
+
const sql = `select sys.dbms_assert.simple_sql_name(:col),\
|
|
157
|
+
sys.dbms_assert.qualified_sql_name(:qn) from dual`;
|
|
158
|
+
const binds = [col, qn];
|
|
159
|
+
await this.conn.execute(sql, binds);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
throw new Error("Invalid owner, table, or column name");
|
|
163
|
+
}
|
|
164
|
+
const result = await this.conn.execute((`select dbms_vector_chain.utl_to_text(t.${this.pref.colname}, :pref) text,\
|
|
165
|
+
dbms_vector_chain.utl_to_text(t.${this.pref.colname}, json('{"plaintext": "false"}')) metadata\
|
|
166
|
+
from ${owner}.${table} t`), {
|
|
167
|
+
pref: { val: this.pref, type: oracledb_1.default.DB_TYPE_JSON },
|
|
168
|
+
}, {
|
|
169
|
+
resultSet: true,
|
|
170
|
+
fetchInfo: {
|
|
171
|
+
TEXT: { type: oracledb_1.default.STRING },
|
|
172
|
+
METADATA: { type: oracledb_1.default.STRING },
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
const resultSet = result.resultSet;
|
|
176
|
+
try {
|
|
177
|
+
if (resultSet) {
|
|
178
|
+
for await (const row of resultSet) {
|
|
179
|
+
const [plain_text, metadata] = await this._extract(row);
|
|
180
|
+
docs.push(new documents_1.Document({
|
|
181
|
+
pageContent: plain_text,
|
|
182
|
+
metadata: metadata,
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
if (resultSet) {
|
|
189
|
+
await resultSet.close();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return docs;
|
|
193
|
+
}
|
|
194
|
+
// extract plain text and metadata from a row
|
|
195
|
+
async _extract(row) {
|
|
196
|
+
const [text, htmlMetadata] = row;
|
|
197
|
+
const metadata = {};
|
|
198
|
+
const parser = new htmlparser2.Parser({
|
|
199
|
+
onopentag(name, attrs) {
|
|
200
|
+
if (name === "meta" && attrs.name) {
|
|
201
|
+
metadata[attrs.name] = attrs.content;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
parser.write(htmlMetadata);
|
|
206
|
+
parser.end();
|
|
207
|
+
return [text, metadata];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.OracleDocLoader = OracleDocLoader;
|
|
211
|
+
//# sourceMappingURL=document_loaders.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document_loaders.cjs","sourceRoot":"","sources":["../src/document_loaders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Document } from "@langchain/core/documents";
|
|
2
|
+
import oracledb from "oracledb";
|
|
3
|
+
import { BaseDocumentLoader } from "@langchain/core/document_loaders/base";
|
|
4
|
+
/**
|
|
5
|
+
* Load documents from a file, a directory, or a table
|
|
6
|
+
* If the document isn't a plain text file such as a PDF,
|
|
7
|
+
* a plain text version will be extracted using utl_to_text
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const loader = new OracleDocLoader(conn, params);
|
|
11
|
+
* const docs = await loader.load();
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare class OracleDocLoader extends BaseDocumentLoader {
|
|
15
|
+
protected conn: oracledb.Connection;
|
|
16
|
+
protected pref: Record<string, any>;
|
|
17
|
+
constructor(conn: oracledb.Connection, pref: Record<string, any>);
|
|
18
|
+
/**
|
|
19
|
+
* A method that loads the text file or blob and returns a promise that
|
|
20
|
+
* resolves to an array of `Document` instances. It reads the text from
|
|
21
|
+
* the file or blob using the `readFile` function from the
|
|
22
|
+
* `node:fs/promises` module or the `text()` method of the blob. It then
|
|
23
|
+
* parses the text using the `parse()` method and creates a `Document`
|
|
24
|
+
* instance for each parsed page. The metadata includes the source of the
|
|
25
|
+
* text (file path or blob) and, if there are multiple pages, the line
|
|
26
|
+
* number of each page.
|
|
27
|
+
* @returns A promise that resolves to an array of `Document` instances.
|
|
28
|
+
*/
|
|
29
|
+
load(): Promise<Document[]>;
|
|
30
|
+
private _loadFromFile;
|
|
31
|
+
private _loadFromTable;
|
|
32
|
+
private _extract;
|
|
33
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Document } from "@langchain/core/documents";
|
|
2
|
+
import oracledb from "oracledb";
|
|
3
|
+
import { BaseDocumentLoader } from "@langchain/core/document_loaders/base";
|
|
4
|
+
/**
|
|
5
|
+
* Load documents from a file, a directory, or a table
|
|
6
|
+
* If the document isn't a plain text file such as a PDF,
|
|
7
|
+
* a plain text version will be extracted using utl_to_text
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const loader = new OracleDocLoader(conn, params);
|
|
11
|
+
* const docs = await loader.load();
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare class OracleDocLoader extends BaseDocumentLoader {
|
|
15
|
+
protected conn: oracledb.Connection;
|
|
16
|
+
protected pref: Record<string, any>;
|
|
17
|
+
constructor(conn: oracledb.Connection, pref: Record<string, any>);
|
|
18
|
+
/**
|
|
19
|
+
* A method that loads the text file or blob and returns a promise that
|
|
20
|
+
* resolves to an array of `Document` instances. It reads the text from
|
|
21
|
+
* the file or blob using the `readFile` function from the
|
|
22
|
+
* `node:fs/promises` module or the `text()` method of the blob. It then
|
|
23
|
+
* parses the text using the `parse()` method and creates a `Document`
|
|
24
|
+
* instance for each parsed page. The metadata includes the source of the
|
|
25
|
+
* text (file path or blob) and, if there are multiple pages, the line
|
|
26
|
+
* number of each page.
|
|
27
|
+
* @returns A promise that resolves to an array of `Document` instances.
|
|
28
|
+
*/
|
|
29
|
+
load(): Promise<Document[]>;
|
|
30
|
+
private _loadFromFile;
|
|
31
|
+
private _loadFromTable;
|
|
32
|
+
private _extract;
|
|
33
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import { Document } from "@langchain/core/documents";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import oracledb from "oracledb";
|
|
7
|
+
import * as htmlparser2 from "htmlparser2";
|
|
8
|
+
import { BaseDocumentLoader } from "@langchain/core/document_loaders/base";
|
|
9
|
+
function* listDir(dir) {
|
|
10
|
+
const files = fs.readdirSync(dir, { withFileTypes: true });
|
|
11
|
+
for (const file of files) {
|
|
12
|
+
if (file.isDirectory()) {
|
|
13
|
+
yield* listDir(path.join(dir, file.name));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
yield path.join(dir, file.name);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load documents from a file, a directory, or a table
|
|
22
|
+
* If the document isn't a plain text file such as a PDF,
|
|
23
|
+
* a plain text version will be extracted using utl_to_text
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const loader = new OracleDocLoader(conn, params);
|
|
27
|
+
* const docs = await loader.load();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class OracleDocLoader extends BaseDocumentLoader {
|
|
31
|
+
constructor(conn, pref) {
|
|
32
|
+
super();
|
|
33
|
+
Object.defineProperty(this, "conn", {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: void 0
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(this, "pref", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: void 0
|
|
44
|
+
});
|
|
45
|
+
this.conn = conn;
|
|
46
|
+
this.pref = pref;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A method that loads the text file or blob and returns a promise that
|
|
50
|
+
* resolves to an array of `Document` instances. It reads the text from
|
|
51
|
+
* the file or blob using the `readFile` function from the
|
|
52
|
+
* `node:fs/promises` module or the `text()` method of the blob. It then
|
|
53
|
+
* parses the text using the `parse()` method and creates a `Document`
|
|
54
|
+
* instance for each parsed page. The metadata includes the source of the
|
|
55
|
+
* text (file path or blob) and, if there are multiple pages, the line
|
|
56
|
+
* number of each page.
|
|
57
|
+
* @returns A promise that resolves to an array of `Document` instances.
|
|
58
|
+
*/
|
|
59
|
+
async load() {
|
|
60
|
+
const docs = [];
|
|
61
|
+
if ("file" in this.pref) {
|
|
62
|
+
const doc = await this._loadFromFile(this.pref.file);
|
|
63
|
+
if (doc != null) {
|
|
64
|
+
docs.push(doc);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if ("dir" in this.pref) {
|
|
68
|
+
for (const file of listDir(this.pref.dir)) {
|
|
69
|
+
const doc = await this._loadFromFile(file);
|
|
70
|
+
if (doc != null) {
|
|
71
|
+
docs.push(doc);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if ("tablename" in this.pref) {
|
|
76
|
+
if (!("owner" in this.pref) || !("colname" in this.pref)) {
|
|
77
|
+
throw new Error("Invalid preferences: missing owner or colname");
|
|
78
|
+
}
|
|
79
|
+
docs.push(...(await this._loadFromTable(this.pref.owner, this.pref.tablename, this.pref.colname)));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
throw new Error("Invalid preferences: missing file, dir, or tablename");
|
|
83
|
+
}
|
|
84
|
+
return docs;
|
|
85
|
+
}
|
|
86
|
+
// load from file
|
|
87
|
+
async _loadFromFile(filename) {
|
|
88
|
+
let doc = null;
|
|
89
|
+
// don't specify an encoding to use binary
|
|
90
|
+
const data = fs.readFileSync(filename);
|
|
91
|
+
const result = await this.conn.execute(`select dbms_vector_chain.utl_to_text(:content, :pref) text,\
|
|
92
|
+
dbms_vector_chain.utl_to_text(:content, json('{"plaintext": "false"}')) metadata from dual`, {
|
|
93
|
+
content: { val: data, dir: oracledb.BIND_IN, type: oracledb.BLOB },
|
|
94
|
+
pref: { val: this.pref, type: oracledb.DB_TYPE_JSON },
|
|
95
|
+
}, {
|
|
96
|
+
resultSet: true,
|
|
97
|
+
fetchInfo: {
|
|
98
|
+
TEXT: { type: oracledb.STRING },
|
|
99
|
+
METADATA: { type: oracledb.STRING },
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
const resultSet = result.resultSet;
|
|
103
|
+
try {
|
|
104
|
+
if (resultSet) {
|
|
105
|
+
for await (const row of resultSet) {
|
|
106
|
+
const [plain_text, metadata] = await this._extract(row);
|
|
107
|
+
doc = new Document({
|
|
108
|
+
pageContent: plain_text,
|
|
109
|
+
metadata: metadata,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
if (resultSet) {
|
|
116
|
+
await resultSet.close();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return doc;
|
|
120
|
+
}
|
|
121
|
+
// load from table
|
|
122
|
+
async _loadFromTable(owner, table, col) {
|
|
123
|
+
const docs = [];
|
|
124
|
+
// Check if names are invalid
|
|
125
|
+
const qn = `${owner}.${table}`;
|
|
126
|
+
try {
|
|
127
|
+
const sql = `select sys.dbms_assert.simple_sql_name(:col),\
|
|
128
|
+
sys.dbms_assert.qualified_sql_name(:qn) from dual`;
|
|
129
|
+
const binds = [col, qn];
|
|
130
|
+
await this.conn.execute(sql, binds);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new Error("Invalid owner, table, or column name");
|
|
134
|
+
}
|
|
135
|
+
const result = await this.conn.execute((`select dbms_vector_chain.utl_to_text(t.${this.pref.colname}, :pref) text,\
|
|
136
|
+
dbms_vector_chain.utl_to_text(t.${this.pref.colname}, json('{"plaintext": "false"}')) metadata\
|
|
137
|
+
from ${owner}.${table} t`), {
|
|
138
|
+
pref: { val: this.pref, type: oracledb.DB_TYPE_JSON },
|
|
139
|
+
}, {
|
|
140
|
+
resultSet: true,
|
|
141
|
+
fetchInfo: {
|
|
142
|
+
TEXT: { type: oracledb.STRING },
|
|
143
|
+
METADATA: { type: oracledb.STRING },
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
const resultSet = result.resultSet;
|
|
147
|
+
try {
|
|
148
|
+
if (resultSet) {
|
|
149
|
+
for await (const row of resultSet) {
|
|
150
|
+
const [plain_text, metadata] = await this._extract(row);
|
|
151
|
+
docs.push(new Document({
|
|
152
|
+
pageContent: plain_text,
|
|
153
|
+
metadata: metadata,
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
if (resultSet) {
|
|
160
|
+
await resultSet.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return docs;
|
|
164
|
+
}
|
|
165
|
+
// extract plain text and metadata from a row
|
|
166
|
+
async _extract(row) {
|
|
167
|
+
const [text, htmlMetadata] = row;
|
|
168
|
+
const metadata = {};
|
|
169
|
+
const parser = new htmlparser2.Parser({
|
|
170
|
+
onopentag(name, attrs) {
|
|
171
|
+
if (name === "meta" && attrs.name) {
|
|
172
|
+
metadata[attrs.name] = attrs.content;
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
parser.write(htmlMetadata);
|
|
177
|
+
parser.end();
|
|
178
|
+
return [text, metadata];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=document_loaders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document_loaders.js","sourceRoot":"","sources":["../src/document_loaders.ts"],"names":[],"mappings":"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"}
|