diff --git a/README.md b/README.md index bb48b41aa..30cbae720 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b - [x] 源文件引用追踪 - [x] 模块封装,实现多级复用 - [x] 混合检索 & 重排 - - [ ] 自查询规划 + - [ ] Tool 模块 - [ ] 嵌入 [Laf](https://github.com/labring/laf),实现在线编写 HTTP 模块 - [ ] 插件封装功能 @@ -67,10 +67,10 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b - [x] 支持知识库单独设置向量模型 - [x] 源文件存储 - [x] 支持手动输入,直接分段,QA 拆分导入 - - [x] 支持 pdf、word、txt、md 等常用文件,支持 url 读取、CSV 批量导入 - - [ ] 支持 HTML、csv、PPT、Excel 导入 + - [x] 支持 pdf,docx,txt,html,md,csv + - [x] 支持 url 读取、CSV 批量导入 + - [ ] 支持 PPT、Excel 导入 - [ ] 支持文件阅读器 - - [ ] 支持差异性文件同步 - [ ] 更多的数据预处理方案 `3` 应用调试能力 @@ -81,8 +81,8 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b - [ ] 高级编排 DeBug 模式 `4` OpenAPI 接口 - - [x] completions 接口 (对齐 GPT 接口) - - [ ] 知识库 CRUD + - [x] completions 接口 (chat 模式对齐 GPT 接口) + - [x] 知识库 CRUD - [ ] 对话 CRUD `5` 运营能力 diff --git a/README_en.md b/README_en.md index 368e281d5..587b8a539 100644 --- a/README_en.md +++ b/README_en.md @@ -49,48 +49,52 @@ Cloud: [fastgpt.in](https://fastgpt.in/) ## 💡 Features -1. Powerful visual workflows: Effortlessly craft AI applications +`1` Application Orchestration Features - - [x] Simple mode on deck - no need for manual arrangement - - [x] User dialogue pre-guidance - - [x] Global variables - - [x] Knowledge base search - - [x] Dialogue via multiple LLM models - - [x] Text magic - convert to structured data - - [x] Extend with HTTP - - [ ] Embed Laf for on-the-fly HTTP module crafting - - [x] Directions for the next dialogue steps - - [x] Tracking source file references - - [ ] Custom file reader - - [ ] Modules are packaged into plug-ins to achieve reuse + - [x] Offers a straightforward mode, eliminating the need for complex orchestration + - [x] Provides clear next-step instructions in dialogues + - [x] Facilitates workflow orchestration + - [x] Tracks references in source files + - [x] Encapsulates modules for enhanced reuse at multiple levels + - [x] Combines search and reordering functions + - [ ] Includes a tool module + - [ ] Integrates [Laf](https://github.com/labring/laf) for online HTTP module creation + - [ ] Plugin encapsulation capabilities -2. Extensive knowledge base preprocessing +`2` Knowledge Base Features - - [x] Reuse and mix multiple knowledge bases - - [x] Track chunk modifications and deletions - - [x] Supports manual entries, direct segmentation, and QA split imports - - [x] Supports URL fetching and batch CSV imports - - [x] Supports Set unique vector models for knowledge bases - - [x] Store original files - - [ ] File learning Agent + - [x] Allows for the mixed use of multiple databases + - [x] Keeps track of modifications and deletions in data chunks + - [x] Enables specific vector models for each knowledge base + - [x] Stores original source files + - [x] Supports direct input and segment-based QA import + - [x] Compatible with a variety of file formats: pdf, docx, txt, html, md, csv + - [x] Facilitates URL reading and bulk CSV importing + - [ ] Supports PPT and Excel file import + - [ ] Features a file reader + - [ ] Offers diverse data preprocessing options -3. Multiple effect testing channels +`3` Application Debugging Features - - [x] Single-point knowledge base search test - - [x] Feedback references and ability to modify and delete during dialogue - - [x] Complete context presentation - - [ ] Complete module intermediate value presentation + - [x] Enables targeted search testing within the knowledge base + - [x] Allows feedback, editing, and deletion during conversations + - [x] Presents the full context of interactions + - [x] Displays all intermediate values within modules + - [ ] Advanced DeBug mode for orchestration -4. OpenAPI +`4` OpenAPI Interface - - [x] completions interface (aligned with GPT interface) - - [ ] Knowledge base CRUD + - [x] The completions interface (aligned with GPT's chat mode interface) + - [x] CRUD operations for the knowledge base + - [ ] CRUD operations for conversations -5. Operational functions +`5` Operational Features + + - [x] Share without requiring login + - [x] Easy embedding with Iframe + - [x] Customizable chat window embedding with features like default open, drag-and-drop + - [x] Centralizes conversation records for review and annotation - - [x] Login-free sharing window - - [x] One-click embedding with Iframe - - [ ] Unified access to dialogue records # diff --git a/docSite/content/docs/development/openapi/chat.md b/docSite/content/docs/development/openapi/chat.md index 3b685359d..d232f294e 100644 --- a/docSite/content/docs/development/openapi/chat.md +++ b/docSite/content/docs/development/openapi/chat.md @@ -48,7 +48,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions' {{< /markdownify >}} {{< /tab >}} -{{< tab tabName="detail=true 响应" >}} +{{< tab tabName="参数说明" >}} {{< markdownify >}} {{% alert context="info" %}} @@ -56,7 +56,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions' - chatId: string | undefined 。 - 为 `undefined` 时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。 不会将你的记录存储到数据库中,你也无法在记录汇总中查阅到。 - 为`非空字符串`时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题。请自行确保 chatId 唯一,长度小于250,通常可以是自己系统的对话框ID。 -- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) 完全一致。 +- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) chat模式一致。 - detail: 是否返回中间值(模块状态,响应的完整结果等),`stream模式`下会通过`event`进行区分,`非stream模式`结果保存在`responseData`中。 - variables: 模块变量,一个对象,会替换模块中,输入框内容里的`{{key}}` {{% /alert %}} diff --git a/docSite/content/docs/development/openapi/dataset.md b/docSite/content/docs/development/openapi/dataset.md index efa70009c..43f8ed94d 100644 --- a/docSite/content/docs/development/openapi/dataset.md +++ b/docSite/content/docs/development/openapi/dataset.md @@ -15,7 +15,9 @@ weight: 853 ## 创建训练订单 -**请求示例** +{{< tabs tabTotal="2" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} ```bash curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/bill/createTrainingBill' \ @@ -26,7 +28,11 @@ curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/bill/c }' ``` -**响应结果** +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} data 为 billId,可用于添加知识库数据时进行账单聚合。 @@ -39,7 +45,764 @@ data 为 billId,可用于添加知识库数据时进行账单聚合。 } ``` -## 知识库添加数据 +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +## 知识库 + +### 创建一个知识库 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/core/dataset/create' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "parentId": null, + "type": "dataset", + "name":"测试", + "intro":"介绍", + "avatar": "", + "vectorModel": "text-embedding-ada-002", + "agentModel": "gpt-3.5-turbo-16k" +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- parentId - 父级ID,用于构建目录结构。通常可以为 null 或者直接不传。 +- type - `dataset`或者`folder`,代表普通知识库和文件夹。不传则代表创建普通知识库。 +- name - 知识库名(必填) +- intro - 介绍(可选) +- avatar - 头像地址(可选) +- vectorModel - 向量模型(建议传空,用系统默认的) +- agentModel - 文本处理模型(建议传空,用系统默认的) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": "65abc9bd9d1448617cba5e6c" +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 获取知识库列表 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request GET 'http://localhost:3000/api/core/dataset/list?parentId=' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- parentId - 父级ID,不传或为空,代表获取根目录下的知识库 +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": [ + { + "_id": "65abc9bd9d1448617cba5e6c", + "parentId": null, + "avatar": "", + "name": "测试", + "intro": "", + "type": "dataset", + "permission": "private", + "canWrite": true, + "isOwner": true, + "vectorModel": { + "model": "text-embedding-ada-002", + "name": "Embedding-2", + "inputPrice": 0, + "defaultToken": 512, + "maxToken": 8000, + "weight": 100 + } + } + ] +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 获取知识库详情 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request GET 'http://localhost:3000/api/core/dataset/detail?id=6593e137231a2be9c5603ba7' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 知识库的ID +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "_id": "6593e137231a2be9c5603ba7", + "parentId": null, + "teamId": "65422be6aa44b7da77729ec8", + "tmbId": "65422be6aa44b7da77729ec9", + "type": "dataset", + "status": "active", + "avatar": "/icon/logo.svg", + "name": "FastGPT test", + "vectorModel": { + "model": "text-embedding-ada-002", + "name": "Embedding-2", + "inputPrice": 0, + "defaultToken": 512, + "maxToken": 8000, + "weight": 100 + }, + "agentModel": { + "model": "gpt-3.5-turbo-16k", + "name": "FastAI-16k", + "maxContext": 16000, + "maxResponse": 16000, + "inputPrice": 0, + "outputPrice": 0 + }, + "intro": "", + "permission": "private", + "updateTime": "2024-01-02T10:11:03.084Z", + "canWrite": true, + "isOwner": true + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 删除一个知识库 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request DELETE 'http://localhost:3000/api/core/dataset/delete?id=65abc8729d1448617cba5df6' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 知识库的ID +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": null +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + + +## 集合 + +### 创建一个空的集合 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/core/dataset/collection/create' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "datasetId":"6593e137231a2be9c5603ba7", + "parentId": null, + "name":"测试", + "type":"virtual", + "metadata":{ + "test":111 + } +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- datasetId: 知识库的ID(必填) +- parentId: 父级ID,不填则默认为根目录 +- name: 集合名称(必填) +- type: + - folder:文件夹 + - virtual:虚拟集合(手动集合) +- metadata: 元数据(暂时没啥用) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + +data 为集合的 ID。 + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": "65abcd009d1448617cba5ee1" +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + + +### 创建一个纯文本集合(商业版) + +传入一段文字,创建一个集合,会根据传入的文字进行分割。 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/proApi/core/dataset/collection/create/text' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "text":"xxxxxxxx", + "datasetId":"6593e137231a2be9c5603ba7", + "parentId": null, + "name":"测试训练", + + "trainingType": "qa", + "chunkSize":8000, + "chunkSplitter":"", + "qaPrompt":"11", + + "metadata":{} +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- text: 原文本 +- datasetId: 知识库的ID(必填) +- parentId: 父级ID,不填则默认为根目录 +- name: 集合名称(必填) +- metadata: 元数据(暂时没啥用) +- trainingType:(必填) + - chunk: 按文本长度进行分割 + - qa: QA拆分 +- chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000) +- chunkSplitter: 自定义最高优先分割符号(可选) +- qaPrompt: qa拆分自定义提示词(可选) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + +data 为集合的 ID。 + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "collectionId": "65abcfab9d1448617cba5f0d", + "results": { + "insertLen": 5, // 分割成多少段 + "overToken": [], + "repeat": [], + "error": [] + } + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 创建一个链接集合(商业版) + +传入一个网络链接,创建一个集合,会先去对应网页抓取内容,再抓取的文字进行分割。 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/proApi/core/dataset/collection/create/link' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "link":"https://doc.fastgpt.in/docs/course/quick-start/", + "datasetId":"6593e137231a2be9c5603ba7", + "parentId": null, + + "trainingType": "chunk", + "chunkSize":512, + "chunkSplitter":"", + "qaPrompt":"", + + "metadata":{ + "webPageSelector":".docs-content" + } +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- link: 网络链接 +- datasetId: 知识库的ID(必填) +- parentId: 父级ID,不填则默认为根目录 +- metadata.webPageSelector: 网页选择器,用于指定网页中的哪个元素作为文本(可选) +- trainingType:(必填) + - chunk: 按文本长度进行分割 + - qa: QA拆分 +- chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000) +- chunkSplitter: 自定义最高优先分割符号(可选) +- qaPrompt: qa拆分自定义提示词(可选) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + +data 为集合的 ID。 + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "collectionId": "65abd0ad9d1448617cba6031" + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 创建一个文件集合(商业版) + +传入一个文件,创建一个集合,会读取文件内容进行分割。目前支持:pdf, docx, md, txt, html, csv。 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/proApi/core/dataset/collection/create/file' \ +--header 'Authorization: Bearer {{authorization}}' \ +--form 'file=@"C:\\Users\\user\\Desktop\\fastgpt测试文件\\index.html"' \ +--form 'data="{\"datasetId\":\"6593e137231a2be9c5603ba7\",\"parentId\":null,\"trainingType\":\"chunk\",\"chunkSize\":512,\"chunkSplitter\":\"\",\"qaPrompt\":\"\",\"metadata\":{}}"' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +需要使用 POST form-data 的格式上传。包含 file 和 data 两个字段。 + +{{% alert icon=" " context="success" %}} +- file: 文件 +- data: 知识库相关信息(json序列化后传入) + - datasetId: 知识库的ID(必填) + - parentId: 父级ID,不填则默认为根目录 + - trainingType:(必填) + - chunk: 按文本长度进行分割 + - qa: QA拆分 + - chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000) + - chunkSplitter: 自定义最高优先分割符号(可选) + - qaPrompt: qa拆分自定义提示词(可选) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + +data 为集合的 ID。 + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "collectionId": "65abc044e4704bac793fbd81", + "results": { + "insertLen": 1, + "overToken": [], + "repeat": [], + "error": [] + } + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 获取集合列表 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/core/dataset/collection/list' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "pageNum":1, + "pageSize": 10, + "datasetId":"6593e137231a2be9c5603ba7", + "parentId": null, + "searchText":"" +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- pageNum: 页码(选填) +- pageSize: 每页数量,最大30(选填) +- datasetId: 知识库的ID(必填) +- parentId: 父级Id(选填) +- searchText: 模糊搜索文本(选填) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "pageNum": 1, + "pageSize": 10, + "data": [ + { + "_id": "6593e137231a2be9c5603ba9", + "parentId": null, + "tmbId": "65422be6aa44b7da77729ec9", + "type": "virtual", + "name": "手动录入", + "updateTime": "2099-01-01T00:00:00.000Z", + "dataAmount": 3, + "trainingAmount": 0, + "canWrite": true + }, + { + "_id": "65abd0ad9d1448617cba6031", + "parentId": null, + "tmbId": "65422be6aa44b7da77729ec9", + "type": "link", + "name": "快速上手 | FastGPT", + "rawLink": "https://doc.fastgpt.in/docs/course/quick-start/", + "updateTime": "2024-01-20T13:54:53.031Z", + "dataAmount": 3, + "trainingAmount": 0, + "canWrite": true + } + ], + "total": 93 + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 获取集合详情 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request GET 'http://localhost:3000/api/core/dataset/collection/detail?id=65abcfab9d1448617cba5f0d' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 集合的ID +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "_id": "65abcfab9d1448617cba5f0d", + "parentId": null, + "teamId": "65422be6aa44b7da77729ec8", + "tmbId": "65422be6aa44b7da77729ec9", + "datasetId": { + "_id": "6593e137231a2be9c5603ba7", + "parentId": null, + "teamId": "65422be6aa44b7da77729ec8", + "tmbId": "65422be6aa44b7da77729ec9", + "type": "dataset", + "status": "active", + "avatar": "/icon/logo.svg", + "name": "FastGPT test", + "vectorModel": "text-embedding-ada-002", + "agentModel": "gpt-3.5-turbo-16k", + "intro": "", + "permission": "private", + "updateTime": "2024-01-02T10:11:03.084Z" + }, + "type": "virtual", + "name": "测试训练", + "trainingType": "qa", + "chunkSize": 8000, + "chunkSplitter": "", + "qaPrompt": "11", + "rawTextLength": 40466, + "hashRawText": "47270840614c0cc122b29daaddc09c2a48f0ec6e77093611ab12b69cba7fee12", + "createTime": "2024-01-20T13:50:35.838Z", + "updateTime": "2024-01-20T13:50:35.838Z", + "canWrite": true, + "sourceName": "测试训练" + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 修改集合信息 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request PUT 'http://localhost:3000/api/core/dataset/collection/update' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "id":"65abcfab9d1448617cba5f0d", + "parentId":null, + "name":"测2222试" +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 集合的ID +- parentId: 修改父级ID(可选) +- name: 修改集合名称(可选) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": null +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 删除一个集合 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request DELETE 'http://localhost:3000/api/core/dataset/collection/delete?id=65aa2a64e6cb9b8ccdc00de8' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 集合的ID +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": null +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +## 数据 + +### 为集合批量添加添加数据 + +注意,每次最多推送 200 组数据。 {{< tabs tabTotal="4" >}} {{< tab tabName="请求示例" >}} @@ -63,8 +826,9 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pus "q": "你会什么?", "a": "我什么都会", "indexes": [{ + "defaultIndex": false, "type":"custom", - "text":"你好" + "text":"自定义索引,不使用默认索引" }] } ] @@ -77,33 +841,17 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pus {{< tab tabName="参数说明" >}} {{< markdownify >}} -需要先了解 FastGPT 的多路索引概念: - -在 FastGPT 中,你可以为一组数据创建多个索引,如果不指定索引,则系统会自动取对应的 chunk 作为索引。例如前面的请求示例中: - -`q:你是谁?a:我是FastGPT助手` 它的`indexes`属性为空,意味着不自定义索引,而是使用默认的索引(你是谁?\n我是FastGPT助手)。 - -在第二组数据中`q:你会什么?a:我什么都会`指定了一个`你好`的索引,因此这组数据的索引为`你好`。 - -```json -{ - "collectionId": "文件集合的ID,参考上面的第二张图", - "mode": "chunk | qa ", // chunk 模式: 可自定义索引。qa 模型:无法自定义索引,会自动取 data 中的 q 作为数据,让模型自动生成问答对和索引。 - "prompt": "QA 拆分提示词,需严格按照模板,建议不要传入。", - "data": [ - { - "q": "生成索引的内容,index 模式下最大 tokens 为3000,建议不超过 1000", - "a": "预期回答/补充", - "indexes": "自定义索引", - }, - { - "q": "xxx", - "a": "xxxx" - } - ], - -} -``` +{{% alert icon=" " context="success" %}} +- collectionId: 集合ID(必填) +- trainingType:(必填) + - chunk: 按文本长度进行分割 + - qa: QA拆分 +- prompt: 自定义 QA 拆分提示词,需严格按照模板,建议不要传入。(选填) +- data:(具体数据) + - q: 主要数据(必填) + - a: 辅助数据(选填) + - indexes: 自定义索引(选填),不传入则默认使用q和a构建索引。也可以传入 +{{% /alert %}} {{< /markdownify >}} {{< /tab >}} @@ -155,6 +903,231 @@ A2: {{< /tabs >}} +### 获取集合的数据列表 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request POST 'http://localhost:3000/api/core/dataset/data/list' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "pageNum":1, + "pageSize": 10, + "collectionId":"65abd4ac9d1448617cba6171", + "searchText":"" +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- pageNum: 页码(选填) +- pageSize: 每页数量,最大30(选填) +- collectionId: 集合的ID(必填) +- searchText: 模糊搜索词(选填) +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "pageNum": 1, + "pageSize": 10, + "data": [ + { + "_id": "65abd4b29d1448617cba61db", + "datasetId": "65abc9bd9d1448617cba5e6c", + "collectionId": "65abd4ac9d1448617cba6171", + "q": "N o . 2 0 2 2 1 2中 国 信 息 通 信 研 究 院京东探索研究院2022年 9月人工智能生成内容(AIGC)白皮书(2022 年)版权声明本白皮书版权属于中国信息通信研究院和京东探索研究院,并受法律保护。转载、摘编或利用其它方式使用本白皮书文字或者观点的,应注明“来源:中国信息通信研究院和京东探索研究院”。违反上述声明者,编者将追究其相关法律责任。前 言习近平总书记曾指出,“数字技术正以新理念、新业态、新模式全面融入人类经济、政治、文化、社会、生态文明建设各领域和全过程”。在当前数字世界和物理世界加速融合的大背景下,人工智能生成内容(Artificial Intelligence Generated Content,简称 AIGC)正在悄然引导着一场深刻的变革,重塑甚至颠覆数字内容的生产方式和消费模式,将极大地丰富人们的数字生活,是未来全面迈向数字文明新时代不可或缺的支撑力量。", + "a": "", + "chunkIndex": 0 + }, + { + "_id": "65abd4b39d1448617cba624d", + "datasetId": "65abc9bd9d1448617cba5e6c", + "collectionId": "65abd4ac9d1448617cba6171", + "q": "本白皮书重点从 AIGC 技术、应用和治理等维度进行了阐述。在技术层面,梳理提出了 AIGC 技术体系,既涵盖了对现实世界各种内容的数字化呈现和增强,也包括了基于人工智能的自主内容创作。在应用层面,重点分析了 AIGC 在传媒、电商、影视等行业和场景的应用情况,探讨了以虚拟数字人、写作机器人等为代表的新业态和新应用。在治理层面,从政策监管、技术能力、企业应用等视角,分析了AIGC 所暴露出的版权纠纷、虚假信息传播等各种问题。最后,从政府、行业、企业、社会等层面,给出了 AIGC 发展和治理建议。由于人工智能仍处于飞速发展阶段,我们对 AIGC 的认识还有待进一步深化,白皮书中存在不足之处,敬请大家批评指正。目 录一、 人工智能生成内容的发展历程与概念.............................................................. 1(一)AIGC 历史沿革 .......................................................................................... 1(二)AIGC 的概念与内涵 .................................................................................. 4二、人工智能生成内容的技术体系及其演进方向.................................................... 7(一)AIGC 技术升级步入深化阶段 .................................................................. 7(二)AIGC 大模型架构潜力凸显 .................................................................... 10(三)AIGC 技术演化出三大前沿能力 ............................................................ 18三、人工智能生成内容的应用场景.......................................................................... 26(一)AIGC+传媒:人机协同生产,", + "a": "", + "chunkIndex": 1 + } + ], + "total": 63 + } +} +``` +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 获取单条数据详情 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request GET 'http://localhost:3000/api/core/dataset/data/detail?id=65abd4b29d1448617cba61db' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 数据的id +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": { + "id": "65abd4b29d1448617cba61db", + "q": "N o . 2 0 2 2 1 2中 国 信 息 通 信 研 究 院京东探索研究院2022年 9月人工智能生成内容(AIGC)白皮书(2022 年)版权声明本白皮书版权属于中国信息通信研究院和京东探索研究院,并受法律保护。转载、摘编或利用其它方式使用本白皮书文字或者观点的,应注明“来源:中国信息通信研究院和京东探索研究院”。违反上述声明者,编者将追究其相关法律责任。前 言习近平总书记曾指出,“数字技术正以新理念、新业态、新模式全面融入人类经济、政治、文化、社会、生态文明建设各领域和全过程”。在当前数字世界和物理世界加速融合的大背景下,人工智能生成内容(Artificial Intelligence Generated Content,简称 AIGC)正在悄然引导着一场深刻的变革,重塑甚至颠覆数字内容的生产方式和消费模式,将极大地丰富人们的数字生活,是未来全面迈向数字文明新时代不可或缺的支撑力量。", + "a": "", + "chunkIndex": 0, + "indexes": [ + { + "defaultIndex": true, + "type": "chunk", + "dataId": "3720083", + "text": "N o . 2 0 2 2 1 2中 国 信 息 通 信 研 究 院京东探索研究院2022年 9月人工智能生成内容(AIGC)白皮书(2022 年)版权声明本白皮书版权属于中国信息通信研究院和京东探索研究院,并受法律保护。转载、摘编或利用其它方式使用本白皮书文字或者观点的,应注明“来源:中国信息通信研究院和京东探索研究院”。违反上述声明者,编者将追究其相关法律责任。前 言习近平总书记曾指出,“数字技术正以新理念、新业态、新模式全面融入人类经济、政治、文化、社会、生态文明建设各领域和全过程”。在当前数字世界和物理世界加速融合的大背景下,人工智能生成内容(Artificial Intelligence Generated Content,简称 AIGC)正在悄然引导着一场深刻的变革,重塑甚至颠覆数字内容的生产方式和消费模式,将极大地丰富人们的数字生活,是未来全面迈向数字文明新时代不可或缺的支撑力量。", + "_id": "65abd4b29d1448617cba61dc" + } + ], + "datasetId": "65abc9bd9d1448617cba5e6c", + "collectionId": "65abd4ac9d1448617cba6171", + "sourceName": "中文-AIGC白皮书2022.pdf", + "sourceId": "65abd4ac9d1448617cba6166", + "isOwner": true, + "canWrite": true + } +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 修改单条数据 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request PUT 'http://localhost:3000/api/core/dataset/data/update' \ +--header 'Authorization: Bearer {{authorization}}' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "id":"65abd4b29d1448617cba61db", + "q":"测试111", + "a":"sss", + "indexes":[] +}' +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 数据的id +- q: 主要数据(选填) +- a: 辅助数据(选填) +- indexes: 自定义索引(选填),类型参考`为集合批量添加添加数据`,建议直接不传。更新q,a后,如果有默认索引,则会直接更新默认索引。 +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": null +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + +### 删除单条数据 + +{{< tabs tabTotal="3" >}} +{{< tab tabName="请求示例" >}} +{{< markdownify >}} + +```bash +curl --location --request DELETE 'http://localhost:3000/api/core/dataset/data/delete?id=65abd4b39d1448617cba624d' \ +--header 'Authorization: Bearer {{authorization}}' \ +``` + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="参数说明" >}} +{{< markdownify >}} + +{{% alert icon=" " context="success" %}} +- id: 数据的id +{{% /alert %}} + +{{< /markdownify >}} +{{< /tab >}} + +{{< tab tabName="响应示例" >}} +{{< markdownify >}} + + +```json +{ + "code": 200, + "statusText": "", + "message": "", + "data": "success" +} +``` + +{{< /markdownify >}} +{{< /tab >}} +{{< /tabs >}} + ## 搜索测试 {{< tabs tabTotal="3" >}} @@ -181,12 +1154,14 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/searchTe {{< tab tabName="参数说明" >}} {{< markdownify >}} +{{% alert icon=" " context="success" %}} - datasetId - 知识库ID - text - 需要测试的文本 - limit - 最大 tokens 数量 - similarity - 最低相关度(0~1,可选) - searchMode - 搜索模式:embedding | fullTextRecall | mixedRecall - usingReRank - 使用重排 +{{% /alert %}} {{< /markdownify >}} {{< /tab >}} @@ -196,7 +1171,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/searchTe 返回 top k 结果, limit 为最大 Tokens 数量,最多 20000 tokens。 -```bash +```json { "code": 200, "statusText": "", @@ -218,1158 +1193,5 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/searchTe {{< /markdownify >}} {{< /tab >}} - {{< /tabs >}} - -# 更多接口 - -目前未整理,简陋导出: - -## POST 知识库搜索测试 - -POST /core/dataset/searchTest - -> Body Parameters - -```json -{ - "datasetId": "656c2ccff7f114064daa72f6", - "text": "导演是谁", - "limit": 1500, - "searchMode": "embedding", - "usingReRank": true, - "similarity": 0.5 -} -``` - -### Params - -|Name|Location|Type|Required|Description| -|---|---|---|---|---| -|Authorization|header|string| no |none| -|body|body|object| no |none| -|» datasetId|body|string| yes |none| -|» text|body|string| yes |none| -|» limit|body|integer| no |none| -|» searchMode|body|[search mode](#schemasearch%20mode)| yes |none| -|» usingReRank|body|boolean| no |none| -|» similarity|body|[similary](#schemasimilary)| no |none| - -> Response Examples - -> 成功 - -```json -{ - "code": 200, - "statusText": "", - "message": "", - "data": { - "list": [ - { - "id": "65962b23f5fac58e46330dfd", - "q": "# 快速了解 FastGPT\nFastGPT 的能力与优势\n\nFastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!\n\n🤖\n\nFastGPT 在线使用:[https://fastgpt.in](https://fastgpt.in)\n\n| | |\n| --- | --- |\n| ![](https://doc.fastgpt.in/imgs/intro1.png) | ![](https://doc.fastgpt.in/imgs/intro2.png) |\n| ![](https://doc.fastgpt.in/imgs/intro3.png) | ![](https://doc.fastgpt.in/imgs/intro4.png) |\n\n", - "a": "", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65962b2089642fd209da3b03", - "sourceName": "https://doc.fastgpt.in/docs/intro/", - "sourceId": "https://doc.fastgpt.in/docs/intro/", - "score": [ - { - "type": "embedding", - "value": 0.8036568760871887, - "index": 20 - }, - { - "type": "fullText", - "value": 1.168349443855932, - "index": 2 - }, - { - "type": "reRank", - "value": 0.9870296135626316, - "index": 0 - }, - { - "type": "rrf", - "value": 0.04366449476962486, - "index": 0 - } - ] - }, - { - "id": "65962b24f5fac58e46330dff", - "q": "# 快速了解 FastGPT\n## FastGPT 能力\n### 2. 简单易用的可视化界面\nFastGPT 采用直观的可视化界面设计,为各种应用场景提供了丰富实用的功能。通过简洁易懂的操作步骤,可以轻松完成 AI 客服的创建和训练流程。\n\n![](https://doc.fastgpt.in/imgs/ability5.png)\n\n", - "a": "", - "chunkIndex": 2, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65962b2089642fd209da3b03", - "sourceName": "https://doc.fastgpt.in/docs/intro/", - "sourceId": "https://doc.fastgpt.in/docs/intro/", - "score": [ - { - "type": "embedding", - "value": 0.8152669668197632, - "index": 3 - }, - { - "type": "fullText", - "value": 1.0511363636363635, - "index": 8 - }, - { - "type": "reRank", - "value": 0.9287972729281414, - "index": 14 - }, - { - "type": "rrf", - "value": 0.04265696347031964, - "index": 1 - } - ] - }, - { - "id": "65962b25f5fac58e46330e00", - "q": "# 快速了解 FastGPT\n## FastGPT 能力\n### 3. 自动数据预处理\n提供手动输入、直接分段、LLM 自动处理和 CSV 等多种数据导入途径,其中“直接分段”支持通过 PDF、WORD、Markdown 和 CSV 文档内容作为上下文。FastGPT 会自动对文本数据进行预处理、向量化和 QA 分割,节省手动训练时间,提升效能。\n\n![](https://doc.fastgpt.in/imgs/ability2.png)\n\n", - "a": "", - "chunkIndex": 3, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65962b2089642fd209da3b03", - "sourceName": "https://doc.fastgpt.in/docs/intro/", - "sourceId": "https://doc.fastgpt.in/docs/intro/", - "score": [ - { - "type": "embedding", - "value": 0.8158369064331055, - "index": 2 - }, - { - "type": "fullText", - "value": 1.014030612244898, - "index": 20 - }, - { - "type": "reRank", - "value": 0.9064876908461501, - "index": 17 - }, - { - "type": "rrf", - "value": 0.04045823457588163, - "index": 2 - } - ] - }, - { - "id": "65a7e1e8fc13bdf20fd46d41", - "q": "# 快速了解 FastGPT\n## FastGPT 能力\n### 5. 强大的 API 集成\nFastGPT 对外的 API 接口对齐了 OpenAI 官方接口,可以直接接入现有的 GPT 应用,也可以轻松集成到企业微信、公众号、飞书等平台。\n\n![](https://doc.fastgpt.in/imgs/ability4.png)", - "a": "", - "chunkIndex": 66, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7e1d4fc13bdf20fd46abe", - "sourceName": "dataset - 2024-01-04T151625.388.csv", - "sourceId": "65a7e1d2fc13bdf20fd46abc", - "score": [ - { - "type": "embedding", - "value": 0.803692102432251, - "index": 18 - }, - { - "type": "fullText", - "value": 1.0511363636363635, - "index": 7 - }, - { - "type": "reRank", - "value": 0.9177460552422909, - "index": 15 - }, - { - "type": "rrf", - "value": 0.03970501147383226, - "index": 3 - } - ] - }, - { - "id": "65a7be319d96e21823f69c9b", - "q": "FastGPT Flow 的工作流设计方案提供了哪些操作?", - "a": "FastGPT Flow 的工作流设计方案提供了数据预处理、各类 AI 应用设置、调试测试及结果反馈等操作。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8283981680870056, - "index": 0 - }, - { - "type": "reRank", - "value": 0.9620363047907355, - "index": 4 - }, - { - "type": "rrf", - "value": 0.03177805800756621, - "index": 4 - } - ] - }, - { - "id": "65a7be389d96e21823f69d58", - "q": "FastGPT Flow 的实验室预约示例中使用了哪些参数?", - "a": "FastGPT Flow 的实验室预约示例中使用了姓名、时间和实验室名称等参数。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8143455386161804, - "index": 9 - }, - { - "type": "reRank", - "value": 0.9806919138043485, - "index": 1 - }, - { - "type": "rrf", - "value": 0.0304147465437788, - "index": 5 - } - ] - }, - { - "id": "65a7be309d96e21823f69c78", - "q": "FastGPT Flow 是什么?", - "a": "FastGPT Flow 是一款基于大型语言模型的知识库问答系统,通过引入 Flow 可视化工作流编排技术,提供了一个即插即用的解决方案。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8115077018737793, - "index": 11 - }, - { - "type": "reRank", - "value": 0.9686195704870232, - "index": 3 - }, - { - "type": "rrf", - "value": 0.029513888888888888, - "index": 6 - } - ] - }, - { - "id": "65a7be389d96e21823f69d5e", - "q": "FastGPT Flow 的实验室预约示例中的代码实现了哪些功能?", - "a": "FastGPT Flow 的实验室预约示例中的代码实现了预约实验室、修改预约、查询预约和取消预约等功能。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8166953921318054, - "index": 1 - }, - { - "type": "reRank", - "value": 0.8350804533361768, - "index": 20 - }, - { - "type": "rrf", - "value": 0.028474711270410194, - "index": 8 - } - ] - }, - { - "id": "65a7be389d96e21823f69d4f", - "q": "FastGPT Flow 的联网搜索示例中使用了哪些参数?", - "a": "FastGPT Flow 的联网搜索示例中使用了搜索关键词、Google 搜索的 API 密钥和自定义搜索引擎 ID。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8025297522544861, - "index": 21 - }, - { - "type": "reRank", - "value": 0.9730876959261983, - "index": 2 - }, - { - "type": "rrf", - "value": 0.028068137824235385, - "index": 10 - } - ] - }, - { - "id": "65a7e1e8fc13bdf20fd46d55", - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7e1d4fc13bdf20fd46abe", - "sourceName": "dataset - 2024-01-04T151625.388.csv", - "sourceId": "65a7e1d2fc13bdf20fd46abc", - "q": "# 快速了解 FastGPT\n## FastGPT 特点\n1. **项目开源**\n \n FastGPT 遵循附加条件 Apache License 2.0 开源协议,你可以 [Fork](https://github.com/labring/FastGPT/fork) 之后进行二次开发和发布。FastGPT 社区版将保留核心功能,商业版仅在社区版基础上使用 API 的形式进行扩展,不影响学习使用。\n \n2. **独特的 QA 结构**\n \n 针对客服问答场景设计的 QA 结构,提高在大量数据场景中的问答准确性。\n \n3. **可视化工作流**\n \n 通过 Flow 模块展示了从问题输入到模型输出的完整流程,便于调试和设计复杂流程。\n \n4. **无限扩展**\n \n 基于 API 进行扩展,无需修改 FastGPT 源码,也可快速接入现有的程序中。\n \n5. **便于调试**\n \n 提供搜索测试、引用修改、完整对话预览等多种调试途径。\n \n6. **支持多种模型**\n \n 支持 GPT、Claude、文心一言等多种 LLM 模型,未来也将支持自定义的向量模型。", - "a": "", - "chunkIndex": 67, - "score": [ - { - "type": "fullText", - "value": 1.0340073529411764, - "index": 12 - }, - { - "type": "reRank", - "value": 0.9542227274192233, - "index": 9 - }, - { - "type": "rrf", - "value": 0.027272727272727275, - "index": 11 - } - ] - }, - { - "id": "65a7be319d96e21823f69c8f", - "q": "FastGPT Flow 的工作流设计中,模块之间如何进行组合和组装?", - "a": "FastGPT Flow 允许用户在核心工作流模块中进行自由组合和组装,从而衍生出一个新的模块。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8098832368850708, - "index": 13 - }, - { - "type": "reRank", - "value": 0.9478657435317039, - "index": 12 - }, - { - "type": "rrf", - "value": 0.027212143650499815, - "index": 12 - } - ] - }, - { - "id": "65a7be359d96e21823f69ce0", - "q": "FastGPT Flow 的模块的输入和输出如何连接?", - "a": "FastGPT Flow 的模块的输入和输出通过连接点进行连接,连接点的颜色代表了不同的数据类型。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.8060981035232544, - "index": 16 - }, - { - "type": "reRank", - "value": 0.9530133603823691, - "index": 10 - }, - { - "type": "rrf", - "value": 0.027071520029266508, - "index": 13 - } - ] - }, - { - "id": "65a7be319d96e21823f69c98", - "q": "FastGPT Flow 的工作流设计方案能够满足哪些问答场景?", - "a": "FastGPT Flow 的工作流设计方案能够满足基本的 AI 知识库问答需求,并适应各种复杂的问答场景,例如联网搜索、数据库操作、数据实时更新、消息通知等。", - "chunkIndex": 0, - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7be059d96e21823f69af5", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7be059d96e21823f69ae8", - "score": [ - { - "type": "embedding", - "value": 0.814436137676239, - "index": 8 - }, - { - "type": "reRank", - "value": 0.8814109034236719, - "index": 19 - }, - { - "type": "rrf", - "value": 0.026992753623188405, - "index": 16 - } - ] - }, - { - "id": "65a7e058fc13bdf20fd46577", - "datasetId": "6593e137231a2be9c5603ba7", - "collectionId": "65a7e01efc13bdf20fd45815", - "sourceName": "FastGPT软著.pdf", - "sourceId": "65a7e01dfc13bdf20fd457f3", - "q": "FastGPT Flow 工作流设计112312 3123213123 232321312 21312 23一、介绍FastGPT 作为一款基于大型语言模型(LLM)的知识库问答系统,旨在为用户提供一个即插即用的解决方案。它集成了数据处理、模型调用等多项功能,通过引入 Flow 可视化工作流编排技术,进一步增强了对复杂问答场景的支持能力。本文将重点介绍 FastGPT Flow工作流的设计方案和应用优势。\nFastGPT Flow 工 作 流 采 用 了 React Flow 框 架 作 为 UI 底 座 , 结 合 自 研 的 FlowController 实现工作流的运行。FastGPT 使用 Flow 模块为用户呈现了一个直观、可视化的界面,从而简化了 AI 应用工作流程的设计和管理方式。React Flow 的应用使得用户能够以图形化的方式组织和编排工作流,这不仅使得工作流的创建过程更为直观,同时也为用户提供了强大且灵活的工作流编辑器。在 FastGPT Flow 工作流设计中,核心工作流模块包括用户引导、问题输入、知识库检索、AI 文本生成、问题分类、结构化内容提取、指定回复、应用调用和 HTTP 扩展,并允许用户在这类模块中进行自由组合和组装,从而衍生出一个新的模块。", - "a": "", - "chunkIndex": 0, - "score": [ - { - "type": "fullText", - "value": 1.0229779411764706, - "index": 15 - }, - { - "type": "reRank", - "value": 0.9577545043363116, - "index": 8 - }, - { - "type": "rrf", - "value": 0.026992753623188405, - "index": 17 - } - ] - } - ], - "duration": "2.978s", - "searchMode": "mixedRecall", - "limit": 1500, - "similarity": 0.1, - "usingReRank": true, - "usingSimilarityFilter": true - } -} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -HTTP Status Code **200** - -|Name|Type|Required|Restrictions|Title|description| -|---|---|---|---|---|---| -|» code|integer|true|none||none| -|» statusText|string|true|none||none| -|» message|string|true|none||none| -|» data|object|true|none||none| -|»» list|[object]|true|none||none| -|»»» id|string|true|none||none| -|»»» q|string|true|none||none| -|»»» a|string|true|none||none| -|»»» chunkIndex|integer|true|none||none| -|»»» datasetId|string|true|none||none| -|»»» collectionId|string|true|none||none| -|»»» sourceName|string|true|none||none| -|»»» sourceId|string|true|none||none| -|»»» score|[object]|true|none||none| -|»»»» type|string|true|none||none| -|»»»» value|number|true|none||none| -|»»»» index|integer|true|none||none| -|»» duration|string|true|none||none| -|»» searchMode|string|true|none||none| -|»» limit|integer|true|none||none| -|»» similarity|number|true|none||none| -|»» usingReRank|boolean|true|none||none| -|»» usingSimilarityFilter|boolean|true|none||none| - -# openapi/知识库/知识库crud - -## GET 获取知识库列表 - -GET /core/dataset/list - -### Params - -|Name|Location|Type|Required|Description| -|---|---|---|---|---| -|parentId|query|string| no |父级的ID| -|Authorization|header|string| no |none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## GET 获取知识库详情 - -GET /core/dataset/detail - -### Params - -|Name|Location|Type|Required|Description| -|---|---|---|---|---| -|id|query|string| no |知识库id| -|Authorization|header|string| no |none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -# openapi/知识库/集合crud - -## POST 获取知识库集合列表 - -POST /core/dataset/collection/list - -> Body Parameters - -```json -{ - "pageNum": 1, - "pageSize": 10, - "datasetId": "6597ca43e26f2a90a1501414", - "parentId": null, - "searchText": "", - "simple": true -} -``` - -### Params - -|Name|Location|Type|Required|Description| -|---|---|---|---|---| -|Authorization|header|string| no |none| -|body|body|object| no |none| -|» pageNum|body|integer| no |none| -|» pageSize|body|integer| no |none| -|» datasetId|body|string| yes |none| -|» parentId|body|null| no |none| -|» searchText|body|string| no |none| -|» simple|body|boolean| no |none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## GET 获取集合详情 - -GET /core/dataset/collection/detail - -### Params - -|Name|Location|Type|Required|Description| -|---|---|---|---|---| -|id|query|string| no |知识库id| -|Authorization|header|string| no |none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## PUT 更新集合 - -PUT /core/dataset/collection/update - -> Body Parameters - -```json -{ - "id": "6597ce094e10ee661f0891c8", - "parentId": null, - "name": "222" -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» id|body|string| yes ||none| -|» parentId|body|null| no | 父级的id|none| -|» name|body|string| no | 名称|none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## POST 创建空集合(文件夹或者一个空集合) - -POST /core/dataset/collection/create - -> Body Parameters - -```json -{ - "datasetId": "6597ca43e26f2a90a1501414", - "parentId": null, - "name": "集合名", - "type": "folder", - "metadata": {} -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» datasetId|body|string| yes ||none| -|» parentId|body|null| no ||none| -|» name|body|string| yes ||none| -|» type|body|[collection type](#schemacollection%20type)| yes ||none| -|» metadata|body|object| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## POST 创建文本集合 - -POST /core/dataset/collection/create/text - -> Body Parameters - -```json -{ - "text": "xxxxxxxxxxxxxx", - "datasetId": "6593e137231a2be9c5603ba7", - "parentId": null, - "name": "测试", - "trainingType": "qa", - "chunkSize": 8000, - "chunkSplitter": "", - "qaPrompt": "", - "metadata": {} -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» datasetId|body|string| no ||none| -|» parentId|body|null| no ||none| -|» name|body|string| yes ||none| -|» text|body|string| yes | 原文本|none| -|» trainingType|body|[training type](#schematraining%20type)| yes ||none| -|» chunkSize|body|integer| no | 分块大小|none| -|» chunkSplitter|body|string| no | 自定义最高优先级的分段符号|none| -|» qaPrompt|body|string| no ||none| -|» metadata|body|object| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## POST 创建网络链接集合 - -POST /core/dataset/collection/create/link - -> Body Parameters - -```json -{ - "link": "https://doc.fastgpt.in/docs/course/quick-start/", - "datasetId": "6593e137231a2be9c5603ba7", - "parentId": null, - "trainingType": "chunk", - "chunkSize": 512, - "chunkSplitter": "", - "qaPrompt": "", - "metadata": { - "webPageSelector": ".docs-content" - } -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» datasetId|body|string| yes ||none| -|» parentId|body|null| no ||none| -|» link|body|string| yes ||none| -|» trainingType|body|[training type](#schematraining%20type)| yes ||none| -|» chunkSize|body|integer| no ||none| -|» chunkSplitter|body|string| no ||none| -|» qaPrompt|body|string| no ||none| -|» metadata|body|object| no ||none| -|»» webPageSelector|body|string| no | web选择器|none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## DELETE 删除一个集合 - -DELETE /core/dataset/collection/delete - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|id|query|string| no ||知识库id| -|Authorization|header|string| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -# openapi/知识库/数据crud - -## POST 获取数据列表 - -POST /core/dataset/data/list - -> Body Parameters - -```json -{ - "pageNum": 1, - "pageSize": 10, - "collectionId": "65a8d2700d70d3de0bf09186", - "searchText": "" -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» pageNum|body|integer| yes ||none| -|» pageSize|body|integer| yes ||none| -|» searchText|body|string| yes ||none| -|» collectionId|body|string| yes ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## GET 获取数据详情 - -GET /core/dataset/data/detail - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|id|query|string| yes ||none| -|Authorization|header|string| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## DELETE 删除一条数据 - -DELETE /core/dataset/data/delete - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|id|query|string| no ||none| -|Authorization|header|string| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## PUT 更新数据 - -PUT /core/dataset/data/update - -> Body Parameters - -```json -{ - "id": "6597ce094e10ee661f0891c8", - "parentId": null, - "name": "222" -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» id|body|string| yes ||none| -|» q|body|string| yes ||none| -|» a|body|string| no ||none| -|» indexes|body|[[数据自定义向量](#schema%e6%95%b0%e6%8d%ae%e8%87%aa%e5%ae%9a%e4%b9%89%e5%90%91%e9%87%8f)]| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -## POST 知识库插入记录(批量插入) - -POST /core/dataset/data/pushData - -> Body Parameters - -```json -{ - "collectionId": "string", - "data": [ - { - "a": "string", - "q": "string", - "chunkIndex": 1 - } - ], - "trainingMode": "string", - "promot": "string", - "billId": "" -} -``` - -### Params - -|Name|Location|Type|Required|Title|Description| -|---|---|---|---|---|---| -|Authorization|header|string| no ||none| -|body|body|object| no ||none| -|» collectionId|body|string| yes ||none| -|» data|body|[object]| yes ||none| -|»» a|body|string| no ||none| -|»» q|body|string| no ||none| -|»» chunkIndex|body|integer| no ||none| -|» trainingMode|body|[training type](#schematraining%20type)| no ||none| -|» promot|body|string| no ||none| -|» billId|body|string| no ||none| - -> Response Examples - -> 200 Response - -```json -{} -``` - -### Responses - -|HTTP Status Code |Meaning|Description|Data schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|成功|Inline| - -### Responses Data Schema - -# Data Schema - -

similary

- -
- - - - -```json -1 - -``` - -### Attribute - -|Name|Type|Required|Restrictions|Title|Description| -|---|---|---|---|---|---| -|*anonymous*|integer|false|none||none| - - - - - - - - -```json -"embedding" - -``` - -### Attribute - -|Name|Type|Required|Restrictions|Title|Description| -|---|---|---|---|---|---| -|*anonymous*|string|false|none||none| - -#### Enum - -|Name|Value| -|---|---| -|*anonymous*|embedding| -|*anonymous*|fullTextRecall| -|*anonymous*|mixedRecall| - -

training type

- - - - - - -```json -"chunk" - -``` - -### Attribute - -|Name|Type|Required|Restrictions|Title|Description| -|---|---|---|---|---|---| -|*anonymous*|string|false|none||none| - -#### Enum - -|Name|Value| -|---|---| -|*anonymous*|chunk| -|*anonymous*|qa| - -

collection type

- - - - - - -```json -"folder" - -``` - -### Attribute - -|Name|Type|Required|Restrictions|Title|Description| -|---|---|---|---|---|---| -|*anonymous*|string|false|none||none| - -#### Enum - -|Name|Value| -|---|---| -|*anonymous*|folder| -|*anonymous*|virtual| -|*anonymous*|link| -|*anonymous*|file| - -

数据自定义向量

- - - - - - -```json -{ - "defaultIndex": true, - "type": "string", - "text": "string" -} - -``` - -### Attribute - -|Name|Type|Required|Restrictions|Title|Description| -|---|---|---|---|---|---| -|defaultIndex|boolean|false|none||是否为默认| -|type|string|true|none||none| -|text|string|true|none||索引文本| - diff --git a/docSite/content/docs/development/upgrading/467.md b/docSite/content/docs/development/upgrading/467.md index c1ae38654..cf3949c89 100644 --- a/docSite/content/docs/development/upgrading/467.md +++ b/docSite/content/docs/development/upgrading/467.md @@ -27,7 +27,8 @@ curl --location --request POST 'https://{{host}}/api/admin/initv467' \ 1. 修改了知识库UI及新的导入交互方式。 2. 优化知识库和对话的数据索引。 -3. 知识库 openAPI,支持通过 API 操作知识库。(文档待补充) +3. 知识库 openAPI,支持通过 [API 操作知识库](/docs/development/openapi/dataset)。 4. 新增 - 输入框变量提示。输入 { 号后将会获得可用变量提示。根据社区针对高级编排的反馈,我们计划于 2 月份的版本中,优化变量内容,支持模块的局部变量以及更多全局变量写入。 -5. 修复 - API 对话时,chatId 冲突问题。 -6. 修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。 \ No newline at end of file +5. 优化 - 切换团队后会保存记录,下次登录时优先登录该团队。 +6. 修复 - API 对话时,chatId 冲突问题。 +7. 修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。 \ No newline at end of file diff --git a/packages/global/common/error/utils.ts b/packages/global/common/error/utils.ts index 3dedc7986..e237c4685 100644 --- a/packages/global/common/error/utils.ts +++ b/packages/global/common/error/utils.ts @@ -1,5 +1,7 @@ +import { replaceSensitiveLink } from '../string/tools'; + export const getErrText = (err: any, def = '') => { const msg: string = typeof err === 'string' ? err : err?.message || def || ''; msg && console.log('error =>', msg); - return msg; + return replaceSensitiveLink(msg); }; diff --git a/packages/global/common/string/tools.ts b/packages/global/common/string/tools.ts index 2fa177ac1..333965459 100644 --- a/packages/global/common/string/tools.ts +++ b/packages/global/common/string/tools.ts @@ -38,6 +38,12 @@ export function replaceVariable(text: string, obj: Record { + const urlRegex = /(?<=https?:\/\/)[^\s]+/g; + return text.replace(urlRegex, 'xxx'); +}; + export const getNanoid = (size = 12) => { return customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', size)(); }; diff --git a/packages/service/common/file/utils.ts b/packages/service/common/file/utils.ts index f3214056f..3a744ef2c 100644 --- a/packages/service/common/file/utils.ts +++ b/packages/service/common/file/utils.ts @@ -4,7 +4,7 @@ export const removeFilesByPaths = (paths: string[]) => { paths.forEach((path) => { fs.unlink(path, (err) => { if (err) { - console.error(err); + // console.error(err); } }); }); diff --git a/packages/service/common/response/index.ts b/packages/service/common/response/index.ts index 293c980fd..569cfd066 100644 --- a/packages/service/common/response/index.ts +++ b/packages/service/common/response/index.ts @@ -3,6 +3,7 @@ import { sseResponseEventEnum } from './constant'; import { proxyError, ERROR_RESPONSE, ERROR_ENUM } from '@fastgpt/global/common/error/errorCode'; import { addLog } from '../system/log'; import { clearCookie } from '../../support/permission/controller'; +import { replaceSensitiveLink } from '@fastgpt/global/common/string/tools'; export interface ResponseType { code: number; @@ -52,7 +53,7 @@ export const jsonRes = ( res.status(code).json({ code, statusText: '', - message: message || msg, + message: replaceSensitiveLink(message || msg), data: data !== undefined ? data : null }); }; @@ -90,7 +91,7 @@ export const sseErrRes = (res: NextApiResponse, error: any) => { responseWrite({ res, event: sseResponseEventEnum.error, - data: JSON.stringify({ message: msg }) + data: JSON.stringify({ message: replaceSensitiveLink(msg) }) }); }; diff --git a/packages/service/support/permission/controller.ts b/packages/service/support/permission/controller.ts index 3a064a4f7..34660eac1 100644 --- a/packages/service/support/permission/controller.ts +++ b/packages/service/support/permission/controller.ts @@ -168,6 +168,10 @@ export async function parseHeaderCert({ return Promise.reject(ERROR_ENUM.unAuthorization); })(); + if (!authRoot && (!teamId || !tmbId)) { + return Promise.reject(ERROR_ENUM.unAuthorization); + } + return { userId: String(uid), teamId: String(teamId), diff --git a/packages/web/components/common/Icon/icons/support/account/loginoutLight.svg b/packages/web/components/common/Icon/icons/support/account/loginoutLight.svg index 9bf4c43e5..252c61549 100644 --- a/packages/web/components/common/Icon/icons/support/account/loginoutLight.svg +++ b/packages/web/components/common/Icon/icons/support/account/loginoutLight.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/projects/app/public/docs/versionIntro.md b/projects/app/public/docs/versionIntro.md index 15150a81f..46bc42bdc 100644 --- a/projects/app/public/docs/versionIntro.md +++ b/projects/app/public/docs/versionIntro.md @@ -4,8 +4,9 @@ 2. 优化知识库和对话的数据索引,加快数据操作。 3. 知识库 openAPI,支持通过 API 操作知识库。 4. 新增 - 输入框变量提示。输入 { 号后将会获得可用变量提示。根据社区针对高级编排的反馈,我们计划于 2 月份的版本中,优化变量内容,支持模块的局部变量以及更多全局变量写入。 -5. 修复 - API 对话时,chatId 冲突问题。 -6. 修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。 -7. [使用文档](https://doc.fastgpt.in/docs/intro/) -8. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow) -9. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) +5. 优化 - 切换团队后会保存记录,下次登录时优先登录该团队。 +6. 修复 - API 对话时,chatId 冲突问题。 +7. 修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。 +8. [使用文档](https://doc.fastgpt.in/docs/intro/) +9. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow) +10. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index 78c0740c1..e802c7706 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -95,7 +95,7 @@ "Last Step": "上一步", "Last use time": "最后使用时间", "Load Failed": "加载失败", - "Loading": "加载中", + "Loading": "加载中...", "Max credit": "最大金额", "Max credit tips": "该链接最大可消耗多少金额,超出后链接将被禁止使用。-1 代表无限制。", "More settings": "更多设置", @@ -541,7 +541,8 @@ "success": "开始同步" } }, - "training": {} + "training": { + } }, "data": { "Auxiliary Data": "辅助数据", diff --git a/projects/app/src/components/ChatBox/MessageInput.tsx b/projects/app/src/components/ChatBox/MessageInput.tsx index 39a727435..42b621e23 100644 --- a/projects/app/src/components/ChatBox/MessageInput.tsx +++ b/projects/app/src/components/ChatBox/MessageInput.tsx @@ -1,7 +1,7 @@ import { useSpeech } from '@/web/common/hooks/useSpeech'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { Box, Flex, Image, Spinner, Textarea } from '@chakra-ui/react'; -import React, { useRef, useEffect, useCallback, useState } from 'react'; +import React, { useRef, useEffect, useCallback, useState, useTransition } from 'react'; import { useTranslation } from 'next-i18next'; import MyTooltip from '../MyTooltip'; import MyIcon from '@fastgpt/web/components/common/Icon'; @@ -37,7 +37,7 @@ const MessageInput = ({ showFileSelector = false, resetInputVal }: { - onChange: (e: string) => void; + onChange?: (e: string) => void; onSendMessage: (e: string) => void; onStop: () => void; isChatting: boolean; @@ -45,6 +45,8 @@ const MessageInput = ({ TextareaDom: React.MutableRefObject; resetInputVal: (val: string) => void; }) => { + const [, startSts] = useTransition(); + const { shareId } = useRouter().query as { shareId?: string }; const { isSpeaking, @@ -330,17 +332,29 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')} const textarea = e.target; textarea.style.height = textareaMinH; textarea.style.height = `${textarea.scrollHeight}px`; - onChange(textarea.value); + + startSts(() => { + onChange?.(textarea.value); + }); }} onKeyDown={(e) => { // enter send.(pc or iframe && enter and unPress shift) + const isEnter = e.keyCode === 13; + if (isEnter && TextareaDom.current && (e.ctrlKey || e.altKey)) { + TextareaDom.current.value += '\n'; + TextareaDom.current.style.height = textareaMinH; + TextareaDom.current.style.height = `${TextareaDom.current.scrollHeight}px`; + return; + } + + // 全选内容 + // @ts-ignore + e.key === 'a' && e.ctrlKey && e.target?.select(); + if ((isPc || window !== parent) && e.keyCode === 13 && !e.shiftKey) { handleSend(); e.preventDefault(); } - // 全选内容 - // @ts-ignore - e.key === 'a' && e.ctrlKey && e.target?.select(); }} onPaste={(e) => { const clipboardData = e.clipboardData; diff --git a/projects/app/src/components/ChatBox/index.tsx b/projects/app/src/components/ChatBox/index.tsx index 9c57b2f88..6683f1de1 100644 --- a/projects/app/src/components/ChatBox/index.tsx +++ b/projects/app/src/components/ChatBox/index.tsx @@ -36,7 +36,7 @@ import { adaptChat2GptMessages } from '@fastgpt/global/core/chat/adapt'; import { useMarkdown } from '@/web/common/hooks/useMarkdown'; import { ModuleItemType } from '@fastgpt/global/core/module/type.d'; import { VariableInputEnum } from '@fastgpt/global/core/module/constants'; -import { useForm } from 'react-hook-form'; +import { UseFormReturn, useForm } from 'react-hook-form'; import type { ChatMessageItemType } from '@fastgpt/global/core/ai/type.d'; import { fileDownload } from '@/web/common/file/utils'; import { htmlTemplate } from '@/constants/common'; @@ -65,7 +65,7 @@ const SelectMarkCollection = dynamic(() => import('./SelectMarkCollection')); import styles from './index.module.scss'; import { postQuestionGuide } from '@/web/core/ai/api'; import { splitGuideModule } from '@fastgpt/global/core/module/utils'; -import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d'; +import type { AppTTSConfigType, VariableItemType } from '@fastgpt/global/core/module/type.d'; import MessageInput from './MessageInput'; import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants'; import ChatBoxDivider from '../core/chat/Divider'; @@ -98,6 +98,15 @@ enum FeedbackTypeEnum { hidden = 'hidden' } +const MessageCardStyle: BoxProps = { + px: 4, + py: 3, + borderRadius: '0 8px 8px 8px', + boxShadow: '0 0 8px rgba(0,0,0,0.15)', + display: 'inline-block', + maxW: ['calc(100% - 25px)', 'calc(100% - 40px)'] +}; + type Props = { feedbackType?: `${FeedbackTypeEnum}`; showMarkIcon?: boolean; // admin mark dataset @@ -157,7 +166,6 @@ const ChatBox = ( const isNewChatReplace = useRef(false); const [refresh, setRefresh] = useState(false); - const [variables, setVariables] = useState>({}); // settings variable const [chatHistory, setChatHistory] = useState([]); const [feedbackId, setFeedbackId] = useState(); const [readFeedbackData, setReadFeedbackData] = useState<{ @@ -180,7 +188,17 @@ const ChatBox = ( ); // compute variable input is finish. - const [variableInputFinish, setVariableInputFinish] = useState(false); + const chatForm = useForm<{ + variables: Record; + }>({ + defaultValues: { + variables: {} + } + }); + const { setValue, watch, handleSubmit } = chatForm; + const variables = watch('variables'); + + const [variableInputFinish, setVariableInputFinish] = useState(false); // clicked start chat button const variableIsFinish = useMemo(() => { if (!variableModules || variableModules.length === 0 || chatHistory.length > 0) return true; @@ -194,21 +212,15 @@ const ChatBox = ( return variableInputFinish; }, [chatHistory.length, variableInputFinish, variableModules, variables]); - const { register, reset, getValues, setValue, handleSubmit } = useForm>({ - defaultValues: variables - }); - // 滚动到底部 - const scrollToBottom = useCallback( - (behavior: 'smooth' | 'auto' = 'smooth') => { - if (!ChatBoxRef.current) return; - ChatBoxRef.current.scrollTo({ - top: ChatBoxRef.current.scrollHeight, - behavior - }); - }, - [ChatBoxRef] - ); + const scrollToBottom = (behavior: 'smooth' | 'auto' = 'smooth') => { + if (!ChatBoxRef.current) return; + ChatBoxRef.current.scrollTo({ + top: ChatBoxRef.current.scrollHeight, + behavior + }); + }; + // 聊天信息生成中……获取当前滚动条位置,判断是否需要滚动到底部 const generatingScroll = useCallback( throttle(() => { @@ -222,28 +234,31 @@ const ChatBox = ( [] ); // eslint-disable-next-line react-hooks/exhaustive-deps - const generatingMessage = ({ text = '', status, name }: generatingMessageProps) => { - setChatHistory((state) => - state.map((item, index) => { - if (index !== state.length - 1) return item; - return { - ...item, - ...(text - ? { - value: item.value + text - } - : {}), - ...(status && name - ? { - status, - moduleName: name - } - : {}) - }; - }) - ); - generatingScroll(); - }; + const generatingMessage = useCallback( + ({ text = '', status, name }: generatingMessageProps) => { + setChatHistory((state) => + state.map((item, index) => { + if (index !== state.length - 1) return item; + return { + ...item, + ...(text + ? { + value: item.value + text + } + : {}), + ...(status && name + ? { + status, + moduleName: name + } + : {}) + }; + }) + ); + generatingScroll(); + }, + [generatingScroll] + ); // 重置输入内容 const resetInputVal = useCallback((val: string) => { @@ -284,149 +299,157 @@ const ChatBox = ( } } catch (error) {} }, - [questionGuide, scrollToBottom, shareId] + [questionGuide, shareId] ); /** * user confirm send prompt */ const sendPrompt = useCallback( - async (variables: Record = {}, inputVal = '', history = chatHistory) => { - if (!onStartChat) return; - if (isChatting) { - toast({ - title: '正在聊天中...请等待结束', - status: 'warning' - }); - return; - } - questionGuideController.current?.abort('stop'); - // get input value - const val = inputVal.trim(); - - if (!val) { - toast({ - title: '内容为空', - status: 'warning' - }); - return; - } - - const newChatList: ChatSiteItemType[] = [ - ...history, - { - dataId: nanoid(), - obj: 'Human', - value: val, - status: 'finish' - }, - { - dataId: nanoid(), - obj: 'AI', - value: '', - status: 'loading' - } - ]; - - // 插入内容 - setChatHistory(newChatList); - - // 清空输入内容 - resetInputVal(''); - setQuestionGuide([]); - setTimeout(() => { - scrollToBottom(); - }, 100); - try { - // create abort obj - const abortSignal = new AbortController(); - chatController.current = abortSignal; - - const messages = adaptChat2GptMessages({ messages: newChatList, reserveId: true }); - - const { - responseData, - responseText, - isNewChat = false - } = await onStartChat({ - chatList: newChatList.map((item) => ({ - dataId: item.dataId, - obj: item.obj, - value: item.value, - status: item.status, - moduleName: item.moduleName - })), - messages, - controller: abortSignal, - generatingMessage, - variables - }); - - isNewChatReplace.current = isNewChat; - - // set finish status - setChatHistory((state) => - state.map((item, index) => { - if (index !== state.length - 1) return item; - return { - ...item, - status: 'finish', - responseData - }; - }) - ); - - setTimeout(() => { - createQuestionGuide({ - history: newChatList.map((item, i) => - i === newChatList.length - 1 - ? { - ...item, - value: responseText - } - : item - ) + ({ + inputVal = '', + history = chatHistory + }: { + inputVal?: string; + history?: ChatSiteItemType[]; + }) => { + handleSubmit(async ({ variables }) => { + if (!onStartChat) return; + if (isChatting) { + toast({ + title: '正在聊天中...请等待结束', + status: 'warning' }); - generatingScroll(); - isPc && TextareaDom.current?.focus(); - }, 100); - } catch (err: any) { - toast({ - title: t(getErrText(err, 'core.chat.error.Chat error')), - status: 'error', - duration: 5000, - isClosable: true - }); + return; + } + questionGuideController.current?.abort('stop'); + // get input value + const val = inputVal.trim(); - if (!err?.responseText) { - resetInputVal(inputVal); - setChatHistory(newChatList.slice(0, newChatList.length - 2)); + if (!val) { + toast({ + title: '内容为空', + status: 'warning' + }); + return; } - // set finish status - setChatHistory((state) => - state.map((item, index) => { - if (index !== state.length - 1) return item; - return { - ...item, - status: 'finish' - }; - }) - ); - } + const newChatList: ChatSiteItemType[] = [ + ...history, + { + dataId: nanoid(), + obj: 'Human', + value: val, + status: 'finish' + }, + { + dataId: nanoid(), + obj: 'AI', + value: '', + status: 'loading' + } + ]; + + // 插入内容 + setChatHistory(newChatList); + + // 清空输入内容 + resetInputVal(''); + setQuestionGuide([]); + setTimeout(() => { + scrollToBottom(); + }, 100); + try { + // create abort obj + const abortSignal = new AbortController(); + chatController.current = abortSignal; + + const messages = adaptChat2GptMessages({ messages: newChatList, reserveId: true }); + + const { + responseData, + responseText, + isNewChat = false + } = await onStartChat({ + chatList: newChatList.map((item) => ({ + dataId: item.dataId, + obj: item.obj, + value: item.value, + status: item.status, + moduleName: item.moduleName + })), + messages, + controller: abortSignal, + generatingMessage, + variables + }); + + isNewChatReplace.current = isNewChat; + + // set finish status + setChatHistory((state) => + state.map((item, index) => { + if (index !== state.length - 1) return item; + return { + ...item, + status: 'finish', + responseData + }; + }) + ); + + setTimeout(() => { + createQuestionGuide({ + history: newChatList.map((item, i) => + i === newChatList.length - 1 + ? { + ...item, + value: responseText + } + : item + ) + }); + generatingScroll(); + isPc && TextareaDom.current?.focus(); + }, 100); + } catch (err: any) { + toast({ + title: t(getErrText(err, 'core.chat.error.Chat error')), + status: 'error', + duration: 5000, + isClosable: true + }); + + if (!err?.responseText) { + resetInputVal(inputVal); + setChatHistory(newChatList.slice(0, newChatList.length - 2)); + } + + // set finish status + setChatHistory((state) => + state.map((item, index) => { + if (index !== state.length - 1) return item; + return { + ...item, + status: 'finish' + }; + }) + ); + } + })(); }, [ chatHistory, - onStartChat, - isChatting, - resetInputVal, - toast, - scrollToBottom, - generatingMessage, createQuestionGuide, + generatingMessage, generatingScroll, + handleSubmit, + isChatting, isPc, - t + onStartChat, + resetInputVal, + t, + toast ] ); @@ -444,11 +467,14 @@ const ChatBox = ( ); setChatHistory((state) => (index === 0 ? [] : state.slice(0, index))); - sendPrompt(variables, delHistory[0].value, chatHistory.slice(0, index)); + sendPrompt({ + inputVal: delHistory[0].value, + history: chatHistory.slice(0, index) + }); } catch (error) {} setLoading(false); }, - [chatHistory, onDelMessage, sendPrompt, setLoading, variables] + [chatHistory, onDelMessage, sendPrompt, setLoading] ); // delete one message const delOneMessage = useCallback( @@ -471,27 +497,21 @@ const ChatBox = ( defaultVal[item.key] = ''; }); - reset(e || defaultVal); - setVariables(e || defaultVal); + setValue('variables', e || defaultVal); }, resetHistory(e) { setVariableInputFinish(!!e.length); setChatHistory(e); }, scrollToBottom, - sendPrompt: (question: string) => handleSubmit((item) => sendPrompt(item, question))() + sendPrompt: (question: string) => { + sendPrompt({ + inputVal: question + }); + } })); /* style start */ - const MessageCardStyle: BoxProps = { - px: 4, - py: 3, - borderRadius: '0 8px 8px 8px', - boxShadow: '0 0 8px rgba(0,0,0,0.15)', - display: 'inline-block', - maxW: ['calc(100% - 25px)', 'calc(100% - 40px)'] - }; - const showEmpty = useMemo( () => feConfigs?.show_emptyChat && @@ -534,14 +554,18 @@ const ChatBox = ( useEffect(() => { const windowMessage = ({ data }: MessageEvent<{ type: 'sendPrompt'; text: string }>) => { if (data?.type === 'sendPrompt' && data?.text) { - handleSubmit((item) => sendPrompt(item, data.text))(); + sendPrompt({ + inputVal: data.text + }); } }; window.addEventListener('message', windowMessage); eventBus.on(EventNameEnum.sendQuestion, ({ text }: { text: string }) => { if (!text) return; - handleSubmit((data) => sendPrompt(data, text))(); + sendPrompt({ + inputVal: text + }); }); eventBus.on(EventNameEnum.editQuestion, ({ text }: { text: string }) => { if (!text) return; @@ -553,140 +577,81 @@ const ChatBox = ( eventBus.off(EventNameEnum.sendQuestion); eventBus.off(EventNameEnum.editQuestion); }; - }, [handleSubmit, resetInputVal, sendPrompt]); + }, [resetInputVal, sendPrompt]); + + const onSubmitVariables = useCallback( + (data: Record) => { + setVariableInputFinish(true); + onUpdateVariable?.(data); + }, + [onUpdateVariable] + ); + const HumanChatCard = useCallback( + ({ item, index }: { item: ChatSiteItemType; index: number }) => { + return ( + <> + {/* control icon */} + + { + delOneMessage({ dataId: item.dataId, index }); + } + : undefined + } + onRetry={useCallback(() => retryInput(index), [index])} + /> + + + {/* content */} + + + + + + + ); + }, + [] + ); return ( - {/* chat box container */} {showEmpty && } - - {!!welcomeText && ( - - {/* avatar */} - - {/* message */} - - - - - - - )} + {!!welcomeText && } {/* variable input */} {!!variableModules?.length && ( - - {/* avatar */} - - {/* message */} - - - {variableModules.map((item) => ( - - {item.label} - {item.type === VariableInputEnum.input && ( - - )} - {item.type === VariableInputEnum.textarea && ( -