diff --git a/.gitignore b/.gitignore index 99739e73c..5be731c50 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ docSite/.vercel .idea/ files/helm/fastgpt/fastgpt-0.1.0.tgz files/helm/fastgpt/charts/*.tgz + +tmp/ diff --git a/docSite/assets/imgs/47-sealos1.png b/docSite/assets/imgs/47-sealos1.png new file mode 100644 index 000000000..aa681715a Binary files /dev/null and b/docSite/assets/imgs/47-sealos1.png differ diff --git a/docSite/assets/imgs/47-sealos2.png b/docSite/assets/imgs/47-sealos2.png new file mode 100644 index 000000000..e1b2235c9 Binary files /dev/null and b/docSite/assets/imgs/47-sealos2.png differ diff --git a/docSite/assets/imgs/47-sealos3.png b/docSite/assets/imgs/47-sealos3.png new file mode 100644 index 000000000..158dd6d01 Binary files /dev/null and b/docSite/assets/imgs/47-sealos3.png differ diff --git a/docSite/assets/imgs/47-sealos4.webp b/docSite/assets/imgs/47-sealos4.webp new file mode 100644 index 000000000..36f63b3d8 Binary files /dev/null and b/docSite/assets/imgs/47-sealos4.webp differ diff --git a/docSite/assets/imgs/47-sealos5.png b/docSite/assets/imgs/47-sealos5.png new file mode 100644 index 000000000..3e74d043e Binary files /dev/null and b/docSite/assets/imgs/47-sealos5.png differ diff --git a/docSite/assets/imgs/aichat.png b/docSite/assets/imgs/aichat.png index 54fa2ddb0..868169718 100644 Binary files a/docSite/assets/imgs/aichat.png and b/docSite/assets/imgs/aichat.png differ diff --git a/docSite/assets/imgs/aichat0.png b/docSite/assets/imgs/aichat0.png new file mode 100644 index 000000000..f9666c2ff Binary files /dev/null and b/docSite/assets/imgs/aichat0.png differ diff --git a/docSite/assets/imgs/aichat01.png b/docSite/assets/imgs/aichat01.png new file mode 100644 index 000000000..2ef5cea80 Binary files /dev/null and b/docSite/assets/imgs/aichat01.png differ diff --git a/docSite/assets/imgs/aichat02.png b/docSite/assets/imgs/aichat02.png new file mode 100644 index 000000000..59debfea8 Binary files /dev/null and b/docSite/assets/imgs/aichat02.png differ diff --git a/docSite/assets/imgs/aichat2.png b/docSite/assets/imgs/aichat2.png new file mode 100644 index 000000000..0eab07caa Binary files /dev/null and b/docSite/assets/imgs/aichat2.png differ diff --git a/docSite/assets/imgs/aichat3.webp b/docSite/assets/imgs/aichat3.webp new file mode 100644 index 000000000..b4dcc0f0f Binary files /dev/null and b/docSite/assets/imgs/aichat3.webp differ diff --git a/docSite/assets/imgs/coreferenceResolution2.jpg b/docSite/assets/imgs/coreferenceResolution2.jpg deleted file mode 100644 index b0a4aed9a..000000000 Binary files a/docSite/assets/imgs/coreferenceResolution2.jpg and /dev/null differ diff --git a/docSite/assets/imgs/coreferenceResolution2.webp b/docSite/assets/imgs/coreferenceResolution2.webp new file mode 100644 index 000000000..29e4680f7 Binary files /dev/null and b/docSite/assets/imgs/coreferenceResolution2.webp differ diff --git a/docSite/assets/imgs/coreferenceResolution3.jpg b/docSite/assets/imgs/coreferenceResolution3.jpg deleted file mode 100644 index 8fbe18ff7..000000000 Binary files a/docSite/assets/imgs/coreferenceResolution3.jpg and /dev/null differ diff --git a/docSite/assets/imgs/coreferenceResolution3.webp b/docSite/assets/imgs/coreferenceResolution3.webp new file mode 100644 index 000000000..d2708ebae Binary files /dev/null and b/docSite/assets/imgs/coreferenceResolution3.webp differ diff --git a/docSite/assets/imgs/datasetEngine3.jpg b/docSite/assets/imgs/datasetEngine3.jpg deleted file mode 100644 index 2f74e0c78..000000000 Binary files a/docSite/assets/imgs/datasetEngine3.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetEngine3.webp b/docSite/assets/imgs/datasetEngine3.webp new file mode 100644 index 000000000..88375faeb Binary files /dev/null and b/docSite/assets/imgs/datasetEngine3.webp differ diff --git a/docSite/assets/imgs/datasetEngine4.jpg b/docSite/assets/imgs/datasetEngine4.jpg deleted file mode 100644 index e62ce5b37..000000000 Binary files a/docSite/assets/imgs/datasetEngine4.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetEngine4.webp b/docSite/assets/imgs/datasetEngine4.webp new file mode 100644 index 000000000..63495b898 Binary files /dev/null and b/docSite/assets/imgs/datasetEngine4.webp differ diff --git a/docSite/assets/imgs/datasetEngine5.jpg b/docSite/assets/imgs/datasetEngine5.jpg deleted file mode 100644 index 2198c96d1..000000000 Binary files a/docSite/assets/imgs/datasetEngine5.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetEngine5.webp b/docSite/assets/imgs/datasetEngine5.webp new file mode 100644 index 000000000..496c8dab3 Binary files /dev/null and b/docSite/assets/imgs/datasetEngine5.webp differ diff --git a/docSite/assets/imgs/datasetEngine6.jpg b/docSite/assets/imgs/datasetEngine6.jpg deleted file mode 100644 index df91eaf9f..000000000 Binary files a/docSite/assets/imgs/datasetEngine6.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetEngine6.webp b/docSite/assets/imgs/datasetEngine6.webp new file mode 100644 index 000000000..31a171e15 Binary files /dev/null and b/docSite/assets/imgs/datasetEngine6.webp differ diff --git a/docSite/assets/imgs/datasetEngine7.jpg b/docSite/assets/imgs/datasetEngine7.jpg deleted file mode 100644 index 777efd94d..000000000 Binary files a/docSite/assets/imgs/datasetEngine7.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetEngine7.webp b/docSite/assets/imgs/datasetEngine7.webp new file mode 100644 index 000000000..79225915f Binary files /dev/null and b/docSite/assets/imgs/datasetEngine7.webp differ diff --git a/docSite/assets/imgs/dataset_search_params1.png b/docSite/assets/imgs/dataset_search_params1.png index 159ddd9d9..7b9302957 100644 Binary files a/docSite/assets/imgs/dataset_search_params1.png and b/docSite/assets/imgs/dataset_search_params1.png differ diff --git a/docSite/assets/imgs/dataset_search_params2.png b/docSite/assets/imgs/dataset_search_params2.png index b67b67088..9f26ccb8e 100644 Binary files a/docSite/assets/imgs/dataset_search_params2.png and b/docSite/assets/imgs/dataset_search_params2.png differ diff --git a/docSite/assets/imgs/dataset_search_params3.png b/docSite/assets/imgs/dataset_search_params3.png index 69ec93864..d25929dc1 100644 Binary files a/docSite/assets/imgs/dataset_search_params3.png and b/docSite/assets/imgs/dataset_search_params3.png differ diff --git a/docSite/assets/imgs/datasetprompt7.jpg b/docSite/assets/imgs/datasetprompt7.jpg deleted file mode 100644 index 268f7fd36..000000000 Binary files a/docSite/assets/imgs/datasetprompt7.jpg and /dev/null differ diff --git a/docSite/assets/imgs/datasetprompt7.webp b/docSite/assets/imgs/datasetprompt7.webp new file mode 100644 index 000000000..f24370148 Binary files /dev/null and b/docSite/assets/imgs/datasetprompt7.webp differ diff --git a/docSite/assets/imgs/demo-appointment1.jpg b/docSite/assets/imgs/demo-appointment1.jpg deleted file mode 100644 index 252e5c8ea..000000000 Binary files a/docSite/assets/imgs/demo-appointment1.jpg and /dev/null differ diff --git a/docSite/assets/imgs/demo-appointment1.webp b/docSite/assets/imgs/demo-appointment1.webp new file mode 100644 index 000000000..29fc83a64 Binary files /dev/null and b/docSite/assets/imgs/demo-appointment1.webp differ diff --git a/docSite/assets/imgs/demo-dalle2.png b/docSite/assets/imgs/demo-dalle2.png deleted file mode 100644 index 790f6df72..000000000 Binary files a/docSite/assets/imgs/demo-dalle2.png and /dev/null differ diff --git a/docSite/assets/imgs/demo-dalle2.webp b/docSite/assets/imgs/demo-dalle2.webp new file mode 100644 index 000000000..cb71a6a0a Binary files /dev/null and b/docSite/assets/imgs/demo-dalle2.webp differ diff --git a/docSite/assets/imgs/feishuwebhook1.png b/docSite/assets/imgs/feishuwebhook1.png new file mode 100644 index 000000000..e2813c6e5 Binary files /dev/null and b/docSite/assets/imgs/feishuwebhook1.png differ diff --git a/docSite/assets/imgs/feishuwebhook2.webp b/docSite/assets/imgs/feishuwebhook2.webp new file mode 100644 index 000000000..d45ac59f8 Binary files /dev/null and b/docSite/assets/imgs/feishuwebhook2.webp differ diff --git a/docSite/assets/imgs/feishuwebhook3.png b/docSite/assets/imgs/feishuwebhook3.png new file mode 100644 index 000000000..32d49a1dd Binary files /dev/null and b/docSite/assets/imgs/feishuwebhook3.png differ diff --git a/docSite/assets/imgs/feishuwebhook4.webp b/docSite/assets/imgs/feishuwebhook4.webp new file mode 100644 index 000000000..ad42fbb32 Binary files /dev/null and b/docSite/assets/imgs/feishuwebhook4.webp differ diff --git a/docSite/assets/imgs/feishuwebhook5.png b/docSite/assets/imgs/feishuwebhook5.png new file mode 100644 index 000000000..ede103023 Binary files /dev/null and b/docSite/assets/imgs/feishuwebhook5.png differ diff --git a/docSite/assets/imgs/flow-dataset1.png b/docSite/assets/imgs/flow-dataset1.png new file mode 100644 index 000000000..949adc545 Binary files /dev/null and b/docSite/assets/imgs/flow-dataset1.png differ diff --git a/docSite/assets/imgs/flow-tool1.png b/docSite/assets/imgs/flow-tool1.png new file mode 100644 index 000000000..fec4d4328 Binary files /dev/null and b/docSite/assets/imgs/flow-tool1.png differ diff --git a/docSite/assets/imgs/flow-tool2.png b/docSite/assets/imgs/flow-tool2.png new file mode 100644 index 000000000..576c9d35a Binary files /dev/null and b/docSite/assets/imgs/flow-tool2.png differ diff --git a/docSite/assets/imgs/flow-tool3.png b/docSite/assets/imgs/flow-tool3.png new file mode 100644 index 000000000..17c410a7b Binary files /dev/null and b/docSite/assets/imgs/flow-tool3.png differ diff --git a/docSite/assets/imgs/flow-tool4.png b/docSite/assets/imgs/flow-tool4.png new file mode 100644 index 000000000..ed52da7dd Binary files /dev/null and b/docSite/assets/imgs/flow-tool4.png differ diff --git a/docSite/assets/imgs/gapierTool10.png b/docSite/assets/imgs/gapierTool10.png deleted file mode 100644 index 4b3f97e06..000000000 Binary files a/docSite/assets/imgs/gapierTool10.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool10.webp b/docSite/assets/imgs/gapierTool10.webp new file mode 100644 index 000000000..b5824349a Binary files /dev/null and b/docSite/assets/imgs/gapierTool10.webp differ diff --git a/docSite/assets/imgs/gapierTool12.png b/docSite/assets/imgs/gapierTool12.png deleted file mode 100644 index a2be0bea1..000000000 Binary files a/docSite/assets/imgs/gapierTool12.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool12.webp b/docSite/assets/imgs/gapierTool12.webp new file mode 100644 index 000000000..40fd845e6 Binary files /dev/null and b/docSite/assets/imgs/gapierTool12.webp differ diff --git a/docSite/assets/imgs/gapierTool13.png b/docSite/assets/imgs/gapierTool13.png deleted file mode 100644 index 1109cfc5e..000000000 Binary files a/docSite/assets/imgs/gapierTool13.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool14.png b/docSite/assets/imgs/gapierTool14.png deleted file mode 100644 index ce8d27817..000000000 Binary files a/docSite/assets/imgs/gapierTool14.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool14.webp b/docSite/assets/imgs/gapierTool14.webp new file mode 100644 index 000000000..a921642fc Binary files /dev/null and b/docSite/assets/imgs/gapierTool14.webp differ diff --git a/docSite/assets/imgs/gapierTool15.png b/docSite/assets/imgs/gapierTool15.png deleted file mode 100644 index 4e9717643..000000000 Binary files a/docSite/assets/imgs/gapierTool15.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool15.webp b/docSite/assets/imgs/gapierTool15.webp new file mode 100644 index 000000000..48506a30d Binary files /dev/null and b/docSite/assets/imgs/gapierTool15.webp differ diff --git a/docSite/assets/imgs/gapierTool16.png b/docSite/assets/imgs/gapierTool16.png deleted file mode 100644 index 0ff1d38c0..000000000 Binary files a/docSite/assets/imgs/gapierTool16.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool16.webp b/docSite/assets/imgs/gapierTool16.webp new file mode 100644 index 000000000..4430b5436 Binary files /dev/null and b/docSite/assets/imgs/gapierTool16.webp differ diff --git a/docSite/assets/imgs/gapierTool17.png b/docSite/assets/imgs/gapierTool17.png deleted file mode 100644 index f57c988f2..000000000 Binary files a/docSite/assets/imgs/gapierTool17.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool17.webp b/docSite/assets/imgs/gapierTool17.webp new file mode 100644 index 000000000..be53447ed Binary files /dev/null and b/docSite/assets/imgs/gapierTool17.webp differ diff --git a/docSite/assets/imgs/gapierTool9.png b/docSite/assets/imgs/gapierTool9.png deleted file mode 100644 index cae83ba62..000000000 Binary files a/docSite/assets/imgs/gapierTool9.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierTool9.webp b/docSite/assets/imgs/gapierTool9.webp new file mode 100644 index 000000000..87313c0eb Binary files /dev/null and b/docSite/assets/imgs/gapierTool9.webp differ diff --git a/docSite/assets/imgs/gapierToolResult1.png b/docSite/assets/imgs/gapierToolResult1.png deleted file mode 100644 index a898f5832..000000000 Binary files a/docSite/assets/imgs/gapierToolResult1.png and /dev/null differ diff --git a/docSite/assets/imgs/gapierToolResult1.webp b/docSite/assets/imgs/gapierToolResult1.webp new file mode 100644 index 000000000..bee1c33da Binary files /dev/null and b/docSite/assets/imgs/gapierToolResult1.webp differ diff --git a/docSite/assets/imgs/getfile_id.png b/docSite/assets/imgs/getfile_id.png deleted file mode 100644 index 0ccaa044f..000000000 Binary files a/docSite/assets/imgs/getfile_id.png and /dev/null differ diff --git a/docSite/assets/imgs/getfile_id.webp b/docSite/assets/imgs/getfile_id.webp new file mode 100644 index 000000000..847eec7f8 Binary files /dev/null and b/docSite/assets/imgs/getfile_id.webp differ diff --git a/docSite/assets/imgs/google_search_1.jpg b/docSite/assets/imgs/google_search_1.jpg deleted file mode 100644 index af89e288e..000000000 Binary files a/docSite/assets/imgs/google_search_1.jpg and /dev/null differ diff --git a/docSite/assets/imgs/google_search_1.png b/docSite/assets/imgs/google_search_1.png deleted file mode 100644 index 059cab5f0..000000000 Binary files a/docSite/assets/imgs/google_search_1.png and /dev/null differ diff --git a/docSite/assets/imgs/google_search_1.webp b/docSite/assets/imgs/google_search_1.webp new file mode 100644 index 000000000..476a2e73d Binary files /dev/null and b/docSite/assets/imgs/google_search_1.webp differ diff --git a/docSite/assets/imgs/google_search_3.png b/docSite/assets/imgs/google_search_3.png new file mode 100644 index 000000000..a13f7635e Binary files /dev/null and b/docSite/assets/imgs/google_search_3.png differ diff --git a/docSite/assets/imgs/google_search_4.png b/docSite/assets/imgs/google_search_4.png new file mode 100644 index 000000000..e2d43d5b2 Binary files /dev/null and b/docSite/assets/imgs/google_search_4.png differ diff --git a/docSite/assets/imgs/http1.jpg b/docSite/assets/imgs/http1.jpg index 6cd2d128d..2832a7299 100644 Binary files a/docSite/assets/imgs/http1.jpg and b/docSite/assets/imgs/http1.jpg differ diff --git a/docSite/assets/imgs/intro1.png b/docSite/assets/imgs/intro1.png deleted file mode 100644 index 690b6042e..000000000 Binary files a/docSite/assets/imgs/intro1.png and /dev/null differ diff --git a/docSite/assets/imgs/intro1.webp b/docSite/assets/imgs/intro1.webp new file mode 100644 index 000000000..d76038c9a Binary files /dev/null and b/docSite/assets/imgs/intro1.webp differ diff --git a/docSite/assets/imgs/oneapi-step1.jpg b/docSite/assets/imgs/oneapi-step1.jpg deleted file mode 100644 index cb4e10113..000000000 Binary files a/docSite/assets/imgs/oneapi-step1.jpg and /dev/null differ diff --git a/docSite/assets/imgs/oneapi-step1.webp b/docSite/assets/imgs/oneapi-step1.webp new file mode 100644 index 000000000..f49f3e538 Binary files /dev/null and b/docSite/assets/imgs/oneapi-step1.webp differ diff --git a/docSite/assets/imgs/question_guide.png b/docSite/assets/imgs/question_guide.png deleted file mode 100644 index 30c518c6f..000000000 Binary files a/docSite/assets/imgs/question_guide.png and /dev/null differ diff --git a/docSite/assets/imgs/question_guide.webp b/docSite/assets/imgs/question_guide.webp new file mode 100644 index 000000000..62d7fe0a4 Binary files /dev/null and b/docSite/assets/imgs/question_guide.webp differ diff --git a/docSite/assets/imgs/sealos3.jpg b/docSite/assets/imgs/sealos3.jpg deleted file mode 100644 index bf1475d56..000000000 Binary files a/docSite/assets/imgs/sealos3.jpg and /dev/null differ diff --git a/docSite/assets/imgs/sealos3.webp b/docSite/assets/imgs/sealos3.webp new file mode 100644 index 000000000..2d06c40b3 Binary files /dev/null and b/docSite/assets/imgs/sealos3.webp differ diff --git a/docSite/assets/imgs/tts_setting2.png b/docSite/assets/imgs/tts_setting2.png deleted file mode 100644 index bb06c2304..000000000 Binary files a/docSite/assets/imgs/tts_setting2.png and /dev/null differ diff --git a/docSite/assets/imgs/tts_setting2.webp b/docSite/assets/imgs/tts_setting2.webp new file mode 100644 index 000000000..86d15ec62 Binary files /dev/null and b/docSite/assets/imgs/tts_setting2.webp differ diff --git a/docSite/assets/imgs/variable3.png b/docSite/assets/imgs/variable3.png index d37eb4586..6146dde34 100644 Binary files a/docSite/assets/imgs/variable3.png and b/docSite/assets/imgs/variable3.png differ diff --git a/docSite/assets/imgs/variable4.png b/docSite/assets/imgs/variable4.png deleted file mode 100644 index dfeac60ff..000000000 Binary files a/docSite/assets/imgs/variable4.png and /dev/null differ diff --git a/docSite/assets/imgs/variable4.webp b/docSite/assets/imgs/variable4.webp new file mode 100644 index 000000000..f0eb92822 Binary files /dev/null and b/docSite/assets/imgs/variable4.webp differ diff --git a/docSite/assets/imgs/variable5.png b/docSite/assets/imgs/variable5.png deleted file mode 100644 index 2d47bae45..000000000 Binary files a/docSite/assets/imgs/variable5.png and /dev/null differ diff --git a/docSite/assets/imgs/variable5.webp b/docSite/assets/imgs/variable5.webp new file mode 100644 index 000000000..bd907e07e Binary files /dev/null and b/docSite/assets/imgs/variable5.webp differ diff --git a/docSite/assets/imgs/webSync10.jpg b/docSite/assets/imgs/webSync10.jpg deleted file mode 100644 index 4407b68cb..000000000 Binary files a/docSite/assets/imgs/webSync10.jpg and /dev/null differ diff --git a/docSite/assets/imgs/webSync10.webp b/docSite/assets/imgs/webSync10.webp new file mode 100644 index 000000000..b7dd21869 Binary files /dev/null and b/docSite/assets/imgs/webSync10.webp differ diff --git a/docSite/assets/imgs/webSync6.jpg b/docSite/assets/imgs/webSync6.jpg deleted file mode 100644 index 83dc70d13..000000000 Binary files a/docSite/assets/imgs/webSync6.jpg and /dev/null differ diff --git a/docSite/assets/imgs/webSync6.webp b/docSite/assets/imgs/webSync6.webp new file mode 100644 index 000000000..b838379b5 Binary files /dev/null and b/docSite/assets/imgs/webSync6.webp differ diff --git a/docSite/assets/imgs/webSync7.jpg b/docSite/assets/imgs/webSync7.jpg deleted file mode 100644 index fc4f385f5..000000000 Binary files a/docSite/assets/imgs/webSync7.jpg and /dev/null differ diff --git a/docSite/assets/imgs/webSync7.webp b/docSite/assets/imgs/webSync7.webp new file mode 100644 index 000000000..7f22abe9e Binary files /dev/null and b/docSite/assets/imgs/webSync7.webp differ diff --git a/docSite/assets/imgs/webSync8.jpg b/docSite/assets/imgs/webSync8.jpg deleted file mode 100644 index 2fc5bb6e9..000000000 Binary files a/docSite/assets/imgs/webSync8.jpg and /dev/null differ diff --git a/docSite/assets/imgs/webSync8.webp b/docSite/assets/imgs/webSync8.webp new file mode 100644 index 000000000..16ce8f3a6 Binary files /dev/null and b/docSite/assets/imgs/webSync8.webp differ diff --git a/docSite/assets/imgs/webSync9.jpg b/docSite/assets/imgs/webSync9.jpg deleted file mode 100644 index 509828c53..000000000 Binary files a/docSite/assets/imgs/webSync9.jpg and /dev/null differ diff --git a/docSite/assets/imgs/webSync9.webp b/docSite/assets/imgs/webSync9.webp new file mode 100644 index 000000000..6fc349d3b Binary files /dev/null and b/docSite/assets/imgs/webSync9.webp differ diff --git a/docSite/assets/imgs/workflow_process.png b/docSite/assets/imgs/workflow_process.png new file mode 100644 index 000000000..5c7559f36 Binary files /dev/null and b/docSite/assets/imgs/workflow_process.png differ diff --git a/docSite/content/docs/commercial/intro.md b/docSite/content/docs/commercial/intro.md index c1da9dd25..6b7aa1ff9 100644 --- a/docSite/content/docs/commercial/intro.md +++ b/docSite/content/docs/commercial/intro.md @@ -26,10 +26,11 @@ FastGPT 商业版是基于 FastGPT 开源版的增强版本,增加了一些独 | 内容审核 | ❌ | ✅ | ✅ | | web站点同步 | ❌ | ✅ | ✅ | | 管理后台 | ❌ | ✅ | ✅ | -| 完整商业授权 | ❌ | ✅ | ✅ | +| 增强训练模式 | ❌ | ✅ | ✅ | | 图片知识库 | ❌ | 设计中 | 设计中 | | 自动规划召回 | ❌ | 设计中 | 设计中 | | 对话日志运营分析 | ❌ | 设计中 | 设计中 | +| 完整商业授权 | ❌ | ✅ | ✅ | {{< /table >}} ## 商业版软件价格 diff --git a/docSite/content/docs/course/ai_settings.md b/docSite/content/docs/course/ai_settings.md index ae3d8c1d7..fbdd7a08c 100644 --- a/docSite/content/docs/course/ai_settings.md +++ b/docSite/content/docs/course/ai_settings.md @@ -1,6 +1,6 @@ --- -title: "AI 高级配置说明" -description: "FastGPT AI 高级配置说明" +title: "AI 相关参数配置说明" +description: "FastGPT AI 相关参数配置说明" icon: "sign_language" draft: false toc: true @@ -9,17 +9,33 @@ weight: 102 在 FastGPT 的 AI 对话模块中,有一个 AI 高级配置,里面包含了 AI 模型的参数配置,本文详细介绍这些配置的含义。 -## 返回AI内容 +| | | | +| --- | --- | --- | +| ![](/imgs/aichat0.png) | ![](/imgs/aichat02.png) | ![](/imgs/aichat2.png) | + +## 返回AI内容(高级编排特有) 这是一个开关,打开的时候,当 AI 对话模块运行时,会将其输出的内容返回到浏览器(API响应);如果关闭,AI 输出的内容不会返回到浏览器,但是生成的内容仍可以通过【AI回复】进行输出。你可以将【AI回复】连接到其他模块中。 -## 温度 +### 最大上下文 -可选范围0-10,越大代表生成的内容越自由扩散,越小代表约严谨。调节能力有限,知识库问答场景通常设置为0。 +代表模型最多容纳的文字数量。 -## 回复上限 +### 函数调用 -控制 AI 回复的最大 Tokens,较小的值可以一定程度上减少 AI 的废话,但也可能导致 AI 回复不完整。 +支持函数调用的模型,在使用工具时更加准确。 + +### 温度 + +越低回答越严谨,少废话(实测下来,感觉差别不大) + +### 回复上限 + +最大回复 token 数量。注意,是回复的Tokens!不是上下文 tokens。 + +### 系统提示词 + +被放置在上下文数组的最前面,role 为 system,用于引导模型。 ## 引用模板 & 引用提示词 @@ -123,7 +139,7 @@ Tips: 建议根据不同的场景,每种知识库仅选择1类数据类型, | 非严格模板效果 | 选择严格模板 | 严格模板效果 | | --- | --- | --- | -| ![](/imgs/datasetprompt7.jpg) | ![](/imgs/datasetprompt8.jpg) |![](/imgs/datasetprompt9.jpg) | +| ![](/imgs/datasetprompt7.webp) | ![](/imgs/datasetprompt8.jpg) |![](/imgs/datasetprompt9.jpg) | #### 提示词设计思路 diff --git a/docSite/content/docs/course/data_search.md b/docSite/content/docs/course/data_search.md deleted file mode 100644 index baa74cd13..000000000 --- a/docSite/content/docs/course/data_search.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: '知识库搜索介绍' -description: '本节会详细介绍 FastGPT 知识库结构设计,理解其 QA 的存储格式和多向量映射,以便更好的构建知识库。同时会介绍每个搜索参数的功能。这篇介绍主要以使用为主,详细原理不多介绍。' -icon: 'language' -draft: false -toc: true -weight: 106 ---- - -## 理解向量 - -FastGPT 采用了 RAG 中的 Embedding 方案构建知识库,要使用好 FastGPT 需要简单的理解`Embedding`向量是如何工作的及其特点。 - -人类的文字、图片、视频等媒介是无法直接被计算机理解的,要想让计算机理解两段文字是否有相似性、相关性,通常需要将它们转成计算机可以理解的语言,向量是其中的一种方式。 - -向量可以简单理解为一个数字数组,两个向量之间可以通过数学公式得出一个`距离`,距离越小代表两个向量的相似度越大。从而映射到文字、图片、视频等媒介上,可以用来判断两个媒介之间的相似度。向量搜索便是利用了这个原理。 - -而由于文字是有多种类型,并且拥有成千上万种组合方式,因此在转成向量进行相似度匹配时,很难保障其精确性。在向量方案构建的知识库中,通常使用`topk`召回的方式,也就是查找前`k`个最相似的内容,丢给大模型去做更进一步的`语义判断`、`逻辑推理`和`归纳总结`,从而实现知识库问答。因此,在知识库问答中,向量搜索的环节是最为重要的。 - -影响向量搜索精度的因素非常多,主要包括:向量模型的质量、数据的质量(长度,完整性,多样性)、检索器的精度(速度与精度之间的取舍)。与数据质量对应的就是检索词的质量。 - -检索器的精度比较容易解决,向量模型的训练略复杂,因此数据和检索词质量优化成了一个重要的环节。 - - -### 提高向量搜索精度的方法 - -1. 更好分词分段:当一段话的结构和语义是完整的,并且是单一的,精度也会提高。因此,许多系统都会优化分词器,尽可能的保障每组数据的完整性。 -2. 精简`index`的内容,减少向量内容的长度:当`index`的内容更少,更准确时,检索精度自然会提高。但与此同时,会牺牲一定的检索范围,适合答案较为严格的场景。 -3. 丰富`index`的数量,可以为同一个`chunk`内容增加多组`index`。 -4. 优化检索词:在实际使用过程中,用户的问题通常是模糊的或是缺失的,并不一定是完整清晰的问题。因此优化用户的问题(检索词)很大程度上也可以提高精度。 -5. 微调向量模型:由于市面上直接使用的向量模型都是通用型模型,在特定领域的检索精度并不高,因此微调向量模型可以很大程度上提高专业领域的检索效果。 - -## FastGPT 构建知识库方案 - -### 数据存储结构 - -在 FastGPT 中,整个知识库由库、集合和数据 3 部分组成。集合可以简单理解为一个`文件`。一个`库`中可以包含多个`集合`,一个`集合`中可以包含多组`数据`。最小的搜索单位是`库`,也就是说,知识库搜索时,是对整个`库`进行搜索,而集合仅是为了对数据进行分类管理,与搜索效果无关。(起码目前还是) - -![](/imgs/dataset_tree.png) - -### 向量存储结构 - -FastGPT 采用了`PostgresSQL`的`PG Vector`插件作为向量检索器,索引为`HNSW`。且`PostgresSQL`仅用于向量检索(该引擎可以替换成其它数据库),`MongoDB`用于其他数据的存取。 - -在`MongoDB`的`dataset.datas`表中,会存储向量原数据的信息,同时有一个`indexes`字段,会记录其对应的向量ID,这是一个数组,也就是说,一组向量可以对应多组数据。 - -在`PostgresSQL`的表中,设置一个`vector`字段用于存储向量。在检索时,会先召回向量,再根据向量的ID,去`MongoDB`中寻找原数据内容,如果对应了同一组原数据,则进行合并,向量得分取最高得分。 - -![](/imgs/datasetSetting1.png) - -### 多向量的目的和使用方式 - -在一组向量中,内容的长度和语义的丰富度通常是矛盾的,无法兼得。因此,FastGPT 采用了多向量映射的方式,将一组数据映射到多组向量中,从而保障数据的完整性和语义的丰富度。 - -你可以为一组较长的文本,添加多组向量,从而在检索时,只要其中一组向量被检索到,该数据也将被召回。 - -### 检索方案 - -1. 通过`问题优化`实现指代消除和问题扩展,从而增加连续对话的检索能力以及语义丰富度。 -2. 通过`Concat query`来增加`Rerank`连续对话的时,排序的准确性。 -3. 通过`RRF`合并方式,综合多个渠道的检索效果。 -4. 通过`Rerank`来二次排序,提高精度。 - -![](/imgs/dataset_search_process.png) - - -## 搜索参数 -| | | | -| --- |---| --- | -|![](/imgs/dataset_search_params1.png)| ![](/imgs/dataset_search_params2.png) | ![](/imgs/dataset_search_params3.png) | - -### 搜索模式 - -#### 语义检索 - -语义检索是通过向量距离,计算用户问题与知识库内容的距离,从而得出“相似度”,当然这并不是语文上的相似度,而是数学上的。 - -优点: -- 相近语义理解 -- 跨多语言理解(例如输入中文问题匹配英文知识点) -- 多模态理解(文本,图片,音视频等) - -缺点: -- 依赖模型训练效果 -- 精度不稳定 -- 受关键词和句子完整度影响 - -#### 全文检索 - -采用传统的全文检索方式。适合查找关键的主谓语等。 - -#### 混合检索 - -同时使用向量检索和全文检索,并通过 RRF 公式进行两个搜索结果合并,一般情况下搜索结果会更加丰富准确。 - -由于混合检索后的查找范围很大,并且无法直接进行相似度过滤,通常需要进行利用重排模型进行一次结果重新排序,并利用重排的得分进行过滤。 - -#### 结果重排 - -利用`ReRank`模型对搜索结果进行重排,绝大多数情况下,可以有效提高搜索结果的准确率。不过,重排模型与问题的完整度(主谓语齐全)有一些关系,通常会先走问题优化后再进行搜索-重排。重排后可以得到一个`0-1`的得分,代表着搜索内容与问题的相关度,该分数通常比向量的得分更加精确,可以根据得分进行过滤。 - -FastGPT 会使用 `RRF` 对重排结果、向量搜索结果、全文检索结果进行合并,得到最终的搜索结果。 - -### 搜索过滤 - -#### 引用上限 - -每次搜索最多引用`n`个`tokens`的内容。 - -之所以不采用`top k`,是发现在混合知识库(问答库、文档库)时,不同`chunk`的长度差距很大,会导致`top k`的结果不稳定,因此采用了`tokens`的方式进行引用上限的控制。 - -#### 最低相关度 - -一个`0-1`的数值,会过滤掉一些低相关度的搜索结果。 - -该值仅在`语义检索`或使用`结果重排`时生效。 - -### 问题优化 - -#### 背景 - -在 RAG 中,我们需要根据输入的问题去数据库里执行 embedding 搜索,查找相关的内容,从而查找到相似的内容(简称知识库搜索)。 - -在搜索的过程中,尤其是连续对话的搜索,我们通常会发现后续的问题难以搜索到合适的内容,其中一个原因是知识库搜索只会使用“当前”的问题去执行。看下面的例子: - -![](/imgs/coreferenceResolution2.jpg) - -用户在提问“第二点是什么”的时候,只会去知识库里查找“第二点是什么”,压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题优化】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下: - -![](/imgs/coreferenceResolution3.jpg) - -#### 实现方式 - -在进行`数据检索`前,会先让模型进行`指代消除`与`问题扩展`,一方面可以可以解决指代对象不明确问题,同时可以扩展问题的语义丰富度。 diff --git a/docSite/content/docs/course/datasetEngine.md b/docSite/content/docs/course/datasetEngine.md index 9b867041e..2d2013eb9 100644 --- a/docSite/content/docs/course/datasetEngine.md +++ b/docSite/content/docs/course/datasetEngine.md @@ -51,7 +51,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | 库 | 集合 | 数据 | | --- | --- | --- | -| ![](/imgs/datasetEngine1.jpg) | ![](/imgs/datasetEngine2.jpg) | ![](/imgs/datasetEngine3.jpg) | +| ![](/imgs/datasetEngine1.jpg) | ![](/imgs/datasetEngine2.jpg) | ![](/imgs/datasetEngine3.webp) | ### 导入数据方案1 - 直接分段导入 @@ -59,7 +59,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | 交互 | 结果 | | --- | --- | -| ![](/imgs/datasetEngine4.jpg) | ![](/imgs/datasetEngine5.jpg) | +| ![](/imgs/datasetEngine4.webp) | ![](/imgs/datasetEngine5.webp) | ### 导入数据方案2 - QA导入 @@ -68,7 +68,7 @@ FastGPT 采用了 `PostgresSQL` 的 `PG Vector` 插件作为向量检索器, | 交互 | 结果 | | --- | --- | -| ![](/imgs/datasetEngine6.jpg) | ![](/imgs/datasetEngine7.jpg) | +| ![](/imgs/datasetEngine6.webp) | ![](/imgs/datasetEngine7.webp) | ### 导入数据方案3 - 手动录入 diff --git a/docSite/content/docs/course/kb.md b/docSite/content/docs/course/kb.md index dbbb16c21..081de09ef 100644 --- a/docSite/content/docs/course/kb.md +++ b/docSite/content/docs/course/kb.md @@ -4,7 +4,7 @@ description: " 利用 FastGPT 打造高质量 AI 知识库" icon: "school" draft: false toc: true -weight: 106 +weight: 300 --- ## 前言 diff --git a/docSite/content/docs/course/websync.md b/docSite/content/docs/course/websync.md deleted file mode 100644 index 3ecc033b3..000000000 --- a/docSite/content/docs/course/websync.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: 'Web 站点同步' -description: 'FastGPT Web 站点同步功能介绍和使用方式' -icon: 'language' -draft: false -toc: true -weight: 105 ---- - -![](/imgs/webSync1.jpg) - -该功能目前仅向商业版用户开放。 - -## 什么是 Web 站点同步 - -Web 站点同步利用爬虫的技术,可以通过一个入口网站,自动捕获`同域名`下的所有网站,目前最多支持`200`个子页面。出于合规与安全角度,FastGPT 仅支持`静态站点`的爬取,主要用于各个文档站点快速构建知识库。 - -Tips: 国内的媒体站点基本不可用,公众号、csdn、知乎等。可以通过终端发送`curl`请求检测是否为静态站点,例如: - -```bash -curl https://doc.fastgpt.in/docs/intro/ -``` - -## 如何使用 - -### 1. 新建知识库,选择 Web 站点同步 - -![](/imgs/webSync2.png) - -![](/imgs/webSync3.png) - -### 2. 点击配置站点信息 - -![](/imgs/webSync4.png) - -### 3. 填写网址和选择器 - -![](/imgs/webSync5.jpg) - -好了, 现在点击开始同步,静等系统自动抓取网站信息即可。 - - -## 创建应用,绑定知识库 - -![](/imgs/webSync6.jpg) - -## 选择器如何使用 - -选择器是 HTML CSS JS 的产物,你可以通过选择器来定位到你需要抓取的具体内容,而不是整个站点。使用方式为: - -### 首先打开浏览器调试面板(通常是 F12,或者【右键 - 检查】) - -![](/imgs/webSync7.jpg) - -![](/imgs/webSync8.jpg) - -### 输入对应元素的选择器 - -[菜鸟教程 css 选择器](https://www.runoob.com/cssref/css-selectors.html),具体选择器的使用方式可以参考菜鸟教程。 - -上图中,我们选中了一个区域,对应的是`div`标签,它有 `data-prismjs-copy`, `data-prismjs-copy-success`, `data-prismjs-copy-error` 三个属性,这里我们用到一个就够。所以选择器是: -**`div[data-prismjs-copy]`** - -除了属性选择器,常见的还有类和ID选择器。例如: - -![](/imgs/webSync9.jpg) - -上图 class 里的是类名(可能包含多个类名,都是空格隔开的,选择一个即可),选择器可以为:**`.docs-content`** - -### 多选择器使用 - -在开头的演示中,我们对 FastGPT 文档是使用了多选择器的方式来选择,通过逗号隔开了两个选择器。 - -![](/imgs/webSync10.jpg) - -我们希望选中上图两个标签中的内容,此时就需要两组选择器。一组是:`.docs-content .mb-0.d-flex`,含义是 `docs-content` 类下同时包含 `mb-0`和`d-flex` 两个类的子元素; - -另一组是`.docs-content div[data-prismjs-copy]`,含义是`docs-content` 类下包含`data-prismjs-copy`属性的`div`元素。 - -把两组选择器用逗号隔开即可:`.docs-content .mb-0.d-flex, .docs-content div[data-prismjs-copy]` \ No newline at end of file diff --git a/docSite/content/docs/development/configuration.md b/docSite/content/docs/development/configuration.md index 10db56a94..b397476e4 100644 --- a/docSite/content/docs/development/configuration.md +++ b/docSite/content/docs/development/configuration.md @@ -26,7 +26,7 @@ llm模型全部合并 }, "llmModels": [ { - "model": "gpt-3.5-turbo", // 模型名 + "model": "gpt-3.5-turbo", // 模型名(对应OneAPI中渠道的模型名) "name": "gpt-3.5-turbo", // 别名 "avatar": "/imgs/model/openai.svg", // 模型的logo "maxContext": 16000, // 最大上下文 @@ -97,14 +97,16 @@ llm模型全部合并 ], "vectorModels": [ { - "model": "text-embedding-ada-002", - "name": "Embedding-2", - "avatar": "/imgs/model/openai.svg", - "charsPointsPrice": 0, - "defaultToken": 700, - "maxToken": 3000, - "weight": 100, - "defaultConfig":{} // 默认配置。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) + "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) + "name": "Embedding-2", // 模型展示名 + "avatar": "/imgs/model/openai.svg", // logo + "charsPointsPrice": 0, // n积分/1k token + "defaultToken": 700, // 默认文本分割时候的 token + "maxToken": 3000, // 最大 token + "weight": 100, // 优先训练权重 + "defaultConfig":{}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) + "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) + "queryConfig": {} // 参训时的额外参数 } ], "reRankModels": [], diff --git a/docSite/content/docs/development/docker.md b/docSite/content/docs/development/docker.md index 99973f842..b5ea91794 100644 --- a/docSite/content/docs/development/docker.md +++ b/docSite/content/docs/development/docker.md @@ -96,11 +96,13 @@ curl -O https://raw.githubusercontent.com/labring/FastGPT/main/projects/app/data ## 三、启动容器 -在 docker-compose.yml 同级目录下执行 +在 docker-compose.yml 同级目录下执行。请确保`docker-compose`版本最好在2.17以上,否则可能无法执行自动化命令。 ```bash # 启动容器 docker-compose up -d +# 等待10s,OneAPI第一次总是要重启几次才能连上Mysql +sleep 10 # 重启一次oneapi(由于OneAPI的默认Key有点问题,不重启的话会提示找不到渠道,临时手动重启一次解决,等待作者修复) docker restart oneapi ``` @@ -109,7 +111,7 @@ docker restart oneapi 可以通过`ip:3001`访问OneAPI,默认账号为`root`密码为`123456`。 -在OneApi中添加合适的AI模型渠道。 +在OneApi中添加合适的AI模型渠道。[点击查看相关教程](/docs/development/one-api/) ## 五、访问 FastGPT diff --git a/docSite/content/docs/development/faq.md b/docSite/content/docs/development/faq.md index 5d73a23a4..640cb5dc6 100644 --- a/docSite/content/docs/development/faq.md +++ b/docSite/content/docs/development/faq.md @@ -12,9 +12,8 @@ images: [] 遇到问题先按下面方式排查。 1. `docker ps -a` 查看所有容器运行状态,检查是否全部 running,如有异常,尝试`docker logs 容器名`查看对应日志。 -2. 不懂 docker 不要瞎改端口,只需要改`OPENAI_BASE_URL`和`CHAT_API_KEY`即可。 -3. 容器都运行正常的,`docker logs 容器名` 查看报错日志 -4. 无法解决时,可以找找[Issue](https://github.com/labring/FastGPT/issues),或新提 Issue,私有部署错误,务必提供详细的日志,否则很难排查。 +2. 容器都运行正常的,`docker logs 容器名` 查看报错日志 +3. 无法解决时,可以找找[Issue](https://github.com/labring/FastGPT/issues),或新提 Issue,私有部署错误,务必提供详细的日志,否则很难排查。 ## 二、通用问题 @@ -29,7 +28,8 @@ images: [] ### 其他模型没法进行问题分类/内容提取 -需要给其他模型配置`toolChoice=false`,就会默认走提示词模式。目前内置提示词仅针对了商业模型API进行测试,国内外的商业模型基本都可用。 +需要给其他模型配置`toolChoice=false`,就会默认走提示词模式。目前内置提示词仅针对了商业模型API进行测试。 +问题分类基本可用,内容提取不太行。 ### 页面崩溃 @@ -48,7 +48,7 @@ images: [] 2. 如果是国内模型,可能是命中风控了。 3. 查看模型请求日志,检查出入参数是否异常。 -### 知识库索引没有进度 +### 知识库索引没有进度/索引很慢 先看日志报错信息。有以下几种情况: @@ -62,15 +62,27 @@ images: [] 或者是FastGPT请求不到 OneAPI(没放同一个网络) +### 修改了 vectorModels 但是没有生效 + +1. 重启容器,确保模型配置已经加载(可以在日志或者新建知识库时候看到新模型) +2. 记得刷新一次浏览器。 +3. 如果是已经创建的知识库,需要删除重建。向量模型是创建时候绑定的,不会动态更新。 + ## 三、常见的 OneAPI 错误 +带有 requestId 的都是 OneAPI 的报错。 + ### insufficient_user_quota user quota is not enough OneAPI 账号的余额不足,默认 root 用户只有 200 刀,可以手动修改。 ### xxx渠道找不到 -OneAPI 中没有配置该模型渠道。或者是修改了配置文件中一部分的模型,但没有全部修改。 +FastGPT 模型配置文件中的 model 必须与 OneAPI 渠道中的模型对应上,否则就会提示这个错误。可检查下面内容: + +1. OneAPI 中没有配置该模型渠道,或者被禁用了。 +2. 修改了 FastGPT 配置文件中一部分的模型,但没有全部修改,仍有模型是 OneAPI 没配置的。 +3. 使用旧的向量模型创建了知识库,后又更新了向量模型。这时候需要删除以前的知识库,重建。 如果OneAPI中,没有配置对应的模型,`config.json`中也不要配置,否则容易报错。 diff --git a/docSite/content/docs/development/intro.md b/docSite/content/docs/development/intro.md index f99d6abb3..8859d23c3 100644 --- a/docSite/content/docs/development/intro.md +++ b/docSite/content/docs/development/intro.md @@ -54,11 +54,11 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec 以下文件均在 `projects/app` 路径下。 -**环境变量** +**1. 环境变量** 复制`.env.template`文件,在同级目录下生成一个`.env.local` 文件,修改`.env.local` 里内容才是有效的变量。变量说明见 .env.template -**config 配置文件** +**2. config 配置文件** 复制 `data/config.json` 文件,生成一个 `data/config.local.json` 配置文件,具体配置参数说明,可参考 [config 配置说明](/docs/development/configuration) @@ -73,7 +73,7 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec ### 5. 运行 ```bash -# 给脚本代码执行权限 +# 给自动化脚本代码执行权限(非 linux 系统, 可以手动执行里面的 postinstall.sh 文件内容) chmod -R +x ./scripts/ # 代码根目录下执行,会安装根 package、projects 和 packages 内所有依赖 pnpm i diff --git a/docSite/content/docs/development/one-api.md b/docSite/content/docs/development/one-api.md index f544927be..72a9e7a5c 100644 --- a/docSite/content/docs/development/one-api.md +++ b/docSite/content/docs/development/one-api.md @@ -1,6 +1,6 @@ --- title: '部署和使用OneAPI,实现Azure、ChatGLM、本地模型接入' -description: '部署和使用OneAPI,实现Azure、ChatGLM、本地模型接入' +description: '部署和使用OneAPI,实现Azure、ChatGLM、本地模型接入。OneAPI使用教程' icon: 'Api' draft: false toc: true @@ -41,7 +41,7 @@ SqlLite 版本不支持多实例,适合个人小流量使用,但是价格非 **2. 打开 AppLaunchpad(应用管理) 工具** -![step1](/imgs/oneapi-step1.jpg) +![step1](/imgs/oneapi-step1.webp) **3. 点击创建新应用** @@ -71,6 +71,13 @@ BATCH_UPDATE_INTERVAL=60 2. OneAPI 会根据请求传入的`模型`来决定使用哪一个`Key`,如果一个模型对应了多个`Key`,则会随机调用。 2. 令牌:访问 OneAPI 所需的凭证,只需要这`1`个凭证即可访问`OneAPI`上配置的模型。因此`FastGPT`中,只需要配置`OneAPI`的`baseurl`和`令牌`即可。 +### 大致工作流程 + +1. 客户端请求 OneAPI +2. 根据请求中的 `model` 参数,匹配对应的渠道(根据渠道里的模型进行匹配,必须完全一致)。如果匹配到多个渠道,则随机选择一个(同优先级)。 +3. OneAPI 向真正的地址发出请求。 +4. OneAPI 将结果返回给客户端。 + ### 1. 登录 One API 打开 【One API 应用详情】,找到访问地址: @@ -81,7 +88,7 @@ BATCH_UPDATE_INTERVAL=60 ### 2. 创建渠道和令牌 -在 One API 中添加对应渠道,直接点击 【添加基础模型】,不要遗漏了向量模型 +在 One API 中添加对应渠道,直接点击 【添加基础模型】,不要遗漏了向量模型(Embedding) ![step6](/imgs/oneapi-step6.png) 创建一个令牌 @@ -112,7 +119,7 @@ CHAT_API_KEY=sk-xxxxxx ### 2. 修改 FastGPT 配置文件 -可以在 `/projects/app/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json),配置文件中有一项是对话模型配置: +可以在 `/projects/app/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json),配置文件中有一项是**对话模型配置**: ```json "llmModels": [ @@ -144,6 +151,24 @@ CHAT_API_KEY=sk-xxxxxx ], ``` +**添加向量模型:** + +```json +"vectorModels": [ + ...... + { + "model": "text-embedding-ada-002", + "name": "Embedding-2", + "avatar": "/imgs/model/openai.svg", + "charsPointsPrice": 0, + "defaultToken": 700, + "maxToken": 3000, + "weight": 100 + }, + ...... +] +``` + ### 3. 重启 FastGPT ```bash diff --git a/docSite/content/docs/development/openapi/dataset.md b/docSite/content/docs/development/openapi/dataset.md index 2de562041..17844816d 100644 --- a/docSite/content/docs/development/openapi/dataset.md +++ b/docSite/content/docs/development/openapi/dataset.md @@ -9,7 +9,7 @@ weight: 853 | 如何获取知识库ID(datasetId) | 如何获取文件集合ID(collection_id) | | --------------------- | --------------------- | -| ![](/imgs/getDatasetId.jpg) | ![](/imgs/getfile_id.png) | +| ![](/imgs/getDatasetId.jpg) | ![](/imgs/getfile_id.webp) | diff --git a/docSite/content/docs/development/proxy/nginx.md b/docSite/content/docs/development/proxy/nginx.md index 33c364602..6d790d996 100644 --- a/docSite/content/docs/development/proxy/nginx.md +++ b/docSite/content/docs/development/proxy/nginx.md @@ -15,7 +15,7 @@ weight: 951 打开 「应用管理」,点击「新建应用」: -![](/imgs/sealos3.jpg) +![](/imgs/sealos3.webp) ![](/imgs/sealos4.png) ### 填写基本配置 diff --git a/docSite/content/docs/development/upgrading/47.md b/docSite/content/docs/development/upgrading/47.md index 54f5b4cec..1a2a646f2 100644 --- a/docSite/content/docs/development/upgrading/47.md +++ b/docSite/content/docs/development/upgrading/47.md @@ -7,13 +7,45 @@ toc: true weight: 826 --- -## 修改配置文件 +## 1. 修改配置文件 增加一些 Boolean 值,用于决定不同功能块可以使用哪些模型,同时增加了模型的 logo:[点击查看最新的配置文件](/docs/development/configuration/) -## 初始化脚本 +## 2. Docker 部署的用户, 修改 docker-compose.yml 文件 -从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成自己域名 +在 fastgpt 容器中,挂在一个目录,用于存储临时文件(文件上传时候)。可以参考最新的 [docker-compose.yml](https://raw.githubusercontent.com/labring/FastGPT/main/files/deploy/fastgpt/docker-compose.yml) + +```yaml +...... + fastgpt: + ...... + volumes: + - ./config.json:/app/data/config.json + - ./fastgpt/tmp:/app/tmp +...... +``` + +## 2. Sealos 部署的用户,挂载存储券 + +| Step1 | Step 2 | Step3 | +| --- | --- | --- | +| ![](/imgs/47-sealos1.png) | ![](/imgs/47-sealos2.png) | ![](/imgs/47-sealos3.png) | +| Step4 | Step 5 | | +| ![](/imgs/47-sealos4.webp) | ![](/imgs/47-sealos5.png) | 完工,检查下应用状态 | + +命令如下: + +```bash +kubectl patch statefulset {{这里改成第一步的应用名}} -p '{"spec":{"template":{"spec":{"securityContext":{"fsGroup": 1001, "fsGroupChangePolicy": "Always"}}}}}' + +# 例如下面的 +# kubectl patch statefulset fastgpt-test -p '{"spec":{"template":{"spec":{"securityContext":{"fsGroup": 1001, "fsGroupChangePolicy": "Always"}}}}}' +``` + + +## 3. 初始化脚本 + +升级完镜像后。从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成自己域名 ```bash curl --location --request POST 'https://{{host}}/api/admin/initv47' \ @@ -24,7 +56,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv47' \ 脚本功能: 1. 初始化插件的 parentId -## 升级 ReRank 模型 +## 4. 升级 ReRank 模型 4.7对ReRank模型进行了格式变动,兼容 cohere 的格式,可以直接使用 cohere 提供的 API。如果是本地的 ReRank 模型,需要修改镜像为:`luanshaotong/reranker:v0.2` 。 @@ -52,12 +84,19 @@ cohere的重排模型对中文不是很好,感觉不如 bge 的好用,接入 1. 新增 - 工具调用模块,可以让LLM模型根据用户意图,动态的选择其他模型或插件执行。 2. 新增 - 分类和内容提取支持 functionCall 模式。部分模型支持 functionCall 不支持 ToolCall,也可以使用了。需要把 LLM 模型配置文件里的 `functionCall` 设置为 `true`, `toolChoice`设置为 `false`。如果 `toolChoice` 为 true,会走 tool 模式。 3. 新增 - HTTP插件,可实现OpenAPI快速生成插件。 -4. 优化 - 高级编排性能。 -5. 优化 - 抽离 Flow controller 到 packages。 -6. 优化 - AI模型选择。 -7. 修复 - 开源版重排选不上。 -8. 修复 - http 请求 body,不使用时,传入undefined。(会造成部分GET请求失败) -9. 新增 - 支持 http url 使用变量。 -10. 修复 - 469 的提取的提示词容易造成幻觉。 -11. 修复 - PG HNSW索引未实际生效问题,本次更新后,搜索速度大幅度提升(但是可能会出现精度损失,如果出现精度损失需要参考PgVector文档,对索引进行调整)。详细见:https://github.com/pgvector/pgvector?tab=readme-ov-file#troubleshooting -12. 新增 - Rerank 模型兼容 [cohere的格式](https://docs.cohere.com/reference/rerank-1),可以直接使用 cohere 的 rerank 模型。 +4. 新增 - Rerank 模型兼容 [cohere的格式](https://docs.cohere.com/reference/rerank-1),可以直接使用 cohere 的 rerank 模型。 +5. 新增 - Helm 安装。 +6. 优化 - 高级编排性能。 +7. 优化 - 抽离 Flow controller 到 packages。 +8. 优化 - AI模型选择。 +9. 优化 - 手动输入知识库弹窗。 +10. 优化 - 变量输入弹窗。 +11. 优化 - docker 部署,自动初始化副本集。 +12. 优化 - 浏览器读取文件自动推断编码,减少乱码情况。 +13. 修复 - 开源版重排选不上。 +14. 修复 - http 请求 body,不使用时,传入undefined。(会造成部分GET请求失败) +15. 新增 - 支持 http url 使用变量。 +16. 修复 - 469 的提取的提示词容易造成幻觉。 +17. 修复 - PG HNSW索引未实际生效问题,本次更新后,搜索速度大幅度提升(但是可能会出现精度损失,如果出现精度损失需要参考PgVector文档,对索引进行调整)。详细见:https://github.com/pgvector/pgvector?tab=readme-ov-file#troubleshooting +18. 修复Safari浏览器语音输入问题。 +19. 修复 - 自定义分割规则可输入正则特殊字符(之前输入的话,会导致前端崩溃) diff --git a/docSite/content/docs/intro.md b/docSite/content/docs/intro.md index 9a8e99b8f..40fbe36f4 100644 --- a/docSite/content/docs/intro.md +++ b/docSite/content/docs/intro.md @@ -15,7 +15,7 @@ FastGPT 在线使用:[https://fastgpt.in](https://fastgpt.in) | | | | --------------------- | --------------------- | -| ![](/imgs/intro1.png) | ![](/imgs/intro2.png) | +| ![](/imgs/intro1.webp) | ![](/imgs/intro2.png) | | ![](/imgs/intro3.png) | ![](/imgs/intro4.png) | ## FastGPT 能力 diff --git a/docSite/content/docs/use-cases/gapier.md b/docSite/content/docs/use-cases/gapier.md index a3c8f3c22..0a38e6860 100644 --- a/docSite/content/docs/use-cases/gapier.md +++ b/docSite/content/docs/use-cases/gapier.md @@ -11,7 +11,7 @@ FastGPT V4.7版本加入了工具调用,可以兼容 GPTs 的 Actions。这意 Gapier 是一个在线 GPTs Actions工具,提供了50多种现成工具,并且每天有免费额度进行测试,方便用户试用,官方地址为:[https://gapier.com/](https://gapier.com/)。 -![](/imgs/gapierToolResult1.png) +![](/imgs/gapierToolResult1.webp) 现在,我们开始把 Gapier 的工具导入到 FastGPT 中。 @@ -33,19 +33,19 @@ Gapier 是一个在线 GPTs Actions工具,提供了50多种现成工具,并 | Step1 | Step2 | | --- | --- | --- | -| ![](/imgs/gapierTool8.png) | ![](/imgs/gapierTool9.png) | +| ![](/imgs/gapierTool8.png) | ![](/imgs/gapierTool9.webp) | | Step3 | Step4 | -| ![](/imgs/gapierTool10.png) | ![](/imgs/gapierTool11.png) | +| ![](/imgs/gapierTool10.webp) | ![](/imgs/gapierTool11.png) | ### 高级编排 | Step1 | Step2 | | --- | --- | --- | -| ![](/imgs/gapierTool12.png) | ![](/imgs/gapierTool13.png) | +| ![](/imgs/gapierTool12.webp) | ![](/imgs/gapierTool13.webp) | | Step3 | Step4 | -| ![](/imgs/gapierTool14.png) | ![](/imgs/gapierTool15.png) | +| ![](/imgs/gapierTool14.webp) | ![](/imgs/gapierTool15.webp) | -![](/imgs/gapierTool16.png) +![](/imgs/gapierTool16.webp) ## 3. 工具调用说明 @@ -57,4 +57,4 @@ Gapier 是一个在线 GPTs Actions工具,提供了50多种现成工具,并 线上版用户,可以在模型选择时,看到是否支持函数调用的标识。 -![](/imgs/gapierTool17.png) +![](/imgs/gapierTool17.webp) diff --git a/docSite/content/docs/workflow/examples/dalle3.md b/docSite/content/docs/workflow/examples/dalle3.md index d80e91828..89bfa5d29 100644 --- a/docSite/content/docs/workflow/examples/dalle3.md +++ b/docSite/content/docs/workflow/examples/dalle3.md @@ -9,7 +9,7 @@ weight: 404 | | | | --------------------- | --------------------- | -| ![](/imgs/demo-dalle1.png) | ![](/imgs/demo-dalle2.png) | +| ![](/imgs/demo-dalle1.png) | ![](/imgs/demo-dalle2.webp) | ## OpenAI Dalle3 接口 diff --git a/docSite/content/docs/workflow/examples/feishu_webhook.md b/docSite/content/docs/workflow/examples/feishu_webhook.md new file mode 100644 index 000000000..26549d17c --- /dev/null +++ b/docSite/content/docs/workflow/examples/feishu_webhook.md @@ -0,0 +1,503 @@ +--- +title: '发送飞书webhook通知' +description: '利用工具调用模块,发送一个飞书webhook通知' +icon: 'image' +draft: false +toc: true +weight: 404 +--- + +该文章展示如何发送一个简单的飞书webhook通知,以此类推,发送其他类型的通知也可以这么操作。 + +| | | +| --------------------- | --------------------- | +| ![](/imgs/feishuwebhook1.png) | ![](/imgs/feishuwebhook2.webp) | + +## 1. 准备飞书机器人 + +| | | | +| --------------------- | --------------------- |--------------------- | +| ![](/imgs/feishuwebhook3.png) | ![](/imgs/feishuwebhook4.webp) |![](/imgs/feishuwebhook5.png) | + +## 2. 导入编排代码 + +复制下面配置,点击「高级编排」右上角的导入按键,导入该配置,导入后将飞书提供的接口地址复制到「HTTP 模块」。 + +```json +[ + { + "moduleId": "userGuide", + "name": "core.module.template.User guide", + "intro": "core.app.tip.userGuideTip", + "avatar": "/imgs/module/userGuide.png", + "flowType": "userGuide", + "position": { + "x": -92.26884681344463, + "y": 710.9354029649536 + }, + "inputs": [ + { + "key": "welcomeText", + "type": "hidden", + "valueType": "string", + "label": "core.app.Welcome Text", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "", + "connected": false + }, + { + "key": "variables", + "type": "hidden", + "valueType": "any", + "label": "core.module.Variable", + "value": [], + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "questionGuide", + "valueType": "boolean", + "type": "switch", + "label": "", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": false, + "connected": false + }, + { + "key": "tts", + "type": "hidden", + "valueType": "any", + "label": "", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": { + "type": "web" + }, + "connected": false + } + ], + "outputs": [] + }, + { + "moduleId": "userChatInput", + "name": "core.module.template.Chat entrance", + "intro": "当用户发送一个内容后,流程将会从这个模块开始执行。", + "avatar": "/imgs/module/userChatInput.svg", + "flowType": "questionInput", + "position": { + "x": 241.60980819261408, + "y": 1330.9528898009685 + }, + "inputs": [ + { + "key": "userChatInput", + "type": "systemInput", + "valueType": "string", + "label": "core.module.input.label.user question", + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + } + ], + "outputs": [ + { + "key": "userChatInput", + "label": "core.module.input.label.user question", + "type": "source", + "valueType": "string", + "targets": [ + { + "moduleId": "n84rvg", + "key": "userChatInput" + } + ] + } + ] + }, + { + "moduleId": "n84rvg", + "name": "工具调用(实验)", + "intro": "通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。", + "avatar": "/imgs/module/tool.svg", + "flowType": "tools", + "showStatus": true, + "position": { + "x": 809.4264785615641, + "y": 873.3971746859133 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "model", + "type": "settingLLMModel", + "label": "core.module.input.label.aiModel", + "required": true, + "valueType": "string", + "showTargetInApp": false, + "showTargetInPlugin": false, + "llmModelType": "all", + "value": "gpt-3.5-turbo", + "connected": false + }, + { + "key": "temperature", + "type": "hidden", + "label": "", + "value": 0, + "valueType": "number", + "min": 0, + "max": 10, + "step": 1, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "maxToken", + "type": "hidden", + "label": "", + "value": 2000, + "valueType": "number", + "min": 100, + "max": 4000, + "step": 50, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "systemPrompt", + "type": "textarea", + "max": 3000, + "valueType": "string", + "label": "core.ai.Prompt", + "description": "core.app.tip.chatNodeSystemPromptTip", + "placeholder": "core.app.tip.chatNodeSystemPromptTip", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "history", + "type": "numberInput", + "label": "core.module.input.label.chat history", + "required": true, + "min": 0, + "max": 30, + "valueType": "chatHistory", + "value": 6, + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "userChatInput", + "type": "custom", + "label": "", + "required": true, + "valueType": "string", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + } + ], + "outputs": [ + { + "key": "userChatInput", + "label": "core.module.input.label.user question", + "type": "hidden", + "valueType": "string", + "targets": [] + }, + { + "key": "selectedTools", + "valueType": "tools", + "type": "hidden", + "targets": [ + { + "moduleId": "3mbu91", + "key": "selectedTools" + } + ] + }, + { + "key": "finish", + "label": "", + "description": "", + "valueType": "boolean", + "type": "hidden", + "targets": [] + } + ] + }, + { + "moduleId": "3mbu91", + "name": "HTTP 请求", + "intro": "调用飞书webhook,发送一个通知", + "avatar": "/imgs/module/http.png", + "flowType": "httpRequest468", + "showStatus": true, + "position": { + "x": 1483.6437630977423, + "y": 798.9716928475544 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "system_httpMethod", + "type": "custom", + "valueType": "string", + "label": "", + "value": "POST", + "required": true, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpReqUrl", + "type": "hidden", + "valueType": "string", + "label": "", + "description": "core.module.input.description.Http Request Url", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "这里填写你的飞书机器人地址", + "connected": false + }, + { + "key": "system_httpHeader", + "type": "custom", + "valueType": "any", + "value": [], + "label": "", + "description": "core.module.input.description.Http Request Header", + "placeholder": "core.module.input.description.Http Request Header", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpParams", + "type": "hidden", + "valueType": "any", + "value": [], + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpJsonBody", + "type": "hidden", + "valueType": "any", + "value": "{\r\n \"msg_type\": \"text\",\r\n \"content\": {\r\n \"text\": \"{{text}}\"\r\n }\r\n}", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "DYNAMIC_INPUT_KEY", + "type": "target", + "valueType": "any", + "label": "core.module.inputType.dynamicTargetInput", + "description": "core.module.input.description.dynamic input", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": true, + "hideInApp": true, + "connected": false + }, + { + "key": "system_addInputParam", + "type": "addInputParam", + "valueType": "any", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "editField": { + "key": true, + "description": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string" + }, + "connected": false + }, + { + "valueType": "string", + "type": "hidden", + "key": "text", + "label": "text", + "toolDescription": "需要发送的通知内容", + "required": true, + "connected": false + } + ], + "outputs": [ + { + "key": "httpRawResponse", + "label": "原始响应", + "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", + "valueType": "any", + "type": "source", + "targets": [ + { + "moduleId": "rzx4mj", + "key": "switch" + }, + { + "moduleId": "psdhs1", + "key": "switch" + } + ] + }, + { + "key": "system_addOutputParam", + "type": "addOutputParam", + "valueType": "any", + "label": "", + "targets": [], + "editField": { + "key": true, + "description": true, + "dataType": true, + "defaultValue": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "outputType": "source", + "valueType": "string" + } + }, + { + "type": "source", + "valueType": "string", + "key": "prompt", + "label": "prompt", + "description": "", + "required": false, + "edit": true, + "editField": { + "key": true, + "description": true, + "dataType": true, + "defaultValue": true + }, + "targets": [] + } + ] + }, + { + "moduleId": "rzx4mj", + "name": "工具调用终止", + "intro": "该模块需配置工具调用使用。当该模块被执行时,本次工具调用将会强制结束,并且不再调用AI针对工具调用结果回答问题。", + "avatar": "/imgs/module/toolStop.svg", + "flowType": "stopTool", + "position": { + "x": 2145.5070710160267, + "y": 1306.3581817783079 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + } + ], + "outputs": [] + }, + { + "moduleId": "psdhs1", + "name": "指定回复", + "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", + "avatar": "/imgs/module/reply.png", + "flowType": "answerNode", + "position": { + "x": 2117.0429459850598, + "y": 1658.4125434513746 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + }, + { + "key": "text", + "type": "textarea", + "valueType": "any", + "label": "core.module.input.label.Response content", + "description": "core.module.input.description.Response content", + "placeholder": "core.module.input.description.Response content", + "showTargetInApp": true, + "showTargetInPlugin": true, + "value": "笑死发送成功啦", + "connected": false + } + ], + "outputs": [ + { + "key": "finish", + "label": "", + "description": "", + "valueType": "boolean", + "type": "hidden", + "targets": [] + } + ] + } +] +``` + +## 3. 流程说明 + +1. 为工具调用挂载一个HTTP模块,功能描述写上:调用飞书webhook,发送一个通知。 +2. HTTP模块的输入参数中,填写飞书机器人的地址,填写发送的通知内容。 +3. HTTP模块输出连接上一个工具终止模块,用于强制结束工具调用。不终止的话,会把调用结果返回给模型,模型会继续回答一次问题,浪费 Tokens +4. HTTP模块输出再连上一个指定回复,直接回复一个发送成功,用于替代AI的回答。 \ No newline at end of file diff --git a/docSite/content/docs/workflow/examples/google_search.md b/docSite/content/docs/workflow/examples/google_search.md index 77096db85..18ef2000c 100644 --- a/docSite/content/docs/workflow/examples/google_search.md +++ b/docSite/content/docs/workflow/examples/google_search.md @@ -7,9 +7,10 @@ toc: true weight: 402 --- -| | | +| | | | --------------------- | --------------------- | -| ![](/imgs/google_search_1.jpg) | ![](/imgs/google_search_2.jpg) | +| 工具调用模式 ![](/imgs/google_search_3.png) | 工具调用模式 ![](/imgs/google_search_4.webp) | +| 非工具调用模式 ![](/imgs/google_search_1.png) | 非工具调用模式 ![](/imgs/google_search_2.jpg) | 如上图,利用 HTTP 模块,你可以外接一个搜索引擎作为AI回复的参考资料。这里以调用 Google Search API 为例。注意:本文主要是为了介绍 HTTP 模型,具体的搜索效果需要依赖提示词和搜索引擎,尤其是【搜索引擎】,简单的搜索引擎无法获取更详细的内容,这部分可能需要更多的调试。 @@ -71,7 +72,411 @@ export default async function (ctx: FunctionContext) { {{% /details %}} -## 模块编排 +## 模块编排 - 工具调用模式 + +利用工具模块,则无需多余的操作,直接由模型决定是否调用谷歌搜索,并生成检索词即可。 + +复制下面配置,点击「高级编排」右上角的导入按键,导入该配置,导入后将接口地址复制到「HTTP 模块」。 + +{{% details title="编排配置" closed="true" %}} + +```json +[ + { + "moduleId": "userGuide", + "name": "core.module.template.User guide", + "intro": "core.app.tip.userGuideTip", + "avatar": "/imgs/module/userGuide.png", + "flowType": "userGuide", + "position": { + "x": -92.26884681344463, + "y": 710.9354029649536 + }, + "inputs": [ + { + "key": "welcomeText", + "type": "hidden", + "valueType": "string", + "label": "core.app.Welcome Text", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "", + "connected": false + }, + { + "key": "variables", + "type": "hidden", + "valueType": "any", + "label": "core.module.Variable", + "value": [], + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "questionGuide", + "valueType": "boolean", + "type": "switch", + "label": "", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": false, + "connected": false + }, + { + "key": "tts", + "type": "hidden", + "valueType": "any", + "label": "", + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": { + "type": "web" + }, + "connected": false + } + ], + "outputs": [] + }, + { + "moduleId": "userChatInput", + "name": "core.module.template.Chat entrance", + "intro": "当用户发送一个内容后,流程将会从这个模块开始执行。", + "avatar": "/imgs/module/userChatInput.svg", + "flowType": "questionInput", + "position": { + "x": 241.60980819261408, + "y": 1330.9528898009685 + }, + "inputs": [ + { + "key": "userChatInput", + "type": "systemInput", + "valueType": "string", + "label": "core.module.input.label.user question", + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + } + ], + "outputs": [ + { + "key": "userChatInput", + "label": "core.module.input.label.user question", + "type": "source", + "valueType": "string", + "targets": [ + { + "moduleId": "n84rvg", + "key": "userChatInput" + } + ] + } + ] + }, + { + "moduleId": "n84rvg", + "name": "工具调用(实验)", + "intro": "通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。", + "avatar": "/imgs/module/tool.svg", + "flowType": "tools", + "showStatus": true, + "position": { + "x": 809.4264785615641, + "y": 873.3971746859133 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "model", + "type": "settingLLMModel", + "label": "core.module.input.label.aiModel", + "required": true, + "valueType": "string", + "showTargetInApp": false, + "showTargetInPlugin": false, + "llmModelType": "all", + "value": "gpt-3.5-turbo", + "connected": false + }, + { + "key": "temperature", + "type": "hidden", + "label": "", + "value": 0, + "valueType": "number", + "min": 0, + "max": 10, + "step": 1, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "maxToken", + "type": "hidden", + "label": "", + "value": 2000, + "valueType": "number", + "min": 100, + "max": 4000, + "step": 50, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "systemPrompt", + "type": "textarea", + "max": 3000, + "valueType": "string", + "label": "core.ai.Prompt", + "description": "core.app.tip.chatNodeSystemPromptTip", + "placeholder": "core.app.tip.chatNodeSystemPromptTip", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "history", + "type": "numberInput", + "label": "core.module.input.label.chat history", + "required": true, + "min": 0, + "max": 30, + "valueType": "chatHistory", + "value": 6, + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "userChatInput", + "type": "custom", + "label": "", + "required": true, + "valueType": "string", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + } + ], + "outputs": [ + { + "key": "userChatInput", + "label": "core.module.input.label.user question", + "type": "hidden", + "valueType": "string", + "targets": [] + }, + { + "key": "selectedTools", + "valueType": "tools", + "type": "hidden", + "targets": [ + { + "moduleId": "3mbu91", + "key": "selectedTools" + } + ] + }, + { + "key": "finish", + "label": "", + "description": "", + "valueType": "boolean", + "type": "hidden", + "targets": [] + } + ] + }, + { + "moduleId": "3mbu91", + "name": "HTTP 请求", + "intro": "调用谷歌搜索,查询相关内容。", + "avatar": "/imgs/module/http.png", + "flowType": "httpRequest468", + "showStatus": true, + "position": { + "x": 848.9794517815185, + "y": 1575.7019813927138 + }, + "inputs": [ + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "system_httpMethod", + "type": "custom", + "valueType": "string", + "label": "", + "value": "POST", + "required": true, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpReqUrl", + "type": "hidden", + "valueType": "string", + "label": "", + "description": "core.module.input.description.Http Request Url", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "这里填写你的laf函数地址", + "connected": false + }, + { + "key": "system_httpHeader", + "type": "custom", + "valueType": "any", + "value": [], + "label": "", + "description": "core.module.input.description.Http Request Header", + "placeholder": "core.module.input.description.Http Request Header", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpParams", + "type": "hidden", + "valueType": "any", + "value": [], + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpJsonBody", + "type": "hidden", + "valueType": "any", + "value": "{\r\n \"searchKey\":\"{{query}}\"\r\n}", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "DYNAMIC_INPUT_KEY", + "type": "target", + "valueType": "any", + "label": "core.module.inputType.dynamicTargetInput", + "description": "core.module.input.description.dynamic input", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": true, + "hideInApp": true, + "connected": false + }, + { + "key": "system_addInputParam", + "type": "addInputParam", + "valueType": "any", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "editField": { + "key": true, + "description": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string" + }, + "connected": false + }, + { + "valueType": "string", + "type": "hidden", + "key": "query", + "label": "query", + "toolDescription": "谷歌搜索检索词", + "required": true, + "connected": false + } + ], + "outputs": [ + { + "key": "httpRawResponse", + "label": "原始响应", + "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", + "valueType": "any", + "type": "source", + "targets": [] + }, + { + "key": "system_addOutputParam", + "type": "addOutputParam", + "valueType": "any", + "label": "", + "targets": [], + "editField": { + "key": true, + "description": true, + "dataType": true, + "defaultValue": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "outputType": "source", + "valueType": "string" + } + }, + { + "type": "source", + "valueType": "string", + "key": "prompt", + "label": "prompt", + "description": "", + "required": false, + "edit": true, + "editField": { + "key": true, + "description": true, + "dataType": true, + "defaultValue": true + }, + "targets": [] + } + ] + } +] +``` + +{{% /details %}} + +## 模块编排 - 非工具调用方式 复制下面配置,点击「高级编排」右上角的导入按键,导入该配置,导入后将接口地址复制到「HTTP 模块」。 @@ -828,7 +1233,7 @@ export default async function (ctx: FunctionContext) { "required": false, "showTargetInApp": false, "showTargetInPlugin": false, - "value": "https://d8dns0.laf.dev/google_earch", + "value": "这里填写你的laf函数地址", "connected": false }, { @@ -977,9 +1382,11 @@ export default async function (ctx: FunctionContext) { {{% /details %}} -## 流程说明 + +### 流程说明 1. 利用【内容提取】模块,将用户的问题提取成搜索关键词。 2. 将搜索关键词传入【HTTP模块】,执行谷歌搜索。 3. 利用【文本编辑模块】组合搜索结果和问题,生成一个适合模型回答的问题。 4. 将新的问题发给【AI模块】,回答搜索结果。 + diff --git a/docSite/content/docs/workflow/examples/lab_appointment.md b/docSite/content/docs/workflow/examples/lab_appointment.md index 6d593fb6c..5c95081cb 100644 --- a/docSite/content/docs/workflow/examples/lab_appointment.md +++ b/docSite/content/docs/workflow/examples/lab_appointment.md @@ -9,7 +9,7 @@ weight: 403 | | | | --------------------- | --------------------- | -| ![](/imgs/demo-appointment1.jpg) | ![](/imgs/demo-appointment2.jpg) | +| ![](/imgs/demo-appointment1.webp) | ![](/imgs/demo-appointment2.jpg) | | ![](/imgs/demo-appointment3.jpg) | ![](/imgs/demo-appointment4.jpg) | diff --git a/docSite/content/docs/workflow/intro.md b/docSite/content/docs/workflow/intro.md index a815e42c5..349a8bb03 100644 --- a/docSite/content/docs/workflow/intro.md +++ b/docSite/content/docs/workflow/intro.md @@ -7,73 +7,79 @@ toc: true weight: 301 --- -FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用了 Flow 节点编排的方式来实现复杂工作流,提高可玩性和扩展性。但同时也提高了上手的门槛,有一定开发背景的用户使用起来会比较容易。 +FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用了 Flow 节点编排(工作流)的方式来实现复杂工作流,提高可玩性和扩展性。但同时也提高了上手的门槛,有一定开发背景的用户使用起来会比较容易。 [查看视频教程](https://www.bilibili.com/video/BV1aB4y1Z7Hy/?spm_id_from=333.999.list.card_archive.click&vd_source=903c2b09b7412037c2eddc6a8fb9828b) ![](/imgs/flow-intro1.png) -## 什么是模块? +## 什么是节点? -在程序中,模块可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个模块一个个拼接起来,即可一步步的去实现最终的 AI 输出。 +在程序中,节点可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个节点一个个拼接起来,即可一步步的去实现最终的 AI 输出。 -如下图,这是一个最简单的 AI 对话。它由用户输入的问题、聊天记录以及 AI 对话模块组成。 +如下图,这是一个最简单的 AI 对话。它由用户输入的问题、聊天记录以及 AI 对话节点组成。 ![](/imgs/flow-intro2.png) 执行流程如下: -1. 用户输入问题后,会向服务器发送一个请求,并携带问题。从而得到【用户问题】模块的输出。 -2. 根据设置的【最长记录数】来获取数据库中的记录数,从而得到【聊天记录】模块的输出。 - 经过上面两个流程,就得到了左侧两个蓝色点的结果。结果会被注入到右侧的【AI】对话模块。 -3. 【AI 对话】模块根据传入的聊天记录和用户问题,调用对话接口,从而实现回答。(这里的对话结果输出隐藏了起来,默认只要触发了对话模块,就会往客户端输出内容) +1. 用户输入问题后,会向服务器发送一个请求,并携带问题。从而得到【用户问题】节点的输出。 +2. 根据设置的【最长记录数】来获取数据库中的记录数,从而得到【聊天记录】节点的输出。 + 经过上面两个流程,就得到了左侧两个蓝色点的结果。结果会被注入到右侧的【AI】对话节点。 +3. 【AI 对话】节点根据传入的聊天记录和用户问题,调用对话接口,从而实现回答。(这里的对话结果输出隐藏了起来,默认只要触发了对话节点,就会往客户端输出内容) -### 模块分类 +### 节点分类 -从功能上,模块可以分为 2 类: +从功能上,节点可以分为 2 类: -1. **系统模块**:用户引导(配置一些对话框信息)、用户问题(流程入口)。 -2. **功能模块**:知识库搜索、AI 对话等剩余模块。(这些模块都有输入和输出,可以自由组合)。 +1. **系统节点**:用户引导(配置一些对话框信息)、用户问题(流程入口)。 +2. **功能节点**:知识库搜索、AI 对话等剩余节点。(这些节点都有输入和输出,可以自由组合)。 -### 模块的组成 +### 节点的组成 -每个模块会包含 3 个核心部分:固定参数、外部输入(左边有个圆圈)和输出(右边有个圆圈)。 +每个节点会包含 3 个核心部分:固定参数、外部输入(左边有个圆圈)和输出(右边有个圆圈)。 ![](/imgs/flow-intro3.png) - 对话模型、温度、回复上限、系统提示词和限定词为固定参数,同时系统提示词和限定词也可以作为外部输入,意味着如果你有输入流向了系统提示词,那么原本填写的内容就会被**覆盖**。 - - 触发器、引用内容、聊天记录和用户问题则为外部输入,需要从其他模块的输出流入。 - - 回复结束则为该模块的输出。 + - 触发器、引用内容、聊天记录和用户问题则为外部输入,需要从其他节点的输出流入。 + - 回复结束则为该节点的输出。 -### 模块什么时候被执行? +## 重点 - 工作流是如何运行的 -模块执行的原则: +与单出入口的工作流不同,FastGPT的工作流可以指定**不同的入口**,并且没有**固定的出口**,而是以节点运行结束作为出口,如果在一个轮调用中,所有节点都不再允许,则工作流结束。 -1. 仅关心**已连接的**外部输入,即左边的圆圈被连接了。 -2. 当连接内容都有值时触发。 -3. **可以多个输出连接到一个输入,后续的值会覆盖前面的值。** +不过为了方便阅读,大部分时候,我们仍是设置一个模块作为入口,在工作流中,它被叫做`对话入口`。下面我们来看下,工作流是如何运行的,以及每个节点何时被触发执行。 -#### 示例 1: +记住3个**节点可执行**的原则: -聊天记录模块会自动执行,因此聊天记录输入会自动赋值。当用户发送问题时,【用户问题】模块会输出值,此时【AI 对话】模块的用户问题输入也会被赋值。两个连接的输入都被赋值后,会执行 【AI 对话】模块。 +1. 仅关心**已连接的**外部输入,即左边的圆圈被连接了参数。 +2. 当**已连接的**内容都被赋值的时候触发。(这个地方经常会遇到,连接了很多根输入线,但是只要有一个输入没有值,这个节点也不会执行) +3. 可以多个输出连接到一个输入,后续的值会覆盖前面的值。 + +![](/imgs/workflow_process.png) + +### 示例 1: + +聊天记录节点会自动执行,因此聊天记录输入会自动赋值。当用户发送问题时,【用户问题】节点会输出值,此时【AI 对话】节点的用户问题输入也会被赋值。两个连接的输入都被赋值后,会执行 【AI 对话】节点。 ![](/imgs/flow-intro1.png) -#### 例子 2: +### 例子 2: 下图是一个知识库搜索例子。 -1. 历史记录会流入【AI 对话】模块。 -2. 用户的问题会流入【知识库搜索】和【AI 对话】模块,由于【AI 对话】模块的触发器和引用内容还是空,此时不会执行。 -3. 【知识库搜索】模块仅一个外部输入,并且被赋值,开始执行。 -4. 【知识库搜索】结果为空时,“搜索结果不为空”的值为空,不会输出,因此【AI 对话】模块会因为触发器没有赋值而无法执行。而“搜索结果为空”会有输出,流向指定回复的触发器,因此【指定回复】模块进行输出。 +1. 历史记录会流入【AI 对话】节点。 +2. 用户的问题会流入【知识库搜索】和【AI 对话】节点,由于【AI 对话】节点的触发器和引用内容还是空,此时不会执行。 +3. 【知识库搜索】节点仅一个外部输入,并且被赋值,开始执行。 +4. 【知识库搜索】结果为空时,“搜索结果不为空”的值为空,不会输出,因此【AI 对话】节点会因为触发器没有赋值而无法执行。而“搜索结果为空”会有输出,流向指定回复的触发器,因此【指定回复】节点进行输出。 5. 【知识库搜索】结果不为空时,“搜索结果不为空”和“引用内容”都有输出,会流向【AI 对话】,此时【AI 对话】的 4 个外部输入都被赋值,开始执行。 ![](/imgs/flow-intro4.png) -## 如何连接模块 +## 如何连接节点 -1. 为了方便识别不同输入输出的类型,FastGPT 给每个模块的输入输出连接点赋予不同的颜色,你可以把相同颜色的连接点连接起来。其中,灰色代表任意类型,可以随意连接。 +1. 为了方便识别不同输入输出的类型,FastGPT 给每个节点的输入输出连接点赋予不同的颜色,你可以把相同颜色的连接点连接起来。其中,灰色代表任意类型,可以随意连接。 2. 位于左侧的连接点为输入,右侧的为输出,连接只能将一个输入和输出连接起来,不能连接“输入和输入”或者“输出和输出”。 3. 可以点击连接线中间的 x 来删除连接线。 4. 可以左键点击选中连接线 @@ -81,8 +87,8 @@ FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用 ## 如何阅读? 1. 建议从左往右阅读。 -2. 从 **用户问题** 模块开始。用户问题模块,代表的是用户发送了一段文本,触发任务开始。 -3. 关注【AI 对话】和【指定回复】模块,这两个模块是输出答案的地方。 +2. 从 **用户问题** 节点开始。用户问题节点,代表的是用户发送了一段文本,触发任务开始。 +3. 关注【AI 对话】和【指定回复】节点,这两个节点是输出答案的地方。 ## FAQ @@ -90,9 +96,9 @@ FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用 1. 文本加工,可以对字符串进行合并。 2. 知识库搜索合并,可以合并多个知识库搜索结果 -3. 其他结果,无法直接合并,可以考虑传入到`HTTP`模块中进行合并,使用`[Laf](https://laf.run/)`可以快速实现一个无服务器HTTP接口。 +3. 其他结果,无法直接合并,可以考虑传入到`HTTP`节点中进行合并,使用`[Laf](https://laf.run/)`可以快速实现一个无服务器HTTP接口。 -### 模块为什么有2个用户问题 +### 节点为什么有2个用户问题 -左侧的`用户问题`是指该模块所需的输入。右侧的`用户问题`是为了方便后续的连线,输出的值和传入的用户问题一样。 +左侧的`用户问题`是指该节点所需的输入。右侧的`用户问题`是为了方便后续的连线,输出的值和传入的用户问题一样。 diff --git a/docSite/content/docs/workflow/modules/ai_chat.md b/docSite/content/docs/workflow/modules/ai_chat.md index 42991ed2a..260c03476 100644 --- a/docSite/content/docs/workflow/modules/ai_chat.md +++ b/docSite/content/docs/workflow/modules/ai_chat.md @@ -9,7 +9,7 @@ weight: 351 ## 特点 -- 可重复添加(复杂编排时防止线太乱,可以更美观) +- 可重复添加 - 有外部输入 - 有静态配置 - 触发执行 @@ -19,53 +19,18 @@ weight: 351 ## 参数说明 -### 对话模型 +## AI模型 可以通过 [config.json](/docs/development/configuration/) 配置可选的对话模型,通过 [one-api](/docs/development/one-api/) 来实现多模型接入。 -### 温度 & 回复上限 +点击AI模型后,可以配置模型的相关参数。 -+ **温度**:越低回答越严谨,少废话(实测下来,感觉差别不大) -+ **回复上限**:最大回复 token 数量(只有 OpenAI 模型有效)。注意,是回复!不是总 tokens。 +![](/imgs/aichat02.png) -### 系统提示词(可被外部输入覆盖) +![](/imgs/aichat2.png) -被放置在上下文数组的最前面,role 为 system,用于引导模型。具体用法参考各搜索引擎的教程~ -### 限定词(可被外部输入覆盖) -与系统提示词类似,role 也是 system 类型,只不过位置会被放置在问题前,拥有更强的引导作用。 - -### 引用内容 - -接收一个外部输入的数组,主要是由【知识库搜索】模块生成,也可以由 HTTP 模块从外部引入。数据结构示例如下: - -```ts -type DataType = { - dataset_id?: string; - id?: string; - q: string; - a: string; - source?: string; -}; -// 如果是外部引入的内容,尽量不要携带 dataset_id 和 id -const quoteList: DataType[] = [ - { dataset_id: '11', id: '222', q: '你还', a: '哈哈', source: '' }, - { dataset_id: '11', id: '333', q: '你还', a: '哈哈', source: '' }, - { dataset_id: '11', id: '444', q: '你还', a: '哈哈', source: '' } -]; -``` - -## 完整上下文组成 - -最终发送给 LLM 大模型的数据是一个数组,内容和顺序如下: - -```bash -[ - 系统提示词 - 引用内容 - 聊天记录 - 限定词 - 问题 -] -``` \ No newline at end of file +{{% alert icon="🍅" context="success" %}} +具体配置参数介绍可以参考: [AI参数配置说明](/docs/course/ai_settings) +{{% /alert %}} \ No newline at end of file diff --git a/docSite/content/docs/workflow/modules/coreferenceResolution.md b/docSite/content/docs/workflow/modules/coreferenceResolution.md index f146ba7dc..e8a06e4c2 100644 --- a/docSite/content/docs/workflow/modules/coreferenceResolution.md +++ b/docSite/content/docs/workflow/modules/coreferenceResolution.md @@ -21,11 +21,11 @@ weight: 364 在搜索的过程中,尤其是连续对话的搜索,我们通常会发现后续的问题难以搜索到合适的内容,其中一个原因是知识库搜索只会使用“当前”的问题去执行。看下面的例子: -![](/imgs/coreferenceResolution2.jpg) +![](/imgs/coreferenceResolution2.webp) 用户在提问“第二点是什么”的时候,只会去知识库里查找“第二点是什么”,压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题优化】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下: -![](/imgs/coreferenceResolution3.jpg) +![](/imgs/coreferenceResolution3.webp) ## 功能 diff --git a/docSite/content/docs/workflow/modules/dataset_search.md b/docSite/content/docs/workflow/modules/dataset_search.md index 7875e29e7..2418fb473 100644 --- a/docSite/content/docs/workflow/modules/dataset_search.md +++ b/docSite/content/docs/workflow/modules/dataset_search.md @@ -17,7 +17,7 @@ weight: 357 - 触发执行 - 核心模块 -![](/imgs/flow-kbsearch1.png) +![](/imgs/flow-dataset1.png) ## 参数说明 @@ -25,15 +25,9 @@ weight: 357 可以选择一个或多个**相同向量模型**的知识库,用于向量搜索。 -### 输入 - 相似度 +### 输入 - 搜索参数 -学名称为距离,两个向量之间距离,可以认为是两个向量的相似度,又可以映射成文本之间的相似度。 - -需要注意的是,不同的向量模型之间的相似度是不能比较的,因为他们的距离值计算出来差距很大。例如,openai 的 embedding 模型,通常 0.8 以上的才是较为准确的内容,而 M3E 模型则是 0.35。 - -### 输入 - 单次搜索上限 - -每次触发搜索模块时,最多取 n 条作为最终引用,又称 topN。需要注意的是,取了 n 条引用不代表对话模型都可以使用,还会受对话模型最大 Tokens 的影响。 +[点击查看参数介绍](/docs/course/data_search/#搜索参数) ### 输出 - 搜索结果 diff --git a/docSite/content/docs/workflow/modules/guide.md b/docSite/content/docs/workflow/modules/guide.md deleted file mode 100644 index b5d083b37..000000000 --- a/docSite/content/docs/workflow/modules/guide.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "用户引导" -description: "FastGPT 用户引导模块介绍" -icon: "psychology" -draft: false -toc: true -weight: 353 ---- - -## 特点 - -- 仅可添加 1 个 -- 无外部输入 -- 不参与实际调度 - -## 作用 - -可以配置欢迎语、全局变量、语言播报等,类似于系统设置,不参与工作流的运行。 - -![](/imgs/guide.png) - -### 欢迎语 - -会在对话开始前发送一个欢迎语。该功能只在网页生效,API是无效的,并且该欢迎语不会被加入 AI 的对话记录中。 - -可以通过特殊的 Markdown 语法,来实现快速提问。 如图中的: - -``` -[剧情介绍] -[导演是谁] -``` - -### 全局变量 - -| | | -| ----- | ----- | -| ![](/imgs/variable.png) | ![](/imgs/variable2.png) | - -如上图中,我们配置了一个名为`测试`, key为`test`的变量,类型为`文本`的全局变量。并在对话中,通过`{{test}}`来引用该变量。 - - -| | | -| ----- | ----- | -| ![](/imgs/variable3.png) | ![](/imgs/variable4.png) | - -从上图中,可以看出,实际的提示词从:`这是一个变量测试: {{test}}` 变成了: `这是一个变量测试: 变量测试`,因为`{{test}}` 被变量替换了。 - -变量在工作流中大部分的`文本输入框`都生效,例如:HTTP模块的URL和参数、各种功能块的提示词。 - -有一个特殊类型的变量,交`外部传入`。这种变量不需要用户填写,而是直接在调用时实时传入。目前支持从分享链接的Query和API调用的`variables`对象中获取。 - -![](/imgs/variable4.png) - - ------- - -除了自定义的全局变量外,还有一些系统参数可以选择: - -+ **cTime**: 当前时间,字符串格式,例如:2023/3/3 20:22 - -### 语音播报 - -| | | -| ----- | ----- | -| ![](/imgs/tts_setting.png) | ![](/imgs/tts_setting2.png) | - -### 猜你想问 - -开启后,每次对话结束,会发送最近的6条对话记录给AI,AI会根据这些对话记录,给出 3 个可能的问题。 - -![](/imgs/question_guide.png) diff --git a/docSite/content/docs/workflow/modules/http.md b/docSite/content/docs/workflow/modules/http.md index 5c593eb7f..ec6f30a77 100644 --- a/docSite/content/docs/workflow/modules/http.md +++ b/docSite/content/docs/workflow/modules/http.md @@ -19,12 +19,13 @@ weight: 355 ## 介绍 -HTTP 模块会向对应的地址发送一个 `POST/GET` 请求,携带部分`系统参数`及`自定义参数`,并接收一个 JSON 响应值,字段也是自定义。 +HTTP 模块会向对应的地址发送一个 `HTTP` 请求,实际操作与 Postman 和 ApiFox 这类直流工具使用差不多。 - Params 为路径请求参数,GET请求中用的居多。 -- Body 为请求体,POST请求中用的居多。 +- Body 为请求体,POST/PUT请求中用的居多。 - Headers 为请求头,用于传递一些特殊的信息。 - 3 种数据中均可以通过 `{{}}` 来引用变量。 +- url 也可以通过 `{{}}` 来引用变量。 - 变量来自于`全局变量`、`系统变量`、`局部传入` ## 参数结构 @@ -42,7 +43,7 @@ HTTP 模块会向对应的地址发送一个 `POST/GET` 请求,携带部分` ### Params, Headers -不多描述,使用方法和Postman, ApiFox 基本一致,目前 Params 和 Headers 未提供语法提示,后续会加入。 +不多描述,使用方法和Postman, ApiFox 基本一致。 可通过 {{key}} 来引入变量。例如: @@ -53,7 +54,7 @@ HTTP 模块会向对应的地址发送一个 `POST/GET` 请求,携带部分` ### Body -只有`POST`模式下会生效。 +只有特定请求类型下会生效。 可以写一个`自定义的 Json`,并通过 {{key}} 来引入变量。例如: @@ -182,17 +183,15 @@ HTTP 模块会向对应的地址发送一个 `POST/GET` 请求,携带部分` FastGPT v4.6.8 后,加入了出参格式化功能,主要以`json`格式化成`字符串`为主。如果你的输出类型选择了`字符串`,则会将`HTTP`对应`key`的值,转成`json`字符串进行输出。因此,未来你可以直接从`HTTP`接口输出内容至`文本加工`中,然后拼接适当的提示词,最终输入给`AI对话`。 -### 动态外部数据 -在插件中的`HTTP模块`有一个属性叫`动态外部数据`,这个属性是与`插件输入`中,数据类型为`动态外部数据`的值搭配使用。 +{{% alert context="warning" %}} +HTTP模块非常强大,你可以对接一些公开的API,来提高编排的功能。 -类似于文本加工模块,会有一个不确定长度,不确定key的用户输入,因此这部分数据会被`动态外部数据`接收,它们是一个对象。在 HTTP 模块中,你可以在`Body`中接收到一个`key`为`DYNAMIC_INPUT_KEY`的对象。 +如果你不想额外部署服务,可以使用 [Laf](https://laf.dev/) 来快速开发上线接口,即写即发,无需部署。 +{{% /alert %}} ## laf 对接 HTTP 示例 -{{% alert context="warning" %}} -如果你不想额外部署服务,可以使用 [Laf](https://laf.dev/) 来快速开发上线接口,即写即发,无需部署。 -{{% /alert %}} 下面是在 Laf 编写的 POST 请求示例: @@ -250,4 +249,5 @@ export default async function (ctx: FunctionContext) { ## 相关示例 - [谷歌搜索](/docs/workflow/examples/google_search/) +- [发送飞书webhook](/docs/workflow/examples/feishu_webhook/) - [实验室预约(操作数据库)](/docs/workflow/examples/lab_appointment/) \ No newline at end of file diff --git a/docSite/content/docs/workflow/modules/input.md b/docSite/content/docs/workflow/modules/input.md index 5e205018d..1898e21c5 100644 --- a/docSite/content/docs/workflow/modules/input.md +++ b/docSite/content/docs/workflow/modules/input.md @@ -1,6 +1,6 @@ --- -title: "用户问题" -description: "FastGPT 用户问题模块介绍" +title: "对话入口" +description: "FastGPT 对话入口模块介绍" icon: "input" draft: false toc: true diff --git a/docSite/content/docs/workflow/modules/tool.md b/docSite/content/docs/workflow/modules/tool.md new file mode 100644 index 000000000..0dda1e079 --- /dev/null +++ b/docSite/content/docs/workflow/modules/tool.md @@ -0,0 +1,59 @@ +--- +title: "工具调用" +description: "FastGPT 工具调用模块介绍" +icon: "build" +draft: false +toc: true +weight: 356 +--- + +![](/imgs/flow-tool1.png) + +## 什么是工具 + +工具可以是一个系统模块,例如:AI对话、知识库搜索、HTTP模块等。也可以是一个插件。 + +工具调用可以让 LLM 更动态的决策流程,而不都是固定的流程。(当然,缺点就是费tokens) + +## 工具的组成 + +1. 工具介绍。通常是模块的介绍或插件的介绍,这个介绍会告诉LLM,这个工具的作用是什么。 +2. 工具参数。对于系统模块来说,工具参数已经是固定的,无需额外配置。对于插件来说,工具参数是一个可配置项。 + +## 工具是如何运行的 + +要了解工具如何允许,首先需要知道它的运行条件。 + +1. 需要工具的介绍(或者叫描述)。这个介绍会告诉LLM,这个工具的作用是什么,LLM会根据上下文语义,决定是否需要调用这个工具。 +2. 工具的参数。有些工具调用时,可能需要一些特殊的参数。参数中有2个关键的值:`参数介绍`和`是否必须`。 + +结合工具的介绍、参数介绍和参数是否必须,LLM会决定是否调用这个工具。有以下几种情况: + + +1. 无参数的工具:直接根据工具介绍,决定是否需要执行。例如:获取当前时间。 +2. 有参数的工具: + 1. 无必须的参数:尽管上下文中,没有适合的参数,也可以调用该工具。但有时候,LLM会自己伪造一个参数。 + 2. 有必须的参数:如果没有适合的参数,LLM可能不会调用该工具。可以通过提示词,引导用户提供参数。 + +### 工具调用逻辑 + +在支持`函数调用`的模型中,可以一次性调用多个工具,调用逻辑如下: + +![](/imgs/flow-tool2.png) + +## 怎么用 + +| 有工具调用模块 | 无工具调用模块 | +| --- | --- | +| ![](/imgs/flow-tool3.png) | ![](/imgs/flow-tool4.png) | + +高级编排中,一旦有了工具调用模块,可用的工具头部会出现一个菱形,可以将它与工具调用模块底部的菱形相连接。 + +被连接的工具,会自动分离工具输入与普通的输入,并且可以编辑`介绍`,可以通过调整介绍,使得该工具调用时机更加精确。 + +关于工具调用,如何调试仍然是一个玄学,所以建议,不要一次性增加太多工具,选择少量工具调优后再进一步尝试。 + +## 相关示例 + +- [谷歌搜索](/docs/workflow/examples/google_search/) +- [发送飞书webhook](/docs/workflow/examples/feishu_webhook/) \ No newline at end of file diff --git a/files/deploy/fastgpt/docker-compose.yml b/files/deploy/fastgpt/docker-compose.yml index 969c3c484..9914dbdc9 100644 --- a/files/deploy/fastgpt/docker-compose.yml +++ b/files/deploy/fastgpt/docker-compose.yml @@ -97,6 +97,7 @@ services: - PG_URL=postgresql://username:password@pg:5432/postgres volumes: - ./config.json:/app/data/config.json + - ./fastgpt/tmp:/app/tmp mysql: image: mysql:8.0.36 container_name: mysql diff --git a/packages/global/common/string/swagger.ts b/packages/global/common/string/swagger.ts new file mode 100644 index 000000000..ccdfaccde --- /dev/null +++ b/packages/global/common/string/swagger.ts @@ -0,0 +1,15 @@ +import SwaggerParser from '@apidevtools/swagger-parser'; + +export const loadOpenAPISchemaFromUrl = async (url: string) => { + return SwaggerParser.bundle(url); +}; + +export const checkOpenAPISchemaValid = async (str: string) => { + try { + const res = await SwaggerParser.validate(JSON.parse(str)); + console.log(res); + return !!res; + } catch (error) { + return false; + } +}; diff --git a/packages/global/core/module/template/input.ts b/packages/global/core/module/template/input.ts index dc698b277..3d810ba08 100644 --- a/packages/global/core/module/template/input.ts +++ b/packages/global/core/module/template/input.ts @@ -6,7 +6,7 @@ import { chatNodeSystemPromptTip } from './tip'; export const Input_Template_Switch: FlowNodeInputItemType = { key: ModuleInputKeyEnum.switch, - type: FlowNodeInputTypeEnum.triggerAndFinish, + type: FlowNodeInputTypeEnum.hidden, label: '', description: 'core.module.input.description.Trigger', valueType: ModuleIOValueTypeEnum.any, diff --git a/packages/global/core/module/template/system/http468.ts b/packages/global/core/module/template/system/http468.ts index a4357bc58..a4599467a 100644 --- a/packages/global/core/module/template/system/http468.ts +++ b/packages/global/core/module/template/system/http468.ts @@ -122,6 +122,7 @@ export const HttpModule468: FlowNodeTemplateType = { outputType: FlowNodeOutputTypeEnum.source, valueType: ModuleIOValueTypeEnum.string } - } + }, + Output_Template_Finish ] }; diff --git a/packages/global/core/plugin/httpPlugin/utils.ts b/packages/global/core/plugin/httpPlugin/utils.ts index c71878722..b73ec2bb4 100644 --- a/packages/global/core/plugin/httpPlugin/utils.ts +++ b/packages/global/core/plugin/httpPlugin/utils.ts @@ -13,19 +13,21 @@ import { HttpParamAndHeaderItemType } from '../../module/api'; import { CreateOnePluginParams } from '../controller'; import { ModuleItemType } from '../../module/type'; import { HttpImgUrl } from '../../../common/file/image/constants'; +import SwaggerParser from '@apidevtools/swagger-parser'; -export const str2OpenApiSchema = (yamlStr = ''): OpenApiJsonSchema => { +export const str2OpenApiSchema = async (yamlStr = ''): Promise => { try { - const data: OpenAPIV3.Document = (() => { + const data = (() => { try { return JSON.parse(yamlStr); } catch (jsonError) { return yaml.load(yamlStr, { schema: yaml.FAILSAFE_SCHEMA }); } })(); + const jsonSchema = (await SwaggerParser.parse(data)) as OpenAPIV3.Document; - const serverPath = data.servers?.[0].url || ''; - const pathData = Object.keys(data.paths) + const serverPath = jsonSchema.servers?.[0].url || ''; + const pathData = Object.keys(jsonSchema.paths) .map((path) => { const methodData: any = data.paths[path]; return Object.keys(methodData) @@ -55,7 +57,7 @@ export const str2OpenApiSchema = (yamlStr = ''): OpenApiJsonSchema => { } }; -export const httpApiSchema2Plugins = ({ +export const httpApiSchema2Plugins = async ({ parentId, apiSchemaStr = '', customHeader = '' @@ -63,8 +65,9 @@ export const httpApiSchema2Plugins = ({ parentId: string; apiSchemaStr?: string; customHeader?: string; -}): CreateOnePluginParams[] => { - const jsonSchema = str2OpenApiSchema(apiSchemaStr); +}): Promise => { + const jsonSchema = await str2OpenApiSchema(apiSchemaStr); + const baseUrl = jsonSchema.serverPath; return jsonSchema.pathData.map((item) => { @@ -222,7 +225,7 @@ export const httpApiSchema2Plugins = ({ } } if (item.request) { - const properties = item.request?.content?.['application/json']?.schema?.properties; + const properties = item.request?.content?.['application/json']?.schema?.properties || {}; const keys = Object.keys(properties); if (keys.length > 0) { httpNodeBody = JSON.stringify( diff --git a/packages/global/package.json b/packages/global/package.json index 5b2257c7e..d8b5559e4 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -12,7 +12,8 @@ "js-yaml": "^4.1.0", "timezones-list": "^3.0.2", "next": "13.5.2", - "jschardet": "3.1.1" + "jschardet": "3.1.1", + "@apidevtools/swagger-parser": "^10.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", diff --git a/packages/global/support/user/inform/type.d.ts b/packages/global/support/user/inform/type.d.ts index d05847ffa..04a66fe30 100644 --- a/packages/global/support/user/inform/type.d.ts +++ b/packages/global/support/user/inform/type.d.ts @@ -8,6 +8,10 @@ export type SendInformProps = { export type SendInform2UserProps = SendInformProps & { tmbId: string; }; +export type SendInform2User = SendInformProps & { + type: `${InformTypeEnum}`; + tmbId: string; +}; export type UserInformSchema = { _id: string; diff --git a/packages/service/common/file/multer.ts b/packages/service/common/file/multer.ts index 27788987c..11fb25983 100644 --- a/packages/service/common/file/multer.ts +++ b/packages/service/common/file/multer.ts @@ -3,6 +3,7 @@ import multer from 'multer'; import path from 'path'; import { BucketNameEnum, bucketNameMap } from '@fastgpt/global/common/file/constants'; import { getNanoid } from '@fastgpt/global/common/string/tools'; +import { tmpFileDirPath } from './constants'; type FileType = { fieldname: string; @@ -23,9 +24,9 @@ export const getUploadModel = ({ maxSize = 500 }: { maxSize?: number }) => { }, preservePath: true, storage: multer.diskStorage({ - // destination: (_req, _file, cb) => { - // cb(null, tmpFileDirPath); - // }, + destination: (_req, _file, cb) => { + cb(null, tmpFileDirPath); + }, filename: async (req, file, cb) => { const { ext } = path.parse(decodeURIComponent(file.originalname)); cb(null, `${getNanoid()}${ext}`); diff --git a/packages/service/common/file/utils.ts b/packages/service/common/file/utils.ts index 380194747..47d956932 100644 --- a/packages/service/common/file/utils.ts +++ b/packages/service/common/file/utils.ts @@ -27,3 +27,18 @@ export const guessBase64ImageType = (str: string) => { const firstChar = str.charAt(0); return imageTypeMap[firstChar] || defaultType; }; + +export const clearDirFiles = (dirPath: string) => { + if (!fs.existsSync(dirPath)) { + return; + } + + fs.readdirSync(dirPath).forEach((file) => { + const curPath = `${dirPath}/${file}`; + if (fs.lstatSync(curPath).isDirectory()) { + clearDirFiles(curPath); + } else { + fs.unlinkSync(curPath); + } + }); +}; diff --git a/packages/service/core/ai/functions/queryExtension.ts b/packages/service/core/ai/functions/queryExtension.ts index 5850104ed..230e0f165 100644 --- a/packages/service/core/ai/functions/queryExtension.ts +++ b/packages/service/core/ai/functions/queryExtension.ts @@ -19,20 +19,28 @@ const defaultPrompt = `作为一个向量检索助手,你的任务是结合历 历史记录: """ Q: 对话背景。 -A: 当前对话是关于 FatGPT 的介绍和使用等。 +A: 当前对话是关于 Nginx 的介绍和使用等。 """ 原问题: 怎么下载 -检索词: ["FastGPT 如何下载?","下载 FastGPT 需要什么条件?","有哪些渠道可以下载 FastGPT?"] +检索词: ["Nginx 如何下载?","下载 Nginx 需要什么条件?","有哪些渠道可以下载 Nginx?"] ---------------- 历史记录: """ Q: 对话背景。 -A: 当前对话是关于 FatGPT 的介绍和使用等。 +A: 当前对话是关于 Nginx 的介绍和使用等。 Q: 报错 "no connection" A: 报错"no connection"可能是因为…… """ 原问题: 怎么解决 -检索词: ["FastGPT 报错"no connection"如何解决?", "造成 'no connection' 报错的原因。", "FastGPT提示'no connection',要怎么办?"] +检索词: ["Nginx报错"no connection"如何解决?","造成'no connection'报错的原因。","Nginx提示'no connection',要怎么办?"] +---------------- +历史记录: +""" +Q: 护产假多少天? +A: 护产假的天数根据员工所在的城市而定。请提供您所在的城市,以便我回答您的问题。 +""" +原问题: 沈阳 +检索词: ["沈阳的护产假多少天?"] ---------------- 历史记录: """ @@ -42,14 +50,6 @@ A: FastGPT 的作者是 labring。 原问题: Tell me about him 检索词: ["Introduce labring, the author of FastGPT." ," Background information on author labring." "," Why does labring do FastGPT?"] ---------------- -历史记录: -""" -Q: 对话背景。 -A: 当前对话是关于 FatGPT 的介绍和使用等。 -""" -原问题: 高级编排怎么用 -检索词: ["FastGPT的高级编排是什么?","FastGPT高级编排的使用教程。","FastGPT高级编排有什么用?"] ----------------- 历史记录: """ Q: 对话背景。 diff --git a/packages/service/core/workflow/dispatch/agent/runTool/constants.ts b/packages/service/core/workflow/dispatch/agent/runTool/constants.ts index eca3f8466..8c2fd4095 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/constants.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/constants.ts @@ -13,13 +13,13 @@ export const Prompt_Tool_Call = ` USER: 你好呀 ANSWER: 0: 你好,有什么可以帮助你的么? USER: 今天杭州的天气如何 -ANSWER: 1: {"toolId":"w2121",arguments:{"city": "杭州"}} +ANSWER: 1: {"toolId":"testToolId",arguments:{"city": "杭州"}} TOOL_RESPONSE: """ 晴天...... """ ANSWER: 0: 今天杭州是晴天。 USER: 今天杭州的天气适合去哪里玩? -ANSWER: 1: {"toolId":"as21da",arguments:{"query": "杭州 天气 去哪里玩"}} +ANSWER: 1: {"toolId":"testToolId2",arguments:{"query": "杭州 天气 去哪里玩"}} TOOL_RESPONSE: """ 晴天. 西湖、灵隐寺、千岛湖…… """ diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts index 02ffddcbb..2a3d9c81c 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts @@ -131,7 +131,7 @@ export const runToolWithPromptCall = async ( })(); const parseAnswerResult = parseAnswer(answer); - // console.log(answer, '==11=='); + // console.log(parseAnswer, '==11=='); // No tools if (typeof parseAnswerResult === 'string') { // No tool is invoked, indicating that the process is over @@ -270,7 +270,9 @@ export const runToolWithPromptCall = async ( // get the next user prompt lastMessage.content += `${answer} -TOOL_RESPONSE: ${toolsRunResponse.toolResponsePrompt} +TOOL_RESPONSE: """ +${toolsRunResponse.toolResponsePrompt} +""" ANSWER: `; /* check stop signal */ diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/chat/oneapi.ts index ae043a155..4f516860e 100644 --- a/packages/service/core/workflow/dispatch/chat/oneapi.ts +++ b/packages/service/core/workflow/dispatch/chat/oneapi.ts @@ -73,7 +73,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise void; variables: EditorVariablePickerType[]; - onChange?: (editorState: EditorState) => void; + onChange?: (editorState: EditorState, editor: LexicalEditor) => void; onBlur?: (editor: LexicalEditor) => void; value?: string; - currentValue?: string; placeholder?: string; }) { const [key, setKey] = useState(getNanoid(6)); @@ -112,9 +111,9 @@ export default function Editor({ { + onChange={(editorState, editor) => { startSts(() => { - onChange?.(e); + onChange?.(editorState, editor); }); }} /> diff --git a/packages/web/components/common/Textarea/PromptEditor/index.tsx b/packages/web/components/common/Textarea/PromptEditor/index.tsx index 25b9ddac4..037db8bed 100644 --- a/packages/web/components/common/Textarea/PromptEditor/index.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/index.tsx @@ -1,5 +1,5 @@ import { Button, ModalBody, ModalFooter, useDisclosure } from '@chakra-ui/react'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { editorStateToText } from './utils'; import Editor from './Editor'; import MyModal from '../../MyModal'; @@ -30,14 +30,15 @@ const PromptEditor = ({ title?: string; }) => { const { isOpen, onOpen, onClose } = useDisclosure(); - const [, startSts] = useTransition(); - const { t } = useTranslation(); - const onChangeInput = useCallback((editorState: EditorState) => { - const text = editorState.read(() => $getRoot().getTextContent()); - const formatValue = text.replaceAll('\n\n', '\n').replaceAll('}}{{', '}} {{'); + const onChangeInput = useCallback((editorState: EditorState, editor: LexicalEditor) => { + const stringifiedEditorState = JSON.stringify(editorState.toJSON()); + const parsedEditorState = editor.parseEditorState(stringifiedEditorState); + const editorStateTextString = parsedEditorState.read(() => $getRoot().getTextContent()); + + const formatValue = editorStateTextString.replaceAll('\n\n', '\n').replaceAll('}}{{', '}} {{'); onChange?.(formatValue); }, []); const onBlurInput = useCallback((editor: LexicalEditor) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac6149b3e..671e5cf81 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: packages/global: dependencies: + '@apidevtools/swagger-parser': + specifier: ^10.1.0 + version: 10.1.0(openapi-types@12.1.3) axios: specifier: ^1.5.1 version: 1.6.8 @@ -272,9 +275,6 @@ importers: projects/app: dependencies: - '@apidevtools/swagger-parser': - specifier: ^10.1.0 - version: 10.1.0(openapi-types@12.1.3) '@bany/curl-to-json': specifier: ^1.2.8 version: 1.2.8 diff --git a/projects/app/data/config.json b/projects/app/data/config.json index a91fdb55c..39072bc52 100644 --- a/projects/app/data/config.json +++ b/projects/app/data/config.json @@ -84,7 +84,9 @@ "charsPointsPrice": 0, "defaultToken": 700, "maxToken": 3000, - "weight": 100 + "weight": 100, + "dbConfig": {}, + "queryConfig": {} } ], "reRankModels": [], diff --git a/projects/app/package.json b/projects/app/package.json index 8bae72268..b33917170 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -9,7 +9,6 @@ "lint": "next lint" }, "dependencies": { - "@apidevtools/swagger-parser": "^10.1.0", "@bany/curl-to-json": "^1.2.8", "@chakra-ui/anatomy": "2.2.1", "@chakra-ui/icons": "2.1.1", diff --git a/projects/app/public/docs/versionIntro.md b/projects/app/public/docs/versionIntro.md index 7c5bcfff2..65c10a583 100644 --- a/projects/app/public/docs/versionIntro.md +++ b/projects/app/public/docs/versionIntro.md @@ -1,7 +1,13 @@ ### FastGPT V4.7 1. 新增 - 工具调用模块,可以让LLM模型根据用户意图,动态的选择其他模型或插件执行。 -2. 优化 - 高级编排性能 -3. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro) -4. [使用文档](https://doc.fastgpt.in/docs/intro/) -5. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) \ No newline at end of file +2. 新增 - 分类和内容提取支持 functionCall 模式。部分模型支持 functionCall 不支持 ToolCall,也可以使用了。需要把 LLM 模型配置文件里的 `functionCall` 设置为 `true`, `toolChoice`设置为 `false`。如果 `toolChoice` 为 true,会走 tool 模式。 +3. 新增 - HTTP插件,可实现OpenAPI快速生成插件。 +4. 优化 - 高级编排性能。 +5. 优化 - AI模型选择。 +6. 优化 - 手动输入知识库弹窗。 +7. 优化 - 变量输入弹窗。 +8. 优化 - 浏览器读取文件自动推断编码,减少乱码情况。 +9. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro) +10. [使用文档](https://doc.fastgpt.in/docs/intro/) +11. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) \ No newline at end of file diff --git a/projects/app/src/components/core/module/Flow/FlowProvider.tsx b/projects/app/src/components/core/module/Flow/FlowProvider.tsx index b8e1b2e87..af8f12ea4 100644 --- a/projects/app/src/components/core/module/Flow/FlowProvider.tsx +++ b/projects/app/src/components/core/module/Flow/FlowProvider.tsx @@ -405,7 +405,7 @@ export const FlowProvider = ({ toolInputs: inputs.filter((item) => isTool && item.toolDescription), commonInputs: inputs.filter((item) => { if (!isTool) return true; - return !item.toolDescription && item.key !== ModuleInputKeyEnum.switch; + return !item.toolDescription; }) }; }, diff --git a/projects/app/src/components/core/module/Flow/components/modules/Container.tsx b/projects/app/src/components/core/module/Flow/components/modules/Container.tsx index 0b6f65130..92f83a725 100644 --- a/projects/app/src/components/core/module/Flow/components/modules/Container.tsx +++ b/projects/app/src/components/core/module/Flow/components/modules/Container.tsx @@ -4,7 +4,7 @@ import { BoxProps } from '@chakra-ui/react'; const Container = ({ children, ...props }: BoxProps) => { return ( - + {children} ); diff --git a/projects/app/src/components/core/module/Flow/components/render/NodeCard.tsx b/projects/app/src/components/core/module/Flow/components/render/NodeCard.tsx index abcf22849..9449330da 100644 --- a/projects/app/src/components/core/module/Flow/components/render/NodeCard.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/NodeCard.tsx @@ -16,6 +16,7 @@ import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { LOGO_ICON } from '@fastgpt/global/common/system/constants'; import { ToolTargetHandle } from './ToolHandle'; import { useEditTextarea } from '@fastgpt/web/hooks/useEditTextarea'; +import TriggerAndFinish from './RenderInput/templates/TriggerAndFinish'; type Props = FlowModuleItemType & { children?: React.ReactNode | React.ReactNode[] | string; @@ -208,6 +209,8 @@ const NodeCard = (props: Props) => { )} + {/* switch */} + ); }, [ diff --git a/projects/app/src/components/core/module/Flow/components/render/RenderInput/index.tsx b/projects/app/src/components/core/module/Flow/components/render/RenderInput/index.tsx index a9e077018..da2fac795 100644 --- a/projects/app/src/components/core/module/Flow/components/render/RenderInput/index.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/RenderInput/index.tsx @@ -13,10 +13,6 @@ const RenderList: { types: `${FlowNodeInputTypeEnum}`[]; Component: React.ComponentType; }[] = [ - { - types: [FlowNodeInputTypeEnum.triggerAndFinish], - Component: dynamic(() => import('./templates/TriggerAndFinish')) - }, { types: [FlowNodeInputTypeEnum.input], Component: dynamic(() => import('./templates/TextInput')) diff --git a/projects/app/src/components/core/module/Flow/components/render/RenderInput/templates/TriggerAndFinish.tsx b/projects/app/src/components/core/module/Flow/components/render/RenderInput/templates/TriggerAndFinish.tsx index fd5d07bab..085223b9e 100644 --- a/projects/app/src/components/core/module/Flow/components/render/RenderInput/templates/TriggerAndFinish.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/RenderInput/templates/TriggerAndFinish.tsx @@ -7,10 +7,18 @@ import SourceHandle from '../../SourceHandle'; import { ModuleInputKeyEnum, ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants'; import { useFlowProviderStore } from '../../../../FlowProvider'; -const TriggerAndFinish = ({ moduleId }: RenderInputProps) => { +const TriggerAndFinish = ({ moduleId, isTool }: { moduleId: string; isTool: boolean }) => { const { t } = useTranslation(); const { nodes } = useFlowProviderStore(); + const inputs = useMemo( + () => nodes.find((node) => node.data.moduleId === moduleId)?.data?.inputs || [], + [moduleId, nodes] + ); + const hasSwitch = useMemo( + () => inputs.some((input) => input.key === ModuleInputKeyEnum.switch), + [inputs] + ); const outputs = useMemo( () => nodes.find((node) => node.data.moduleId === moduleId)?.data?.outputs || [], [moduleId, nodes] @@ -20,8 +28,8 @@ const TriggerAndFinish = ({ moduleId }: RenderInputProps) => { [outputs] ); - const Render = useMemo( - () => ( + const Render = useMemo(() => { + return ( { position={'relative'} > - - {t('core.module.input.label.switch')} + {!isTool && ( + + + {t('core.module.input.label.switch')} + + )} {hasFinishOutput && ( - + {t('core.module.output.label.running done')} )} - ), - [hasFinishOutput, t] - ); + ); + }, [hasFinishOutput, isTool, t]); - return Render; + return hasSwitch ? Render : null; }; export default React.memo(TriggerAndFinish); diff --git a/projects/app/src/components/core/module/Flow/components/render/SourceHandle.tsx b/projects/app/src/components/core/module/Flow/components/render/SourceHandle.tsx index af0f96e5a..2be2e3f29 100644 --- a/projects/app/src/components/core/module/Flow/components/render/SourceHandle.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/SourceHandle.tsx @@ -28,8 +28,8 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => { { { h={'14px'} border={'4px solid #5E8FFF'} transform={'translate(-40%,-30%) rotate(45deg)'} + pointerEvents={'none'} /> @@ -98,6 +99,7 @@ export const ToolSourceHandle = ({ moduleId }: ToolHandleProps) => { h={'14px'} border={'4px solid #5E8FFF'} transform={'translate(-40%,-30%) rotate(45deg)'} + pointerEvents={'none'} /> diff --git a/projects/app/src/pages/api/core/plugin/create.ts b/projects/app/src/pages/api/core/plugin/create.ts index 7b58b789a..d6c8f6286 100644 --- a/projects/app/src/pages/api/core/plugin/create.ts +++ b/projects/app/src/pages/api/core/plugin/create.ts @@ -4,7 +4,6 @@ import { connectToDatabase } from '@/service/mongo'; import type { CreateOnePluginParams } from '@fastgpt/global/core/plugin/controller'; import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user'; import { MongoPlugin } from '@fastgpt/service/core/plugin/schema'; -import { checkTeamPluginLimit } from '@fastgpt/service/support/permission/teamLimit'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { httpApiSchema2Plugins } from '@fastgpt/global/core/plugin/httpPlugin/utils'; @@ -31,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< { session } ); - const childrenPlugins = httpApiSchema2Plugins({ + const childrenPlugins = await httpApiSchema2Plugins({ parentId, apiSchemaStr: body.metadata?.apiSchemaStr, customHeader: body.metadata?.customHeaders diff --git a/projects/app/src/pages/api/core/plugin/httpPlugin/getApiSchemaByUrl.ts b/projects/app/src/pages/api/core/plugin/httpPlugin/getApiSchemaByUrl.ts index 42165d750..3ad92c46e 100644 --- a/projects/app/src/pages/api/core/plugin/httpPlugin/getApiSchemaByUrl.ts +++ b/projects/app/src/pages/api/core/plugin/httpPlugin/getApiSchemaByUrl.ts @@ -1,15 +1,13 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { jsonRes } from '@fastgpt/service/common/response'; -import SwaggerParser from '@apidevtools/swagger-parser'; +import { loadOpenAPISchemaFromUrl } from '@fastgpt/global/common/string/swagger'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { const apiURL = req.body.url as string; - const api = await SwaggerParser.validate(apiURL); - return jsonRes(res, { - data: api + data: await loadOpenAPISchemaFromUrl(apiURL) }); } catch (err) { jsonRes(res, { diff --git a/projects/app/src/pages/api/core/plugin/update.ts b/projects/app/src/pages/api/core/plugin/update.ts index 1ed8bc962..70e4ea8a1 100644 --- a/projects/app/src/pages/api/core/plugin/update.ts +++ b/projects/app/src/pages/api/core/plugin/update.ts @@ -75,7 +75,7 @@ const updateHttpChildrenPlugin = async ({ '_id metadata' ); - const schemaPlugins = httpApiSchema2Plugins({ + const schemaPlugins = await httpApiSchema2Plugins({ parentId: parent.id, apiSchemaStr: parent.metadata?.apiSchemaStr, customHeader: parent.metadata?.customHeaders diff --git a/projects/app/src/pages/plugin/list/component/HttpPluginEditModal.tsx b/projects/app/src/pages/plugin/list/component/HttpPluginEditModal.tsx index 11d44e6ca..66bb6910e 100644 --- a/projects/app/src/pages/plugin/list/component/HttpPluginEditModal.tsx +++ b/projects/app/src/pages/plugin/list/component/HttpPluginEditModal.tsx @@ -13,8 +13,7 @@ import { Tbody, Tr, Td, - IconButton, - useDisclosure + IconButton } from '@chakra-ui/react'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { useForm } from 'react-hook-form'; @@ -37,12 +36,12 @@ import { import { str2OpenApiSchema } from '@fastgpt/global/core/plugin/httpPlugin/utils'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; -import { AddIcon } from '@chakra-ui/icons'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { EditFormType } from './type'; import { FolderImgUrl } from '@fastgpt/global/common/file/image/constants'; import HttpInput from '@fastgpt/web/components/common/Input/HttpInput'; import { HttpHeaders } from '@/components/core/module/Flow/components/nodes/NodeHttp'; +import { OpenApiJsonSchema } from '@fastgpt/global/core/plugin/httpPlugin/type'; export const defaultHttpPlugin: CreateOnePluginParams = { avatar: FolderImgUrl, @@ -85,20 +84,7 @@ const HttpPluginEditModal = ({ defaultValues: defaultPlugin }); const apiSchemaStr = watch('metadata.apiSchemaStr'); - const apiData = useMemo(() => { - if (!apiSchemaStr) { - return { pathData: [], serverPath: '' }; - } - try { - return str2OpenApiSchema(apiSchemaStr); - } catch (err) { - toast({ - status: 'warning', - title: t('plugin.Invalid Schema') - }); - return { pathData: [], serverPath: '' }; - } - }, [apiSchemaStr, t, toast]); + const [apiData, setApiData] = useState({ pathData: [], serverPath: '' }); const { mutate: onCreate, isLoading: isCreating } = useRequest({ mutationFn: async (data: CreateOnePluginParams) => { @@ -201,6 +187,23 @@ const HttpPluginEditModal = ({ [customHeaders] ); + useEffect(() => { + (async () => { + if (!apiSchemaStr) { + return setApiData({ pathData: [], serverPath: '' }); + } + try { + setApiData(await str2OpenApiSchema(apiSchemaStr)); + } catch (err) { + toast({ + status: 'warning', + title: t('plugin.Invalid Schema') + }); + setApiData({ pathData: [], serverPath: '' }); + } + })(); + }, [apiSchemaStr, t, toast]); + return ( <> { const onclickBuyDatasetSize = useCallback( async ({ datasetSize, month }: { datasetSize: number; month: number }) => { try { + datasetSize = Math.ceil(datasetSize); + month = Math.ceil(month); + const datasetSizePayAmount = datasetSize * month * extraDatasetPrice; if (datasetSizePayAmount === 0) { return toast({ @@ -80,6 +83,8 @@ const ExtraPlan = () => { const onclickBuyExtraPoints = useCallback( async ({ points }: { points: number }) => { try { + points = Math.ceil(points); + const month = 1; const payAmount = points * month * extraPointsPrice; diff --git a/projects/app/src/service/mongo.ts b/projects/app/src/service/mongo.ts index e91d1dce6..58cbe31e3 100644 --- a/projects/app/src/service/mongo.ts +++ b/projects/app/src/service/mongo.ts @@ -11,6 +11,8 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { initGlobal } from './common/system'; import { startMongoWatch } from './common/system/volumnMongoWatch'; import { startTrainingQueue } from './core/dataset/training/utils'; +import { clearDirFiles } from '@fastgpt/service/common/file/utils'; +import { tmpFileDirPath } from '@fastgpt/service/common/file/constants'; /** * connect MongoDB and init data @@ -32,6 +34,9 @@ export function connectToDatabase(): Promise { // start queue startTrainingQueue(true); + + // clear tmp files + clearDirFiles(tmpFileDirPath); } }); } diff --git a/projects/app/src/web/common/api/fetch.ts b/projects/app/src/web/common/api/fetch.ts index de0ee2d77..aab9ff7cf 100644 --- a/projects/app/src/web/common/api/fetch.ts +++ b/projects/app/src/web/common/api/fetch.ts @@ -23,6 +23,8 @@ type StreamResponseType = { responseText: string; [DispatchNodeResponseKeyEnum.nodeResponse]: ChatHistoryItemResType[]; }; +class FatalError extends Error {} + export const streamFetch = ({ url = '/api/v1/chat/completions', data, @@ -206,9 +208,12 @@ export const streamFetch = ({ onclose() { finished = true; }, - onerror(e) { + onerror(err) { + if (err instanceof FatalError) { + throw err; + } clearTimeout(timeoutId); - failedFinish(getErrText(e)); + failedFinish(getErrText(err)); }, openWhenHidden: true }); diff --git a/projects/app/src/web/core/chat/utils.ts b/projects/app/src/web/core/chat/utils.ts index 164c0d409..e18e4188d 100644 --- a/projects/app/src/web/core/chat/utils.ts +++ b/projects/app/src/web/core/chat/utils.ts @@ -15,7 +15,10 @@ export function checkChatSupportSelectFileByChatModels(models: string[] = []) { } export function checkChatSupportSelectFileByModules(modules: ModuleItemType[] = []) { - const chatModules = modules.filter((item) => item.flowType === FlowNodeTypeEnum.chatNode); + const chatModules = modules.filter( + (item) => + item.flowType === FlowNodeTypeEnum.chatNode || item.flowType === FlowNodeTypeEnum.tools + ); const models: string[] = chatModules.map( (item) => item.inputs.find((item) => item.key === 'model')?.value || '' ); diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh index 5c2243b75..0f55eeaee 100755 --- a/scripts/postinstall.sh +++ b/scripts/postinstall.sh @@ -1,2 +1,6 @@ +# 创建临时文件目录 +mkdir projects/app/tmp +# 初始化UI库的自定义ts类型 pnpm run gen:theme-typings -cd worker && pnpm i --ignore-workspace \ No newline at end of file +# 安装 worker 里的依赖 +cd worker && pnpm i --ignore-workspace