Skip to content

Commit 40e36d1

Browse files
Feature/DocumentStore (#2106)
* datasource: initial commit * datasource: datasource details and chunks * datasource: Document Store Node * more changes * Document Store - Base functionality * Document Store Loader Component * Document Store Loader Component * before merging the modularity PR * after merging the modularity PR * preview mode * initial draft PR * fixes * minor updates and fixes * preview with loader and splitter * preview with credential * show stored chunks * preview update... * edit config * save, preview and other changes * save, preview and other changes * save, process and other changes * save, process and other changes * alpha1 - for internal testing * rerouting urls * bug fix on new leader create * pagination support for chunks * delete document store * Update pnpm-lock.yaml * doc store card view * Update store files to use updated storage functions, Document Store Table View and other changes * ui changes * add expanded chunk dialog, improve ui * change throw Error to InternalError * Bug Fixes and removal of subFolder, adding of view chunks for store * lint fixes * merge changes * DocumentStoreStatus component * ui changes for doc store * add remove metadata key field, add custom document loader * add chatflows used doc store chips * add types/interfaces to DocumentStore Services * document loader list dialog title bar color change * update interfaces * Whereused Chatflow Name and Added chunkNo to retain order of created chunks. * use typeorm order chunkNo, ui changes --------- Co-authored-by: Henry <hzj94@hotmail.com> Co-authored-by: Henry Heng <henryheng@flowiseai.com>
1 parent af4e28a commit 40e36d1

File tree

91 files changed

+38562
-32640
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+38562
-32640
lines changed

README-JA.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<a href="https://github.com/FlowiseAI/Flowise">
1717
<img width="100%" src="https://github.com/FlowiseAI/Flowise/blob/main/images/flowise.gif?raw=true"></a>
1818

19-
## ⚡クイックスタート
19+
## クイックスタート
2020

2121
[NodeJS](https://nodejs.org/en/download) >= 18.15.0 をダウンロードしてインストール
2222

@@ -67,7 +67,7 @@
6767

6868
## 👨‍💻 開発者向け
6969

70-
Flowise には、3つの異なるモジュールが1つの mono リポジトリにあります。
70+
Flowise には、3 つの異なるモジュールが 1 つの mono リポジトリにあります。
7171

7272
- `server`: API ロジックを提供する Node バックエンド
7373
- `ui`: React フロントエンド

README-KR.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ English | [中文](./README-ZH.md) | [日本語](./README-JA.md) | 한국어
1616
<a href="https://github.com/FlowiseAI/Flowise">
1717
<img width="100%" src="https://github.com/FlowiseAI/Flowise/blob/main/images/flowise.gif?raw=true"></a>
1818

19-
## ⚡빠른 시작 가이드
19+
## ⚡빠른 시작 가이드
2020

2121
18.15.0 버전 이상의 [NodeJS](https://nodejs.org/en/download) 다운로드 및 설치
2222

@@ -43,10 +43,10 @@ English | [中文](./README-ZH.md) | [日本語](./README-JA.md) | 한국어
4343
### 도커 컴포즈 활용
4444

4545
1. 프로젝트의 최상위(root) 디렉토리에 있는 `docker` 폴더로 이동하세요.
46-
2. `.env.example` 파일을 복사한 후, 같은 경로에 붙여넣기 한 다음, `.env`로 이름을 변경합니다.
46+
2. `.env.example` 파일을 복사한 후, 같은 경로에 붙여넣기 한 다음, `.env`로 이름을 변경합니다.
4747
3. `docker-compose up -d` 실행
4848
4. [http://localhost:3000](http://localhost:3000) URL 열기
49-
5. `docker-compose stop` 명령어를 통해 컨테이너를 종료시킬 수 있습니다.
49+
5. `docker-compose stop` 명령어를 통해 컨테이너를 종료시킬 수 있습니다.
5050

5151
### 도커 이미지 활용
5252

@@ -70,7 +70,7 @@ English | [中文](./README-ZH.md) | [日本語](./README-JA.md) | 한국어
7070
Flowise는 단일 리포지토리에 3개의 서로 다른 모듈이 있습니다.
7171

7272
- `server`: API 로직을 제공하는 노드 백엔드
73-
- `ui`: 리액트 프론트엔드
73+
- `ui`: 리액트 프론트엔드
7474
- `components`: 서드파티 노드 통합을 위한 컴포넌트
7575

7676
### 사전 설치 요건
@@ -112,11 +112,11 @@ Flowise는 단일 리포지토리에 3개의 서로 다른 모듈이 있습니
112112
pnpm start
113113
```
114114

115-
이제 [http://localhost:3000](http://localhost:3000)에서 애플리케이션에 접속할 수 있습니다.
115+
이제 [http://localhost:3000](http://localhost:3000)에서 애플리케이션에 접속할 수 있습니다.
116116

117117
6. 개발 환경에서 빌드할 경우:
118118

119-
- `packages/ui`경로에 `.env` 파일을 생성하고 `VITE_PORT`(`.env.example` 참조)를 지정합니다.
119+
- `packages/ui`경로에 `.env` 파일을 생성하고 `VITE_PORT`(`.env.example` 참조)를 지정합니다.
120120
- `packages/server`경로에 `.env` 파일을 생성하고 `PORT`(`.env.example` 참조)를 지정합니다.
121121
- 실행하기
122122

@@ -143,7 +143,7 @@ Flowise는 인스턴스 구성을 위한 다양한 환경 변수를 지원합니
143143
144144
[Flowise 문서](https://docs.flowiseai.com/)
145145
146-
## 🌐 자체 호스팅 하기
146+
## 🌐 자체 호스팅 하기
147147
148148
기존 인프라 환경에서 Flowise를 자체 호스팅으로 배포하세요. 다양한 배포 [deployments](https://docs.flowiseai.com/configuration/deployment) 방법을 지원합니다.
149149
@@ -182,23 +182,23 @@ Flowise는 인스턴스 구성을 위한 다양한 환경 변수를 지원합니
182182
183183
## 💻 클라우드 호스팅 서비스
184184
185-
곧 출시될 예정입니다.
185+
곧 출시될 예정입니다.
186186
187-
## 🙋 기술 지원
187+
## 🙋 기술 지원
188188
189-
질문, 버그 리포팅, 새로운 기능 요청 등은 [discussion](https://github.com/FlowiseAI/Flowise/discussions) 섹션에서 자유롭게 이야기 해주세요.
189+
질문, 버그 리포팅, 새로운 기능 요청 등은 [discussion](https://github.com/FlowiseAI/Flowise/discussions) 섹션에서 자유롭게 이야기 해주세요.
190190
191191
## 🙌 오픈소스 활동에 기여하기
192192
193-
다음과 같은 멋진 기여자들(contributors)에게 감사드립니다.
193+
다음과 같은 멋진 기여자들(contributors)에게 감사드립니다.
194194
195195
<a href="https://github.com/FlowiseAI/Flowise/graphs/contributors">
196196
<img src="https://contrib.rocks/image?repo=FlowiseAI/Flowise" />
197197
</a>
198198
199-
[contributing guide](CONTRIBUTING.md)를 살펴보세요. 디스코드 [Discord](https://discord.gg/jbaHfsRVBW) 채널에서도 이슈나 질의응답을 진행하실 수 있습니다.
199+
[contributing guide](CONTRIBUTING.md)를 살펴보세요. 디스코드 [Discord](https://discord.gg/jbaHfsRVBW) 채널에서도 이슈나 질의응답을 진행하실 수 있습니다.
200200
[![Star History Chart](https://api.star-history.com/svg?repos=FlowiseAI/Flowise&type=Timeline)](https://star-history.com/#FlowiseAI/Flowise&Date)
201201
202-
## 📄 라이센스
202+
## 📄 라이센스
203203
204-
본 리포지토리의 소스코드는 [Apache License Version 2.0](LICENSE.md) 라이센스가 적용됩니다.
204+
본 리포지토리의 소스코드는 [Apache License Version 2.0](LICENSE.md) 라이센스가 적용됩니다.

packages/components/nodes/documentloaders/API/APILoader.ts

+49-15
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import axios, { AxiosRequestConfig } from 'axios'
2+
import { omit } from 'lodash'
23
import { Document } from '@langchain/core/documents'
34
import { TextSplitter } from 'langchain/text_splitter'
45
import { BaseDocumentLoader } from 'langchain/document_loaders/base'
5-
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
6+
import { ICommonObject, IDocument, INode, INodeData, INodeParams } from '../../../src/Interface'
67

78
class API_DocumentLoaders implements INode {
89
label: string
@@ -66,6 +67,25 @@ class API_DocumentLoaders implements INode {
6667
'JSON body for the POST request. If not specified, agent will try to figure out itself from AIPlugin if provided',
6768
additionalParams: true,
6869
optional: true
70+
},
71+
{
72+
label: 'Additional Metadata',
73+
name: 'metadata',
74+
type: 'json',
75+
description: 'Additional metadata to be added to the extracted documents',
76+
optional: true,
77+
additionalParams: true
78+
},
79+
{
80+
label: 'Omit Metadata Keys',
81+
name: 'omitMetadataKeys',
82+
type: 'string',
83+
rows: 4,
84+
description:
85+
'Each document loader comes with a default set of metadata keys that are extracted from the document. You can use this field to omit some of the default metadata keys. The value should be a list of keys, seperated by comma',
86+
placeholder: 'key1, key2, key3.nestedKey1',
87+
optional: true,
88+
additionalParams: true
6989
}
7090
]
7191
}
@@ -76,6 +96,12 @@ class API_DocumentLoaders implements INode {
7696
const method = nodeData.inputs?.method as string
7797
const textSplitter = nodeData.inputs?.textSplitter as TextSplitter
7898
const metadata = nodeData.inputs?.metadata
99+
const _omitMetadataKeys = nodeData.inputs?.omitMetadataKeys as string
100+
101+
let omitMetadataKeys: string[] = []
102+
if (_omitMetadataKeys) {
103+
omitMetadataKeys = _omitMetadataKeys.split(',').map((key) => key.trim())
104+
}
79105

80106
const options: ApiLoaderParams = {
81107
url,
@@ -94,7 +120,7 @@ class API_DocumentLoaders implements INode {
94120

95121
const loader = new ApiLoader(options)
96122

97-
let docs = []
123+
let docs: IDocument[] = []
98124

99125
if (textSplitter) {
100126
docs = await loader.loadAndSplit(textSplitter)
@@ -104,18 +130,26 @@ class API_DocumentLoaders implements INode {
104130

105131
if (metadata) {
106132
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
107-
let finaldocs = []
108-
for (const doc of docs) {
109-
const newdoc = {
110-
...doc,
111-
metadata: {
133+
docs = docs.map((doc) => ({
134+
...doc,
135+
metadata: omit(
136+
{
112137
...doc.metadata,
113138
...parsedMetadata
114-
}
115-
}
116-
finaldocs.push(newdoc)
117-
}
118-
return finaldocs
139+
},
140+
omitMetadataKeys
141+
)
142+
}))
143+
} else {
144+
docs = docs.map((doc) => ({
145+
...doc,
146+
metadata: omit(
147+
{
148+
...doc.metadata
149+
},
150+
omitMetadataKeys
151+
)
152+
}))
119153
}
120154

121155
return docs
@@ -146,15 +180,15 @@ class ApiLoader extends BaseDocumentLoader {
146180
this.method = method
147181
}
148182

149-
public async load(): Promise<Document[]> {
183+
public async load(): Promise<IDocument[]> {
150184
if (this.method === 'POST') {
151185
return this.executePostRequest(this.url, this.headers, this.body)
152186
} else {
153187
return this.executeGetRequest(this.url, this.headers)
154188
}
155189
}
156190

157-
protected async executeGetRequest(url: string, headers?: ICommonObject): Promise<Document[]> {
191+
protected async executeGetRequest(url: string, headers?: ICommonObject): Promise<IDocument[]> {
158192
try {
159193
const config: AxiosRequestConfig = {}
160194
if (headers) {
@@ -174,7 +208,7 @@ class ApiLoader extends BaseDocumentLoader {
174208
}
175209
}
176210

177-
protected async executePostRequest(url: string, headers?: ICommonObject, body?: ICommonObject): Promise<Document[]> {
211+
protected async executePostRequest(url: string, headers?: ICommonObject, body?: ICommonObject): Promise<IDocument[]> {
178212
try {
179213
const config: AxiosRequestConfig = {}
180214
if (headers) {

packages/components/nodes/documentloaders/Airtable/Airtable.ts

+44-17
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import axios from 'axios'
2+
import { omit } from 'lodash'
23
import { Document } from '@langchain/core/documents'
34
import { TextSplitter } from 'langchain/text_splitter'
45
import { BaseDocumentLoader } from 'langchain/document_loaders/base'
56
import { getCredentialData, getCredentialParam } from '../../../src/utils'
6-
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
7+
import { IDocument, ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
78

89
class Airtable_DocumentLoaders implements INode {
910
label: string
@@ -93,9 +94,21 @@ class Airtable_DocumentLoaders implements INode {
9394
description: 'Number of results to return. Ignored when Return All is enabled.'
9495
},
9596
{
96-
label: 'Metadata',
97+
label: 'Additional Metadata',
9798
name: 'metadata',
9899
type: 'json',
100+
description: 'Additional metadata to be added to the extracted documents',
101+
optional: true,
102+
additionalParams: true
103+
},
104+
{
105+
label: 'Omit Metadata Keys',
106+
name: 'omitMetadataKeys',
107+
type: 'string',
108+
rows: 4,
109+
description:
110+
'Each document loader comes with a default set of metadata keys that are extracted from the document. You can use this field to omit some of the default metadata keys. The value should be a list of keys, seperated by comma',
111+
placeholder: 'key1, key2, key3.nestedKey1',
99112
optional: true,
100113
additionalParams: true
101114
}
@@ -111,6 +124,12 @@ class Airtable_DocumentLoaders implements INode {
111124
const limit = nodeData.inputs?.limit as string
112125
const textSplitter = nodeData.inputs?.textSplitter as TextSplitter
113126
const metadata = nodeData.inputs?.metadata
127+
const _omitMetadataKeys = nodeData.inputs?.omitMetadataKeys as string
128+
129+
let omitMetadataKeys: string[] = []
130+
if (_omitMetadataKeys) {
131+
omitMetadataKeys = _omitMetadataKeys.split(',').map((key) => key.trim())
132+
}
114133

115134
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
116135
const accessToken = getCredentialParam('accessToken', credentialData, nodeData)
@@ -131,7 +150,7 @@ class Airtable_DocumentLoaders implements INode {
131150
throw new Error('Base ID and Table ID must be provided.')
132151
}
133152

134-
let docs = []
153+
let docs: IDocument[] = []
135154

136155
if (textSplitter) {
137156
docs = await loader.loadAndSplit(textSplitter)
@@ -141,18 +160,26 @@ class Airtable_DocumentLoaders implements INode {
141160

142161
if (metadata) {
143162
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
144-
let finaldocs = []
145-
for (const doc of docs) {
146-
const newdoc = {
147-
...doc,
148-
metadata: {
163+
docs = docs.map((doc) => ({
164+
...doc,
165+
metadata: omit(
166+
{
149167
...doc.metadata,
150168
...parsedMetadata
151-
}
152-
}
153-
finaldocs.push(newdoc)
154-
}
155-
return finaldocs
169+
},
170+
omitMetadataKeys
171+
)
172+
}))
173+
} else {
174+
docs = docs.map((doc) => ({
175+
...doc,
176+
metadata: omit(
177+
{
178+
...doc.metadata
179+
},
180+
omitMetadataKeys
181+
)
182+
}))
156183
}
157184

158185
return docs
@@ -213,7 +240,7 @@ class AirtableLoader extends BaseDocumentLoader {
213240
this.returnAll = returnAll
214241
}
215242

216-
public async load(): Promise<Document[]> {
243+
public async load(): Promise<IDocument[]> {
217244
if (this.returnAll) {
218245
return this.loadAll()
219246
}
@@ -238,7 +265,7 @@ class AirtableLoader extends BaseDocumentLoader {
238265
}
239266
}
240267

241-
private createDocumentFromPage(page: AirtableLoaderPage): Document {
268+
private createDocumentFromPage(page: AirtableLoaderPage): IDocument {
242269
// Generate the URL
243270
const pageUrl = `https://api.airtable.com/v0/${this.baseId}/${this.tableId}/${page.id}`
244271

@@ -251,7 +278,7 @@ class AirtableLoader extends BaseDocumentLoader {
251278
})
252279
}
253280

254-
private async loadLimit(): Promise<Document[]> {
281+
private async loadLimit(): Promise<IDocument[]> {
255282
let data: AirtableLoaderRequest = {
256283
maxRecords: this.limit,
257284
view: this.viewId
@@ -282,7 +309,7 @@ class AirtableLoader extends BaseDocumentLoader {
282309
return returnPages.map((page) => this.createDocumentFromPage(page))
283310
}
284311

285-
private async loadAll(): Promise<Document[]> {
312+
private async loadAll(): Promise<IDocument[]> {
286313
let data: AirtableLoaderRequest = {
287314
view: this.viewId
288315
}

0 commit comments

Comments
 (0)