From 16103029f595899699cc4b5e3843769f21a30680 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Thu, 16 Nov 2023 10:46:47 +0800 Subject: [PATCH] doc and config rerank (#475) --- .../content/docs/installation/upgrading/46.md | 8 ++--- docSite/content/docs/use-cases/ai_settings.md | 26 +++++++-------- .../content/docs/use-cases/datasetEngine.md | 24 +++++++------- packages/global/core/module/node/type.d.ts | 1 + projects/app/public/locales/en/common.json | 3 ++ projects/app/public/locales/zh/common.json | 3 ++ .../core/module/DatasetSelectModal.tsx | 28 ++++++++++++++-- .../Flow/components/render/RenderInput.tsx | 32 +++++++++++++++++-- .../app/src/constants/flow/ModuleTemplate.ts | 8 +++++ .../app/src/global/core/api/datasetReq.d.ts | 1 + .../src/pages/api/core/dataset/searchTest.ts | 5 +-- .../app/detail/components/BasicEdit/index.tsx | 18 +++++------ .../pages/dataset/detail/components/Test.tsx | 14 ++++++-- .../app/src/service/core/dataset/data/pg.ts | 11 ++++++- .../src/service/moduleDispatch/chat/oneapi.ts | 2 +- .../service/moduleDispatch/dataset/search.ts | 8 +++-- projects/app/src/web/common/api/fetch.ts | 3 +- .../app/src/web/core/app/basicSettings.ts | 18 ++++++++++- 18 files changed, 158 insertions(+), 55 deletions(-) diff --git a/docSite/content/docs/installation/upgrading/46.md b/docSite/content/docs/installation/upgrading/46.md index 406c5e5c8..552326b10 100644 --- a/docSite/content/docs/installation/upgrading/46.md +++ b/docSite/content/docs/installation/upgrading/46.md @@ -7,16 +7,16 @@ toc: true weight: 836 --- -# V4.6 版本加入了简单的团队功能,可以邀请其他用户进来管理资源。该版本升级后无法执行旧的升级脚本,且无法回退。 +**V4.6 版本加入了简单的团队功能,可以邀请其他用户进来管理资源。该版本升级后无法执行旧的升级脚本,且无法回退。** -# 1. 更新镜像并变更配置文件 +## 1. 更新镜像并变更配置文件 更新镜像至 latest 或者 v4.6 版本。商业版镜像更新至 V0.2.1 最新配置可参考: [V46版本最新 config.json](/docs/development/configuration),商业镜像配置文件也更新,参考最新的飞书文档。 -# 2. 执行初始化 API +## 2. 执行初始化 API 发起 2 个 HTTP 请求({{rootkey}} 替换成环境变量里的`rootkey`,{{host}}替换成自己域名) @@ -45,7 +45,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv46-2' \ 4. 初始化 Mongo Data -# V4.6功能介绍 +## V4.6功能介绍 1. 新增 - 团队空间 2. 新增 - 多路向量(多个向量映射一组数据) diff --git a/docSite/content/docs/use-cases/ai_settings.md b/docSite/content/docs/use-cases/ai_settings.md index 0d96d1ce2..c73b65047 100644 --- a/docSite/content/docs/use-cases/ai_settings.md +++ b/docSite/content/docs/use-cases/ai_settings.md @@ -9,23 +9,23 @@ weight: 310 在 FastGPT 的 AI 对话模块中,有一个 AI 高级配置,里面包含了 AI 模型的参数配置,本文详细介绍这些配置的含义。 -# 返回AI内容 +## 返回AI内容 这是一个开关,打开的时候,当 AI 对话模块运行时,会将其输出的内容返回到浏览器(API响应);如果关闭,AI 输出的内容不会返回到浏览器,但是生成的内容仍可以通过【AI回复】进行输出。你可以将【AI回复】连接到其他模块中。 -# 温度 +## 温度 可选范围0-10,约大代表生成的内容约自由扩散,越小代表约严谨。调节能力有限,知识库问答场景通常设置为0。 -# 回复上限 +## 回复上限 控制 AI 回复的最大 Tokens,较小的值可以一定程度上减少 AI 的废话,但也可能导致 AI 回复不完整。 -# 引用模板 & 引用提示词 +## 引用模板 & 引用提示词 这两个参数与知识库问答场景相关,可以控制知识库相关的提示词。 -## AI 对话消息组成 +### AI 对话消息组成 想使用明白这两个变量,首先要了解传递传递给 AI 模型的消息格式。它是一个数组,FastGPT 中这个数组的组成形式为: @@ -42,7 +42,7 @@ weight: 310 Tips: 可以通过点击上下文按键查看完整的上下文组成,便于调试。 {{% /alert %}} -## 引用模板和提示词设计 +### 引用模板和提示词设计 引用模板和引用提示词通常是成对出现,引用提示词依赖引用模板。 @@ -50,7 +50,7 @@ FastGPT 知识库采用 QA 对(不一定都是问答格式,仅代表两个变 可以通过 [知识库结构讲解](/docs/use-cases/datasetEngine/) 了解详细的知识库的结构。 -### 引用模板 +#### 引用模板 ``` {instruction:"{{q}}",output:"{{a}}",source:"{{source}}"} @@ -64,7 +64,7 @@ FastGPT 知识库采用 QA 对(不一定都是问答格式,仅代表两个变 {instruction:"电影《铃芽之旅》的编剧是谁?22",output:"新海诚是本片的编剧。",source:"手动输入"} ``` -### 引用提示词 +#### 引用提示词 引用模板需要和引用提示词一起使用,提示词中可以写引用模板的格式说明以及对话的要求等。可以使用 {{quote}} 来使用 **引用模板**,使用 {{question}} 来引入问题。例如: @@ -95,15 +95,15 @@ FastGPT 知识库采用 QA 对(不一定都是问答格式,仅代表两个变 我的问题是:"{{question}}" ``` -### 总结 +#### 总结 引用模板规定了搜索出来的内容如何组成一句话,其由 q,a,index,source 多个变量组成。 引用提示词由`引用模板`和`提示词`组成,提示词通常是对引用模板的一个描述,加上对模型的要求。 -## 引用模板和提示词设计 示例 +### 引用模板和提示词设计 示例 -### 通用模板与问答模板对比 +#### 通用模板与问答模板对比 我们通过一组`你是谁`的手动数据,对通用模板与问答模板的效果进行对比。此处特意打了个搞笑的答案,通用模板下 GPT35 就变得不那么听话了,而问答模板下 GPT35 依然能够回答正确。这是由于结构化的提示词,在大语言模型中具有更强的引导作用。 @@ -117,7 +117,7 @@ Tips: 建议根据不同的场景,每种知识库仅选择1类数据类型, | ![](/imgs/datasetprompt3.png) | ![](/imgs/datasetprompt5.png) | | ![](/imgs/datasetprompt4.png) | ![](/imgs/datasetprompt6.png) | -### 严格模板 +#### 严格模板 使用非严格模板,我们随便询问一个不在知识库中的内容,模型通常会根据其自身知识进行回答。 @@ -125,7 +125,7 @@ Tips: 建议根据不同的场景,每种知识库仅选择1类数据类型, | --- | --- | --- | | ![](/imgs/datasetprompt7.png) | ![](/imgs/datasetprompt8.png) |![](/imgs/datasetprompt9.png) | -### 提示词设计思路 +#### 提示词设计思路 1. 使用序号进行不同要求描述。 2. 使用首先、然后、最后等词语进行描述。 diff --git a/docSite/content/docs/use-cases/datasetEngine.md b/docSite/content/docs/use-cases/datasetEngine.md index 48e9d6c5e..e9058377c 100644 --- a/docSite/content/docs/use-cases/datasetEngine.md +++ b/docSite/content/docs/use-cases/datasetEngine.md @@ -7,7 +7,7 @@ toc: true weight: 311 --- -# 理解向量 +## 理解向量 FastGPT 采用了 RAG 中的 Embedding 方案构建知识库,要使用好 FastGPT 需要简单的理解`Embedding`向量是如何工作的及其特点。 @@ -21,7 +21,7 @@ FastGPT 采用了 RAG 中的 Embedding 方案构建知识库,要使用好 Fast 检索器的精度比较容易解决,向量模型的训练略复杂,因此数据和检索词质量优化成了一个重要的环节。 -# FastGPT 中向量的结构设计 +## FastGPT 中向量的结构设计 FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器,索引为`HNSW`。且`PostgresSQL`仅用于向量检索,`MongoDB`用于其他数据的存取。 @@ -29,13 +29,13 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, ![](/imgs/datasetSetting1.png) -## 多向量的目的和使用方式 +### 多向量的目的和使用方式 -在一组数据中,如果我们希望它尽可能长,但语义又要在向量中尽可能提现,则没有办法通过一组向量来表示。因此,我们采用了多向量映射的方式,将一组数据映射到多组向量中,从而保障数据的完整性和语义的提现。 +在一组向量中,内容的长度和语义的丰富度通常是矛盾的,无法兼得。因此,FastGPT 采用了多向量映射的方式,将一组数据映射到多组向量中,从而保障数据的完整性和语义的丰富度。 你可以为一组较长的文本,添加多组向量,从而在检索时,只要其中一组向量被检索到,该数据也将被召回。 -## 提高向量搜索精度的方法 +### 提高向量搜索精度的方法 1. 更好分词分段:当一段话的结构和语义是完整的,并且是单一的,精度也会提高。因此,许多系统都会优化分词器,尽可能的保障每组数据的完整性。 2. 精简`index`的内容,减少向量内容的长度:当`index`的内容更少,更准确时,检索精度自然会提高。但与此同时,会牺牲一定的检索范围,适合答案较为严格的场景。 @@ -43,7 +43,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, 4. 优化检索词:在实际使用过程中,用户的问题通常是模糊的或是缺失的,并不一定是完整清晰的问题。因此优化用户的问题(检索词)很大程度上也可以提高精度。 5. 微调向量模型:由于市面上直接使用的向量模型都是通用型模型,在特定领域的检索精度并不高,因此微调向量模型可以很大程度上提高专业领域的检索效果。 -# FastGPT 构建知识库方案 +## FastGPT 构建知识库方案 在 FastGPT 中,整个知识库由库、集合和数据 3 部分组成。集合可以简单理解为一个`文件`。一个`库`中可以包含多个`集合`,一个`集合`中可以包含多组`数据`。最小的搜索单位是`库`,也就是说,知识库搜索时,是对整个`库`进行搜索,而集合仅是为了对数据进行分类管理,与搜索效果无关。(起码目前还是) @@ -51,7 +51,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | --- | --- | --- | | ![](/imgs/datasetEngine1.png) | ![](/imgs/datasetEngine2.png) | ![](/imgs/datasetEngine3.png) | -## 导入数据方案1 - 直接分段导入 +### 导入数据方案1 - 直接分段导入 选择文件导入时,可以选择直接分段方案。直接分段会利用`句子分词器`对文本进行一定长度拆分,最终分割中多组的`q`。如果使用了直接分段方案,我们建议在`应用`设置`引用提示词`时,使用`通用模板`即可,无需选择`问答模板`。 @@ -60,7 +60,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | ![](/imgs/datasetEngine4.png) | ![](/imgs/datasetEngine5.png) | -## 导入数据方案2 - QA导入 +### 导入数据方案2 - QA导入 选择文件导入时,可以选择QA拆分方案。仍然需要使用到`句子分词器`对文本进行拆分,但长度比直接分段大很多。在导入后,会先调用`大模型`对分段进行学习,并给出一些`问题`和`答案`,最终问题和答案会一起被存储到`q`中。注意,新版的 FastGPT 为了提高搜索的范围,不再将问题和答案分别存储到 qa 中。 @@ -68,7 +68,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | --- | --- | | ![](/imgs/datasetEngine6.png) | ![](/imgs/datasetEngine7.png) | -## 导入数据方案3 - 手动录入 +### 导入数据方案3 - 手动录入 在 FastGPT 中,你可以在任何一个`集合`中点击右上角的`插入`手动录入知识点,或者使用`标注`功能手动录入。被搜索的内容为`q`,补充内容(可选)为`a`。 @@ -76,16 +76,16 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | --- | --- | --- | | ![](/imgs/datasetEngine8.png) | ![](/imgs/datasetEngine9.png) | ![](/imgs/datasetEngine10.png) | -## 导入数据方案4 - CSV录入 +### 导入数据方案4 - CSV录入 有些数据较为独特,可能需要单独的进行预处理分割后再导入 FastGPT,此时可以选择 csv 导入,可批量的将处理好的数据导入。 ![](/imgs/datasetEngine11.png) -## 导入数据方案5 - API导入 +### 导入数据方案5 - API导入 参考[FastGPT OpenAPI使用](/docs/development/openapi/#知识库添加数据)。 -# QA的组合与引用提示词构建 +## QA的组合与引用提示词构建 参考[引用模板与引用提示词示例](/docs/use-cases/ai_settings/#示例) diff --git a/packages/global/core/module/node/type.d.ts b/packages/global/core/module/node/type.d.ts index 999f1c3d3..9ee5ee4f9 100644 --- a/packages/global/core/module/node/type.d.ts +++ b/packages/global/core/module/node/type.d.ts @@ -32,6 +32,7 @@ export type FlowNodeInputItemType = { connected?: boolean; description?: string; placeholder?: string; + plusField?: boolean; max?: number; min?: number; step?: number; diff --git a/projects/app/public/locales/en/common.json b/projects/app/public/locales/en/common.json index bdb957cf0..360ebb91f 100644 --- a/projects/app/public/locales/en/common.json +++ b/projects/app/public/locales/en/common.json @@ -317,6 +317,9 @@ }, "deleteDatasetTips": "Are you sure to delete the knowledge base? Data cannot be recovered after deletion, please confirm!", "deleteFolderTips": "Are you sure to delete this folder and all the knowledge bases it contains? Data cannot be recovered after deletion, please confirm!", + "recall": { + "rerank": "Rerank" + }, "test": { "noResult": "Search results are empty" } diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index cd6ceaa42..dcef53a46 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -317,6 +317,9 @@ }, "deleteDatasetTips": "确认删除该知识库?删除后数据无法恢复,请确认!", "deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!", + "recall": { + "rerank": "结果重排" + }, "test": { "noResult": "搜索结果为空" } diff --git a/projects/app/src/components/core/module/DatasetSelectModal.tsx b/projects/app/src/components/core/module/DatasetSelectModal.tsx index 015a63a68..bd2fe6fb3 100644 --- a/projects/app/src/components/core/module/DatasetSelectModal.tsx +++ b/projects/app/src/components/core/module/DatasetSelectModal.tsx @@ -9,7 +9,8 @@ import { useTheme, Textarea, Grid, - Divider + Divider, + Switch } from '@chakra-ui/react'; import Avatar from '@/components/Avatar'; import { useForm } from 'react-hook-form'; @@ -30,6 +31,7 @@ export type KbParamsType = { searchSimilarity: number; searchLimit: number; searchEmptyText: string; + rerank: boolean; }; export const DatasetSelectModal = ({ @@ -225,10 +227,11 @@ export const DatasetSelectModal = ({ ); }; -export const KbParamsModal = ({ +export const DatasetParamsModal = ({ searchEmptyText, searchLimit, searchSimilarity, + rerank, onClose, onChange }: KbParamsType & { onClose: () => void; onChange: (e: KbParamsType) => void }) => { @@ -237,7 +240,8 @@ export const KbParamsModal = ({ defaultValues: { searchEmptyText, searchLimit, - searchSimilarity + searchSimilarity, + rerank } }); @@ -245,6 +249,24 @@ export const KbParamsModal = ({ + {feConfigs?.isPlus && ( + + + 结果重排 + + + + + { + setValue('rerank', e.target.checked); + setRefresh(!refresh); + }} + /> + + )} 相似度 diff --git a/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx b/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx index 2031b2a0e..1e39db09c 100644 --- a/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx @@ -14,7 +14,8 @@ import { useDisclosure, Button, useTheme, - Grid + Grid, + Switch } from '@chakra-ui/react'; import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant'; import { QuestionOutlineIcon } from '@chakra-ui/icons'; @@ -35,6 +36,7 @@ import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d'; import { useQuery } from '@tanstack/react-query'; import type { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import type { EditFieldModeType, EditFieldType } from '../modules/FieldEditModal'; +import { feConfigs } from '@/web/common/system/staticData'; const FieldEditModal = dynamic(() => import('../modules/FieldEditModal')); const SelectAppModal = dynamic(() => import('../../SelectAppModal')); @@ -163,7 +165,10 @@ const RenderInput = ({ editFiledType?: EditFieldModeType; }) => { const sortInputs = useMemo( - () => flowInputList.sort((a, b) => (a.key === FlowNodeInputTypeEnum.switch ? -1 : 1)), + () => + flowInputList + .filter((item) => !item.plusField || feConfigs.isPlus) + .sort((a, b) => (a.key === FlowNodeInputTypeEnum.switch ? -1 : 1)), [flowInputList] ); return ( @@ -187,6 +192,9 @@ const RenderInput = ({ {item.type === FlowNodeInputTypeEnum.input && ( )} + {item.type === FlowNodeInputTypeEnum.switch && ( + + )} {item.type === FlowNodeInputTypeEnum.textarea && ( )} @@ -277,6 +285,26 @@ var TextInputRender = React.memo(function TextInputRender({ item, moduleId }: Re ); }); +var SwitchRender = React.memo(function SwitchRender({ item, moduleId }: RenderProps) { + return ( + { + onChangeNode({ + moduleId, + type: 'updateInput', + key: item.key, + value: { + ...item, + value: e.target.checked + } + }); + }} + /> + ); +}); + var TextareaRender = React.memo(function TextareaRender({ item, moduleId }: RenderProps) { return (