diff --git a/.github/workflows/docs-deploy-vercel.yml b/.github/workflows/docs-deploy-vercel.yml index 42a83b8abcb0..50e9e99cfafa 100644 --- a/.github/workflows/docs-deploy-vercel.yml +++ b/.github/workflows/docs-deploy-vercel.yml @@ -58,7 +58,7 @@ jobs: # Step 4 - Builds the site using Hugo - name: Build - run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify + run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e” && hugo -v --minify # Step 5 - Push our generated site to Vercel - name: Deploy to Vercel diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index c4c0a28e23d2..b42b29c0aa2d 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -58,7 +58,7 @@ jobs: # Step 4 - Builds the site using Hugo - name: Build - run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify + run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e” && hugo -v --minify # Step 5 - Push our generated site to Vercel - name: Deploy to Vercel diff --git a/docSite/Dockerfile b/docSite/Dockerfile index ca7417d6448e..37f095d1c49d 100644 --- a/docSite/Dockerfile +++ b/docSite/Dockerfile @@ -3,7 +3,7 @@ FROM hugomods/hugo:0.117.0 AS builder WORKDIR /app ADD ./docSite hugo -RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify +RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e” && hugo -v --minify FROM fholzer/nginx-brotli:latest diff --git a/docSite/assets/imgs/image-100.png b/docSite/assets/imgs/image-100.png new file mode 100644 index 000000000000..2fcd4c06ad61 Binary files /dev/null and b/docSite/assets/imgs/image-100.png differ diff --git a/docSite/assets/imgs/image-101.png b/docSite/assets/imgs/image-101.png new file mode 100644 index 000000000000..c1648a4ea37c Binary files /dev/null and b/docSite/assets/imgs/image-101.png differ diff --git a/docSite/assets/imgs/image-102.png b/docSite/assets/imgs/image-102.png new file mode 100644 index 000000000000..27f0131ab9dd Binary files /dev/null and b/docSite/assets/imgs/image-102.png differ diff --git a/docSite/assets/imgs/image-103.png b/docSite/assets/imgs/image-103.png new file mode 100644 index 000000000000..039194024a35 Binary files /dev/null and b/docSite/assets/imgs/image-103.png differ diff --git a/docSite/assets/imgs/image-104.png b/docSite/assets/imgs/image-104.png new file mode 100644 index 000000000000..7f09448b14f1 Binary files /dev/null and b/docSite/assets/imgs/image-104.png differ diff --git a/docSite/assets/imgs/image-105.png b/docSite/assets/imgs/image-105.png new file mode 100644 index 000000000000..527ddab8565a Binary files /dev/null and b/docSite/assets/imgs/image-105.png differ diff --git a/docSite/assets/imgs/image-106.png b/docSite/assets/imgs/image-106.png new file mode 100644 index 000000000000..20adabc94283 Binary files /dev/null and b/docSite/assets/imgs/image-106.png differ diff --git a/docSite/assets/imgs/image-107.png b/docSite/assets/imgs/image-107.png new file mode 100644 index 000000000000..378c9cb52cb4 Binary files /dev/null and b/docSite/assets/imgs/image-107.png differ diff --git a/docSite/assets/imgs/image-88.png b/docSite/assets/imgs/image-88.png new file mode 100644 index 000000000000..03b5def59d3f Binary files /dev/null and b/docSite/assets/imgs/image-88.png differ diff --git a/docSite/assets/imgs/image-89.png b/docSite/assets/imgs/image-89.png new file mode 100644 index 000000000000..3bbd87bc478c Binary files /dev/null and b/docSite/assets/imgs/image-89.png differ diff --git a/docSite/assets/imgs/image-90.png b/docSite/assets/imgs/image-90.png new file mode 100644 index 000000000000..6ff40e2b50d6 Binary files /dev/null and b/docSite/assets/imgs/image-90.png differ diff --git a/docSite/assets/imgs/image-91.png b/docSite/assets/imgs/image-91.png new file mode 100644 index 000000000000..25fc67b92569 Binary files /dev/null and b/docSite/assets/imgs/image-91.png differ diff --git a/docSite/assets/imgs/image-92.png b/docSite/assets/imgs/image-92.png new file mode 100644 index 000000000000..7864734115eb Binary files /dev/null and b/docSite/assets/imgs/image-92.png differ diff --git a/docSite/assets/imgs/image-93.png b/docSite/assets/imgs/image-93.png new file mode 100644 index 000000000000..b87ef9bb386e Binary files /dev/null and b/docSite/assets/imgs/image-93.png differ diff --git a/docSite/assets/imgs/image-94.png b/docSite/assets/imgs/image-94.png new file mode 100644 index 000000000000..20c2b714d1d6 Binary files /dev/null and b/docSite/assets/imgs/image-94.png differ diff --git a/docSite/assets/imgs/image-95.png b/docSite/assets/imgs/image-95.png new file mode 100644 index 000000000000..1ef65ca8bbef Binary files /dev/null and b/docSite/assets/imgs/image-95.png differ diff --git a/docSite/assets/imgs/image-96.png b/docSite/assets/imgs/image-96.png new file mode 100644 index 000000000000..3ddbc9c48dd9 Binary files /dev/null and b/docSite/assets/imgs/image-96.png differ diff --git a/docSite/assets/imgs/image-97.png b/docSite/assets/imgs/image-97.png new file mode 100644 index 000000000000..f376836b3f7a Binary files /dev/null and b/docSite/assets/imgs/image-97.png differ diff --git a/docSite/assets/imgs/image-98.png b/docSite/assets/imgs/image-98.png new file mode 100644 index 000000000000..c97f5d85ee1b Binary files /dev/null and b/docSite/assets/imgs/image-98.png differ diff --git a/docSite/assets/imgs/image-99.png b/docSite/assets/imgs/image-99.png new file mode 100644 index 000000000000..5d4abc5d82b0 Binary files /dev/null and b/docSite/assets/imgs/image-99.png differ diff --git a/docSite/content/zh-cn/docs/development/configuration.md b/docSite/content/zh-cn/docs/development/configuration.md index e65315f4e40a..8cb5cbba0f37 100644 --- a/docSite/content/zh-cn/docs/development/configuration.md +++ b/docSite/content/zh-cn/docs/development/configuration.md @@ -25,251 +25,6 @@ weight: 707 "qaMaxProcess": 15, // 问答拆分线程数量 "tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。 "pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。 - }, - "llmModels": [ - { - "provider": "OpenAI", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other - "model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名) - "name": "gpt-4o-mini", // 模型别名 - "maxContext": 125000, // 最大上下文 - "maxResponse": 16000, // 最大回复 - "quoteMaxToken": 120000, // 最大引用内容 - "maxTemperature": 1.2, // 最大温度 - "charsPointsPrice": 0, // n积分/1k token(商业版) - "censor": false, // 是否开启敏感校验(商业版) - "vision": true, // 是否支持图片输入 - "datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错 - "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) - "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) - "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) - "usedInQueryExtension": true, // 是否用于问题优化(务必保证至少有一个为true) - "toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。) - "functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice,如果为false,则使用 functionCall,如果仍为 false,则使用提示词模式) - "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 - "customExtractPrompt": "", // 自定义内容提取提示词 - "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 - "defaultConfig": {}, // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) - "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) - }, - { - "provider": "OpenAI", - "model": "gpt-4o", - "name": "gpt-4o", - "maxContext": 125000, - "maxResponse": 4000, - "quoteMaxToken": 120000, - "maxTemperature": 1.2, - "charsPointsPrice": 0, - "censor": false, - "vision": true, - "datasetProcess": true, - "usedInClassify": true, - "usedInExtractFields": true, - "usedInToolCall": true, - "usedInQueryExtension": true, - "toolChoice": true, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig": {}, - "fieldMap": {} - }, - { - "provider": "OpenAI", - "model": "o1-mini", - "name": "o1-mini", - "maxContext": 125000, - "maxResponse": 65000, - "quoteMaxToken": 120000, - "maxTemperature": 1.2, - "charsPointsPrice": 0, - "censor": false, - "vision": false, - "datasetProcess": true, - "usedInClassify": true, - "usedInExtractFields": true, - "usedInToolCall": true, - "usedInQueryExtension": true, - "toolChoice": false, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig": { - "temperature": 1, - "max_tokens": null, - "stream": false - } - }, - { - "provider": "OpenAI", - "model": "o1-preview", - "name": "o1-preview", - "maxContext": 125000, - "maxResponse": 32000, - "quoteMaxToken": 120000, - "maxTemperature": 1.2, - "charsPointsPrice": 0, - "censor": false, - "vision": false, - "datasetProcess": true, - "usedInClassify": true, - "usedInExtractFields": true, - "usedInToolCall": true, - "usedInQueryExtension": true, - "toolChoice": false, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig": { - "temperature": 1, - "max_tokens": null, - "stream": false - } - } - ], - "vectorModels": [ - { - "provider": "OpenAI", - "model": "text-embedding-3-small", - "name": "text-embedding-3-small", - "charsPointsPrice": 0, - "defaultToken": 512, - "maxToken": 3000, - "weight": 100 - }, - { - "provider": "OpenAI", - "model": "text-embedding-3-large", - "name": "text-embedding-3-large", - "charsPointsPrice": 0, - "defaultToken": 512, - "maxToken": 3000, - "weight": 100, - "defaultConfig": { - "dimensions": 1024 - } - }, - { - "provider": "OpenAI", - "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) - "name": "Embedding-2", // 模型展示名 - "charsPointsPrice": 0, // n积分/1k token - "defaultToken": 700, // 默认文本分割时候的 token - "maxToken": 3000, // 最大 token - "weight": 100, // 优先训练权重 - "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) - "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) - "queryConfig": {} // 参训时的额外参数 - } - ], - "reRankModels": [], - "audioSpeechModels": [ - { - "provider": "OpenAI", - "model": "tts-1", - "name": "OpenAI TTS1", - "charsPointsPrice": 0, - "voices": [ - { "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" }, - { "label": "Echo", "value": "echo", "bufferId": "openai-Echo" }, - { "label": "Fable", "value": "fable", "bufferId": "openai-Fable" }, - { "label": "Onyx", "value": "onyx", "bufferId": "openai-Onyx" }, - { "label": "Nova", "value": "nova", "bufferId": "openai-Nova" }, - { "label": "Shimmer", "value": "shimmer", "bufferId": "openai-Shimmer" } - ] - } - ], - "whisperModel": { - "provider": "OpenAI", - "model": "whisper-1", - "name": "Whisper1", - "charsPointsPrice": 0 } } -``` - -## 内置的模型提供商ID - -为了方便模型分类展示,FastGPT 内置了部分模型提供商的名字和 Logo。如果你期望补充提供商,可[提交 Issue](https://github.com/labring/FastGPT/issues),并提供几个信息: - -1. 厂商官网地址 -2. 厂商 SVG logo,建议是正方形图片。 - -目前已支持的提供商, 复制 "-" 之前的字符串,作为 provider 的值。 - -- OpenAI -- Claude -- Gemini -- Meta -- MistralAI -- AliCloud - 阿里云 -- Qwen - 通义千问 -- Doubao - 豆包 -- ChatGLM - 智谱 -- DeepSeek - 深度求索 -- Moonshot - 月之暗面 -- MiniMax -- SparkDesk - 讯飞星火 -- Hunyuan - 腾讯混元 -- Baichuan - 百川 -- Yi - 零一万物 -- Ernie - 文心一言 -- StepFun - 阶跃星辰 -- Ollama -- BAAI - 智源研究院 -- FishAudio -- Intern - 书生 -- Moka - Moka-AI -- Other - 其他 - - -## ReRank 模型接入 - -由于 OneAPI 不支持 Rerank 模型,所以需要单独配置接入,这里 - - -### 使用硅基流动的在线模型 - -有免费的 `bge-reranker-v2-m3` 模型可以使用。 - -1. [点击注册硅基流动账号](https://cloud.siliconflow.cn/i/TR9Ym0c4) -2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak -3. 修改 FastGPT 配置文件 - -```json -{ - "reRankModels": [ - { - "model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名 - "name": "BAAI/bge-reranker-v2-m3", - "requestUrl": "https://api.siliconflow.cn/v1/rerank", - "requestAuth": "siliconflow 上申请的 key" - } - ] -} -``` - -### 私有部署模型 - -请使用 4.6.6-alpha 以上版本,配置文件中的 `reRankModels` 为重排模型,虽然是数组,不过目前仅有第1个生效。 - -1. [部署 ReRank 模型](/docs/development/custom-models/bge-rerank/) -1. 找到 FastGPT 的配置文件中的 `reRankModels`, 4.6.6 以前是 `ReRankModels`。 -2. 修改对应的值: - -```json -{ - "reRankModels": [ - { - "model": "bge-reranker-base", // 随意 - "name": "检索重排-base", // 随意 - "charsPointsPrice": 0, - "requestUrl": "{{host}}/v1/rerank", - "requestAuth": "安全凭证,已自动补 Bearer" - } - ] -} -``` +``` \ No newline at end of file diff --git a/docSite/content/zh-cn/docs/development/custom-models/bge-rerank.md b/docSite/content/zh-cn/docs/development/custom-models/bge-rerank.md index c6ae7fd11b88..ef1f27ac795c 100644 --- a/docSite/content/zh-cn/docs/development/custom-models/bge-rerank.md +++ b/docSite/content/zh-cn/docs/development/custom-models/bge-rerank.md @@ -118,10 +118,17 @@ services: ``` ## 接入 FastGPT -参考 [ReRank模型接入](/docs/development/configuration/#rerank-接入),host 变量为部署的域名。 +1. 打开 FastGPT 模型配置,新增一个重排模型。 +2. 填写模型配置表单:模型 ID 为`bge-reranker-base`,地址填写`{{host}}/v1/rerank`,host 为你部署的域名/IP:Port。 + +![alt text](/imgs/image-102.png) ## QA +### 403报错 + +FastGPT中,自定义请求 Token 和环境变量的 ACCESS_TOKEN 不一致。 + ### Docker 运行提示 `Bus error (core dumped)` 尝试增加 `docker-compose.yml` 配置项 `shm_size` ,以增加容器中的共享内存目录大小。 diff --git a/docSite/content/zh-cn/docs/development/custom-models/xinference.md b/docSite/content/zh-cn/docs/development/custom-models/xinference.md index a76fbdf31c21..19441dba27e8 100644 --- a/docSite/content/zh-cn/docs/development/custom-models/xinference.md +++ b/docSite/content/zh-cn/docs/development/custom-models/xinference.md @@ -144,7 +144,6 @@ curl --location --request POST 'https:///v1/chat/completions' \ "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) - "usedInQueryExtension": true, // 是否用于问题优化(务必保证至少有一个为true) "toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。) "functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice,如果为false,则使用 functionCall,如果仍为 false,则使用提示词模式) "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 diff --git a/docSite/content/zh-cn/docs/development/docker.md b/docSite/content/zh-cn/docs/development/docker.md index e438d1655086..7f9274151e86 100644 --- a/docSite/content/zh-cn/docs/development/docker.md +++ b/docSite/content/zh-cn/docs/development/docker.md @@ -7,6 +7,13 @@ toc: true weight: 707 --- +## 前置知识 + +1. 基础的网络知识:端口,防火墙…… +2. Docker 和 Docker Compose 基础知识 +3. 大模型相关接口和参数 +4. RAG 相关知识:向量模型,向量数据库,向量检索 + ## 部署架构图 ![](/imgs/sealos-fastgpt.webp) @@ -202,6 +209,10 @@ docker restart oneapi 首次运行,会自动初始化 root 用户,密码为 `1234`(与环境变量中的`DEFAULT_ROOT_PSW`一致),日志里会提示一次`MongoServerError: Unable to read from a snapshot due to pending collection catalog changes;`可忽略。 +### 6. 配置模型 + +[点击查看模型配置教程](/docs/development/modelConfig/intro/) + ## FAQ ### Mongo 副本集自动初始化失败 diff --git a/docSite/content/zh-cn/docs/development/faq.md b/docSite/content/zh-cn/docs/development/faq.md index a2e747f0b368..9d37d77508ae 100644 --- a/docSite/content/zh-cn/docs/development/faq.md +++ b/docSite/content/zh-cn/docs/development/faq.md @@ -23,11 +23,11 @@ images: [] ![](/imgs/faq1.png) 这是索引模型的长度限制,通过任何方式部署都一样的,但不同索引模型的配置不一样,可以在后台修改参数。 -### sealos怎么挂载 小程序配置文件 +### 怎么挂载小程序配置文件 -新增配置文件:/app/projects/app/public/xxxx.txt +将验证文件,挂载到指定位置:/app/projects/app/public/xxxx.txt -如图: +然后重启。例如: ![](/imgs/faq2.png) diff --git a/docSite/content/zh-cn/docs/development/modelConfig/intro.md b/docSite/content/zh-cn/docs/development/modelConfig/intro.md new file mode 100644 index 000000000000..acd417ae518f --- /dev/null +++ b/docSite/content/zh-cn/docs/development/modelConfig/intro.md @@ -0,0 +1,442 @@ +--- +title: 'FastGPT 模型配置说明' +description: 'FastGPT 模型配置说明' +icon: 'api' +draft: false +toc: true +weight: 744 +--- + +在 4.8.20 版本以前,FastGPT 模型配置在 `config.json` 文件中声明,你可以在 https://github.com/labring/FastGPT/blob/main/projects/app/data/model.json 中找到旧版的配置文件示例。 + +从 4.8.20 版本开始,你可以直接在 FastGPT 页面中进行模型配置,并且系统内置了大量模型,无需从 0 开始配置。下面介绍模型配置的基本流程: + +## 1. 使用 OneAPI 对接模型提供商 + +可以使用 [OneAPI 接入教程](/docs/development/modelconfig/one-api) 来进行模型聚合,从而可以对接更多模型提供商。你需要先在各服务商申请好 API 接入 OneAPI 后,才能在 FastGPT 中使用这些模型。示例流程如下: + +![alt text](/imgs/image-95.png) + +除了各模型官方的服务外,还有一些第三方服务商提供模型接入服务,当然你也可以用 Ollama 等来部署本地模型,最终都需要接入 OneAPI,下面是一些第三方服务商: + +{{% alert icon=" " context="info" %}} +- [SiliconCloud(硅基流动)](https://cloud.siliconflow.cn/i/TR9Ym0c4): 提供开源模型调用的平台。 +- [Sealos AIProxy](https://hzh.sealos.run/?openapp=system-aiproxy): 提供国内各家模型代理,无需逐一申请 api。 +{{% /alert %}} + +在 OneAPI 配置好模型后,你就可以打开 FastGPT 页面,启用对应模型了。 + +## 2. 登录 root 用户 + +仅 root 用户可以进行模型配置。 + +## 3. 进入模型配置页面 + +登录 root 用户后,在`账号-模型提供商-模型配置`中,你可以看到所有内置的模型和自定义模型,以及哪些模型启用了。 + +![alt text](/image-90.png) + +## 4. 配置介绍 + +{{% alert icon="🤖 " context="success" %}} +注意:目前语音识别模型和重排模型仅会生效一个,所以配置时候,只需要配置一个即可。 +{{% /alert %}} + +### 核心配置 + +- 模型 ID:接口请求时候,Body 中`model`字段的值,全局唯一。 +- 自定义请求地址/Key:如果需要绕过`OneAPI`,可以设置自定义请求地址和 Token。一般情况下不需要,如果 OneAPI 不支持某些模型,可以使用该特性。 + +### 模型类型 + +1. 语言模型 - 进行文本对话,多模态模型支持图片识别。 +2. 索引模型 - 对文本块进行索引,用于相关文本检索。 +3. 语音合成 - 将文本转换为语音。 +4. 语音识别 - 将语音转换为文本。 +5. 重排模型 - 对文本进行重排,用于优化文本质量。 + +### 启用模型 + +系统内置了目前主流厂商的模型,如果你不熟悉配置,直接点击`启用`即可,需要注意到是,模型 ID 需要和 OneAPI 中渠道的`模型`一致。 + +| | | +| --- | --- | +| ![alt text](/imgs/image-91.png) | ![alt text](/imgs/image-92.png) | + +### 修改模型配置 + +点击模型右侧的齿轮即可进行模型配置,不同类型模型的配置有区别。 + +| | | +| --- | --- | +| ![alt text](/imgs/image-93.png) | ![alt text](/imgs/image-94.png) | + +### 新增自定义模型 + +如果系统内置的模型无法满足你的需求,你可以添加自定义模型。自定义模型中,如果`模型 ID`与系统内置的模型 ID 一致,则会被认为是修改系统模型。 + +| | | +| --- | --- | +| ![alt text](/imgs/image-96.png) | ![alt text](/imgs/image-97.png) | + +### 通过配置文件配置 + +如果你觉得通过页面配置模型比较麻烦,你也可以通过配置文件来配置模型。或者希望快速将一个系统的配置,复制到另一个系统,也可以通过配置文件来实现。 + +| | | +| --- | --- | +| ![alt text](/imgs/image-98.png) | ![alt text](/imgs/image-99.png) | + +**语言模型字段说明:** + +```json +{ + "model": "模型 ID", + "metadata": { + "isCustom": true, // 是否为自定义模型 + "isActive": true, // 是否启用 + "provider": "OpenAI", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other + "model": "gpt-4o-mini", // 模型ID(对应OneAPI中渠道的模型名) + "name": "gpt-4o-mini", // 模型别名 + "maxContext": 125000, // 最大上下文 + "maxResponse": 16000, // 最大回复 + "quoteMaxToken": 120000, // 最大引用内容 + "maxTemperature": 1.2, // 最大温度 + "charsPointsPrice": 0, // n积分/1k token(商业版) + "censor": false, // 是否开启敏感校验(商业版) + "vision": true, // 是否支持图片输入 + "datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错 + "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) + "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) + "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) + "toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。) + "functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice,如果为false,则使用 functionCall,如果仍为 false,则使用提示词模式) + "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 + "customExtractPrompt": "", // 自定义内容提取提示词 + "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 + "defaultConfig": {}, // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) + "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) + } +} +``` + +**索引模型字段说明:** + +```json +{ + "model": "模型 ID", + "metadata": { + "isCustom": true, // 是否为自定义模型 + "isActive": true, // 是否启用 + "provider": "OpenAI", // 模型提供商 + "model": "text-embedding-3-small", // 模型ID + "name": "text-embedding-3-small", // 模型别名 + "charsPointsPrice": 0, // n积分/1k token + "defaultToken": 512, // 默认文本分割时候的 token + "maxToken": 3000 // 最大 token + } +} +``` + +**重排模型字段说明:** + +```json +{ + "model": "模型 ID", + "metadata": { + "isCustom": true, // 是否为自定义模型 + "isActive": true, // 是否启用 + "provider": "BAAI", // 模型提供商 + "model": "bge-reranker-v2-m3", // 模型ID + "name": "ReRanker-Base", // 模型别名 + "requestUrl": "", // 自定义请求地址 + "requestAuth": "", // 自定义请求认证 + "type": "rerank" // 模型类型 + } +} +``` + +**语音合成模型字段说明:** + +```json +{ + "model": "模型 ID", + "metadata": { + "isActive": true, // 是否启用 + "isCustom": true, // 是否为自定义模型 + "type": "tts", // 模型类型 + "provider": "FishAudio", // 模型提供商 + "model": "fishaudio/fish-speech-1.5", // 模型ID + "name": "fish-speech-1.5", // 模型别名 + "voices": [ // 音色 + { + "label": "fish-alex", // 音色名称 + "value": "fishaudio/fish-speech-1.5:alex", // 音色ID + }, + { + "label": "fish-anna", // 音色名称 + "value": "fishaudio/fish-speech-1.5:anna", // 音色ID + } + ], + "charsPointsPrice": 0 // n积分/1k token + } +} +``` + +**语音识别模型字段说明:** + +```json +{ + "model": "whisper-1", + "metadata": { + "isActive": true, // 是否启用 + "isCustom": true, // 是否为自定义模型 + "provider": "OpenAI", // 模型提供商 + "model": "whisper-1", // 模型ID + "name": "whisper-1", // 模型别名 + "charsPointsPrice": 0, // n积分/1k token + "type": "stt" // 模型类型 + } +} +``` + +## 模型测试 + +FastGPT 页面上提供了每类模型的简单测试,可以初步检查模型是否正常工作,会实际按模板发送一个请求。 + +![alt text](/imgs/image-105.png) + +## 特殊接入示例 + +### ReRank 模型接入 + +由于 OneAPI 不支持 Rerank 模型,所以需要单独配置。FastGPT 中,模型配置支持自定义请求地址,可以绕过 OneAPI,直接向提供商发起请求,可以利用这个特性来接入 Rerank 模型。 + + +#### 使用硅基流动的在线模型 + +有免费的 `bge-reranker-v2-m3` 模型可以使用。 + +1. [点击注册硅基流动账号](https://cloud.siliconflow.cn/i/TR9Ym0c4) +2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak +3. 打开 FastGPT 模型配置,新增一个`BAAI/bge-reranker-v2-m3`的重排模型(如果系统内置了,也可以直接变更,无需新增)。 + +![alt text](/imgs/image-101.png) + +#### 私有部署模型 + +[点击查看部署 ReRank 模型教程](/docs/development/custom-models/bge-rerank/) + +### 接入语音识别模型 + +OneAPI 的语言识别接口,无法正确的识别其他模型(会始终识别成 whisper-1),所以如果想接入其他模型,可以通过自定义请求地址来实现。例如,接入硅基流动的 `FunAudioLLM/SenseVoiceSmall` 模型,可以参考如下配置: + +点击模型编辑: + +![alt text](/imgs/image-106.png) + +填写硅基流动的地址:`https://api.siliconflow.cn/v1/audio/transcriptions`,并填写硅基流动的 API Key。 + +![alt text](/imgs/image-107.png) + +## 其他配置项说明 + +### 自定义请求地址 + +如果填写了该值,则可以允许你绕过 OneAPI,直接向自定义请求地址发起请求。需要填写完整的请求地址,例如: + +- LLM: {{host}}/v1/chat/completions +- Embedding: {{host}}/v1/embeddings +- STT: {{host}}/v1/audio/transcriptions +- TTS: {{host}}/v1/audio/speech +- Rerank: {{host}}/v1/rerank + +自定义请求 Key,则是向自定义请求地址发起请求时候,携带请求头:Authorization: Bearer xxx 进行请求。 + +所有接口均遵循 OpenAI 提供的模型格式,可参考 [OpenAI API 文档](https://platform.openai.com/docs/api-reference/introduction) 进行配置。 + +由于 OpenAI 没有提供 ReRank 模型,遵循的是 Cohere 的格式。[点击查看接口请求示例](/docs/development/faq/#如何检查模型问题) + + +## 旧版模型配置说明 + +配置好 OneAPI 后,需要在`config.json`文件中,手动的增加模型配置,并重启。 + +由于环境变量不利于配置复杂的内容,FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `projects/app/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/development/docker/) 来挂载配置文件。 + +**开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。 +**Docker部署**,修改`config.json` 文件,需要重启容器。 + +下面配置文件示例中包含了系统参数和各个模型配置: + +```json +{ + "feConfigs": { + "lafEnv": "https://laf.dev" // laf环境。 https://laf.run (杭州阿里云) ,或者私有化的laf环境。如果使用 Laf openapi 功能,需要最新版的 laf 。 + }, + "systemEnv": { + "vectorMaxProcess": 15, // 向量处理线程数量 + "qaMaxProcess": 15, // 问答拆分线程数量 + "tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。 + "pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。 + }, + "llmModels": [ + { + "provider": "OpenAI", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other + "model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名) + "name": "gpt-4o-mini", // 模型别名 + "maxContext": 125000, // 最大上下文 + "maxResponse": 16000, // 最大回复 + "quoteMaxToken": 120000, // 最大引用内容 + "maxTemperature": 1.2, // 最大温度 + "charsPointsPrice": 0, // n积分/1k token(商业版) + "censor": false, // 是否开启敏感校验(商业版) + "vision": true, // 是否支持图片输入 + "datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错 + "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) + "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) + "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) + "toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。) + "functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice,如果为false,则使用 functionCall,如果仍为 false,则使用提示词模式) + "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 + "customExtractPrompt": "", // 自定义内容提取提示词 + "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 + "defaultConfig": {}, // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) + "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) + }, + { + "provider": "OpenAI", + "model": "gpt-4o", + "name": "gpt-4o", + "maxContext": 125000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 1.2, + "charsPointsPrice": 0, + "censor": false, + "vision": true, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "toolChoice": true, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "defaultConfig": {}, + "fieldMap": {} + }, + { + "provider": "OpenAI", + "model": "o1-mini", + "name": "o1-mini", + "maxContext": 125000, + "maxResponse": 65000, + "quoteMaxToken": 120000, + "maxTemperature": 1.2, + "charsPointsPrice": 0, + "censor": false, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "defaultConfig": { + "temperature": 1, + "max_tokens": null, + "stream": false + } + }, + { + "provider": "OpenAI", + "model": "o1-preview", + "name": "o1-preview", + "maxContext": 125000, + "maxResponse": 32000, + "quoteMaxToken": 120000, + "maxTemperature": 1.2, + "charsPointsPrice": 0, + "censor": false, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "defaultConfig": { + "temperature": 1, + "max_tokens": null, + "stream": false + } + } + ], + "vectorModels": [ + { + "provider": "OpenAI", + "model": "text-embedding-3-small", + "name": "text-embedding-3-small", + "charsPointsPrice": 0, + "defaultToken": 512, + "maxToken": 3000, + "weight": 100 + }, + { + "provider": "OpenAI", + "model": "text-embedding-3-large", + "name": "text-embedding-3-large", + "charsPointsPrice": 0, + "defaultToken": 512, + "maxToken": 3000, + "weight": 100, + "defaultConfig": { + "dimensions": 1024 + } + }, + { + "provider": "OpenAI", + "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) + "name": "Embedding-2", // 模型展示名 + "charsPointsPrice": 0, // n积分/1k token + "defaultToken": 700, // 默认文本分割时候的 token + "maxToken": 3000, // 最大 token + "weight": 100, // 优先训练权重 + "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) + "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) + "queryConfig": {} // 参训时的额外参数 + } + ], + "reRankModels": [], + "audioSpeechModels": [ + { + "provider": "OpenAI", + "model": "tts-1", + "name": "OpenAI TTS1", + "charsPointsPrice": 0, + "voices": [ + { "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" }, + { "label": "Echo", "value": "echo", "bufferId": "openai-Echo" }, + { "label": "Fable", "value": "fable", "bufferId": "openai-Fable" }, + { "label": "Onyx", "value": "onyx", "bufferId": "openai-Onyx" }, + { "label": "Nova", "value": "nova", "bufferId": "openai-Nova" }, + { "label": "Shimmer", "value": "shimmer", "bufferId": "openai-Shimmer" } + ] + } + ], + "whisperModel": { + "provider": "OpenAI", + "model": "whisper-1", + "name": "Whisper1", + "charsPointsPrice": 0 + } +} +``` \ No newline at end of file diff --git a/docSite/content/zh-cn/docs/development/modelConfig/one-api.md b/docSite/content/zh-cn/docs/development/modelConfig/one-api.md index 5a0f74284246..537e90067c0a 100644 --- a/docSite/content/zh-cn/docs/development/modelConfig/one-api.md +++ b/docSite/content/zh-cn/docs/development/modelConfig/one-api.md @@ -94,70 +94,16 @@ CHAT_API_KEY=sk-xxxxxx ![](/imgs/oneapi-demo1.png) -### 2. 修改 FastGPT 配置文件 - -可以在 `/projects/app/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json),按下面内容修改配置文件,最新/更具体的配置说明,可查看[FastGPT 配置文件说明](/docs/development/configuration)。 - -配置模型关键点在于`model` 需要与 OneAPI 渠道中的模型一致。 - -```json -{ - "llmModels": [ // 语言模型配置 - { - "model": "ERNIE-Bot", // 这里的模型需要对应 One API 的模型 - "name": "文心一言", // 对外展示的名称 - "avatar": "/imgs/model/openai.svg", // 模型的logo - "maxContext": 16000, // 最大上下文 - "maxResponse": 4000, // 最大回复 - "quoteMaxToken": 13000, // 最大引用内容 - "maxTemperature": 1.2, // 最大温度 - "charsPointsPrice": 0, - "censor": false, - "vision": false, // 是否支持图片输入 - "datasetProcess": true, // 是否设置为知识库处理模型 - "usedInClassify": true, // 是否用于问题分类 - "usedInExtractFields": true, // 是否用于字段提取 - "usedInToolCall": true, // 是否用于工具调用 - "usedInQueryExtension": true, // 是否用于问题优化 - "toolChoice": true, // 是否支持工具选择 - "functionCall": false, // 是否支持函数调用 - "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 - "customExtractPrompt": "", // 自定义内容提取提示词 - "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 - "defaultConfig":{} // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) - } - ], - "vectorModels": [ // 向量模型配置 - { - "model": "text-embedding-ada-002", - "name": "Embedding-2", - "avatar": "/imgs/model/openai.svg", - "charsPointsPrice": 0, - "defaultToken": 700, - "maxToken": 3000, - "weight": 100 - }, - ] -} -``` - -### 3. 重启 FastGPT - -**Docker 版本** - -```bash -docker-compose down -docker-compose up -d -``` +### 2. 修改 FastGPT 模型配置 -**Sealos 版本** +打开 FastGPT 模型配置,启动文心千帆模型,如果希望未内置,可以通过新增模型来配置。 -直接找到 FastGPT 服务,点击重启即可。 +![alt text](/imgs/image-103.png) ## 其他服务商接入参考 -这章介绍一些提供商接入 OneAPI 的教程,配置后不要忘记修改 FastGPT 配置文件。 +这章介绍一些提供商接入 OneAPI 的教程,配置后不要忘记在 FastGPT 模型配置中启用。 ### 阿里通义千问 diff --git a/docSite/content/zh-cn/docs/development/modelConfig/siliconCloud.md b/docSite/content/zh-cn/docs/development/modelConfig/siliconCloud.md index df4cd67ed1c9..06036deb3adf 100644 --- a/docSite/content/zh-cn/docs/development/modelConfig/siliconCloud.md +++ b/docSite/content/zh-cn/docs/development/modelConfig/siliconCloud.md @@ -27,139 +27,13 @@ OPENAI_BASE_URL=https://api.siliconflow.cn/v1 CHAT_API_KEY=sk-xxxxxx ``` -## 3. 修改 FastGPT 配置文件 - -我们选取 SiliconCloud 中的模型作为 FastGPT 配置。这里配置了 `Qwen2.5 72b` 的纯语言和视觉模型;选择 `bge-m3` 作为向量模型;选择 `bge-reranker-v2-m3` 作为重排模型。选择 `fish-speech-1.5` 作为语音模型;选择 `SenseVoiceSmall` 作为语音输入模型。 - -注意:ReRank 模型仍需配置一次 Api Key - -```json -{ - "llmModels": [ - { - "provider": "Other", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other - "model": "Qwen/Qwen2.5-72B-Instruct", // 模型名(对应OneAPI中渠道的模型名) - "name": "Qwen2.5-72B-Instruct", // 模型别名 - "maxContext": 32000, // 最大上下文 - "maxResponse": 4000, // 最大回复 - "quoteMaxToken": 30000, // 最大引用内容 - "maxTemperature": 1, // 最大温度 - "charsPointsPrice": 0, // n积分/1k token(商业版) - "censor": false, // 是否开启敏感校验(商业版) - "vision": false, // 是否支持图片输入 - "datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错 - "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) - "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) - "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) - "usedInQueryExtension": true, // 是否用于问题优化(务必保证至少有一个为true) - "toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。) - "functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice,如果为false,则使用 functionCall,如果仍为 false,则使用提示词模式) - "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 - "customExtractPrompt": "", // 自定义内容提取提示词 - "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 - "defaultConfig": {}, // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) - "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) - }, - { - "provider": "Other", - "model": "Qwen/Qwen2-VL-72B-Instruct", - "name": "Qwen2-VL-72B-Instruct", - "maxContext": 32000, - "maxResponse": 4000, - "quoteMaxToken": 30000, - "maxTemperature": 1, - "charsPointsPrice": 0, - "censor": false, - "vision": true, - "datasetProcess": false, - "usedInClassify": false, - "usedInExtractFields": false, - "usedInToolCall": false, - "usedInQueryExtension": false, - "toolChoice": false, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig": {} - } - ], - "vectorModels": [ - { - "provider": "Other", - "model": "Pro/BAAI/bge-m3", - "name": "Pro/BAAI/bge-m3", - "charsPointsPrice": 0, - "defaultToken": 512, - "maxToken": 5000, - "weight": 100 - } - ], - "reRankModels": [ - { - "model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名 - "name": "BAAI/bge-reranker-v2-m3", - "requestUrl": "https://api.siliconflow.cn/v1/rerank", - "requestAuth": "siliconflow 上申请的 key" - } - ], - "audioSpeechModels": [ - { - "model": "fishaudio/fish-speech-1.5", - "name": "fish-speech-1.5", - "voices": [ - { - "label": "fish-alex", - "value": "fishaudio/fish-speech-1.5:alex", - "bufferId": "fish-alex" - }, - { - "label": "fish-anna", - "value": "fishaudio/fish-speech-1.5:anna", - "bufferId": "fish-anna" - }, - { - "label": "fish-bella", - "value": "fishaudio/fish-speech-1.5:bella", - "bufferId": "fish-bella" - }, - { - "label": "fish-benjamin", - "value": "fishaudio/fish-speech-1.5:benjamin", - "bufferId": "fish-benjamin" - }, - { - "label": "fish-charles", - "value": "fishaudio/fish-speech-1.5:charles", - "bufferId": "fish-charles" - }, - { - "label": "fish-claire", - "value": "fishaudio/fish-speech-1.5:claire", - "bufferId": "fish-claire" - }, - { - "label": "fish-david", - "value": "fishaudio/fish-speech-1.5:david", - "bufferId": "fish-david" - }, - { - "label": "fish-diana", - "value": "fishaudio/fish-speech-1.5:diana", - "bufferId": "fish-diana" - } - ] - } - ], - "whisperModel": { - "model": "FunAudioLLM/SenseVoiceSmall", - "name": "SenseVoiceSmall", - "charsPointsPrice": 0 - } -} -``` +## 3. 修改 FastGPT 模型配置 + +系统内置了几个硅基流动的模型进行体验,如果需要其他模型,可以手动添加。 + +这里启动了 `Qwen2.5 72b` 的纯语言和视觉模型;选择 `bge-m3` 作为向量模型;选择 `bge-reranker-v2-m3` 作为重排模型。选择 `fish-speech-1.5` 作为语音模型;选择 `SenseVoiceSmall` 作为语音输入模型。 -## 4. 重启 FastGPT +![alt text](/imgs/image-104.png) ## 5. 体验测试 diff --git a/docSite/content/zh-cn/docs/development/sealos.md b/docSite/content/zh-cn/docs/development/sealos.md index 9e4f25e84566..0a23e5ce76b1 100644 --- a/docSite/content/zh-cn/docs/development/sealos.md +++ b/docSite/content/zh-cn/docs/development/sealos.md @@ -34,7 +34,7 @@ FastGPT 使用了 one-api 项目来管理模型池,其可以兼容 OpenAI 、A Deploy on Sealos -### 开始部署 +### 1. 开始部署 由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。 @@ -52,27 +52,15 @@ FastGPT 使用了 one-api 项目来管理模型池,其可以兼容 OpenAI 、A ![](/imgs/sealos2.png) -### 登录 +### 2. 登录 用户名:`root` 密码是刚刚一键部署时设置的`root_password` -### 修改配置文件和环境变量 - -在 Sealos 中,你可以打开`应用管理`(App Launchpad)看到部署的 FastGPT,可以打开`数据库`(Database)看到对应的数据库。 +### 3. 配置模型 -在`应用管理`中,选中 FastGPT,点击变更,可以看到对应的环境变量和配置文件。 - -![](/imgs/fastgptonsealos1.png) - -{{% alert icon="🤖 " context="success" %}} -在 Sealos 上,FastGPT 一共运行了 1 个服务和 2 个数据库,如暂停和删除请注意数据库一同操作。(你可以白天启动,晚上暂停它们,省钱大法) -{{% /alert %}} - -### 更新 - -点击变更或重启会自动拉取镜像更新,请确保镜像`tag`正确。建议不要使用`latest`,改成固定版本号。 +[点击查看模型配置教程](/docs/development/modelConfig/intro/) ## 收费 @@ -88,7 +76,20 @@ FastGPT 商业版共包含了2个应用(fastgpt, fastgpt-plus)和2个数据 点击右侧的详情,可以查看对应应用的详细信息。 +### 修改配置文件和环境变量 + +在 Sealos 中,你可以打开`应用管理`(App Launchpad)看到部署的 FastGPT,可以打开`数据库`(Database)看到对应的数据库。 + +在`应用管理`中,选中 FastGPT,点击变更,可以看到对应的环境变量和配置文件。 + +![](/imgs/fastgptonsealos1.png) + +{{% alert icon="🤖 " context="success" %}} +在 Sealos 上,FastGPT 一共运行了 1 个服务和 2 个数据库,如暂停和删除请注意数据库一同操作。(你可以白天启动,晚上暂停它们,省钱大法) +{{% /alert %}} + ### 如何更新/升级 FastGPT + [升级脚本文档](https://doc.tryfastgpt.ai/docs/development/upgrading/)先看下文档,看下需要升级哪个版本。注意,不要跨版本升级!!!!! 例如,目前是4.5 版本,要升级到4.5.1,就先把镜像版本改成v4.5.1,执行一下升级脚本,等待完成后再继续升级。如果目标版本不需要执行初始化,则可以跳过。 @@ -148,8 +149,6 @@ SYSTEM_FAVICON 可以是一个网络地址 ![](/imgs/onsealos8.png) -### 管理后台(已合并到plus) - ### 商业版镜像配置文件 ``` diff --git a/docSite/content/zh-cn/docs/development/upgrading/4811.md b/docSite/content/zh-cn/docs/development/upgrading/4811.md index 548dfdccf87f..b6d3891e03c5 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4811.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4811.md @@ -31,7 +31,6 @@ weight: 813 "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, - "usedInQueryExtension": true, "toolChoice": false, "functionCall": false, "customCQPrompt": "", @@ -56,7 +55,6 @@ weight: 813 "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, - "usedInQueryExtension": true, "toolChoice": false, "functionCall": false, "customCQPrompt": "", diff --git a/docSite/content/zh-cn/docs/development/upgrading/4820.md b/docSite/content/zh-cn/docs/development/upgrading/4820.md new file mode 100644 index 000000000000..10e5e18ca591 --- /dev/null +++ b/docSite/content/zh-cn/docs/development/upgrading/4820.md @@ -0,0 +1,50 @@ +--- +title: 'V4.8.20(进行中)' +description: 'FastGPT V4.8.20 更新说明' +icon: 'upgrade' +draft: false +toc: true +weight: 804 +--- + +## 更新指南 + +### 1. 做好数据库备份 + +### 2. 更新环境变量 + +如果有很早版本用户,配置了`ONEAPI_URL`的,需要统一改成`OPENAI_BASE_URL` + +### 3. 更新镜像: + +- 更新 fastgpt 镜像 tag: v4.8.20 +- 更新 fastgpt-pro 商业版镜像 tag: v4.8.20 +- Sandbox 镜像无需更新 + +### 4. 运行升级脚本 + +从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成**FastGPT 域名**。 + +```bash +curl --location --request POST 'https://{{host}}/api/admin/initv4820' \ +--header 'rootkey: {{rootkey}}' \ +--header 'Content-Type: application/json' +``` + +脚本会自动把原配置文件的模型加载到新版模型配置中。 + +## 完整更新内容 + +1. 新增 - 可视化模型参数配置。预设超过 100 个模型配置。同时支持所有类型模型的一键测试。(预计下个版本会完全支持在页面上配置渠道)。 +2. 新增 - DeepSeek resoner 模型支持输出思考过程。 +3. 新增 - 使用记录导出和仪表盘。 +4. 新增 - markdown 语法扩展,支持音视频(代码块 audio 和 video)。 +5. 新增 - 调整 max_tokens 计算逻辑。优先保证 max_tokens 为配置值,如超出最大上下文,则减少历史记录。例如:如果申请 8000 的 max_tokens,则上下文长度会减少 8000。 +6. 优化 - 问题优化增加上下文过滤,避免超出上下文。 +7. 优化 - 页面组件抽离,减少页面组件路由。 +8. 优化 - 全文检索,忽略大小写。 +9. 优化 - 问答生成和增强索引改成流输出,避免部分模型超时。 +10. 优化 - 自动给 assistant 空 content,补充 null,同时合并连续的 text assistant,避免部分模型抛错。 +11. 优化 - 调整图片 Host, 取消上传时补充 FE_DOMAIN,改成发送对话前补充,避免替换域名后原图片无法正常使用。 +12. 修复 - 部分场景成员列表无法触底加载。 +13. 修复 - 工作流递归执行,部分条件下无法正常运行。 diff --git a/files/docker/docker-compose-milvus.yml b/files/docker/docker-compose-milvus.yml index e6d1ce279846..9313163e2ef9 100644 --- a/files/docker/docker-compose-milvus.yml +++ b/files/docker/docker-compose-milvus.yml @@ -114,15 +114,15 @@ services: # fastgpt sandbox: container_name: sandbox - image: ghcr.io/labring/fastgpt-sandbox:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt-sandbox:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.20 # 阿里云 networks: - fastgpt restart: always fastgpt: container_name: fastgpt - image: ghcr.io/labring/fastgpt:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.20 # 阿里云 ports: - 3000:3000 networks: diff --git a/files/docker/docker-compose-pgvector.yml b/files/docker/docker-compose-pgvector.yml index e8da9abe82db..d14cbe1e8824 100644 --- a/files/docker/docker-compose-pgvector.yml +++ b/files/docker/docker-compose-pgvector.yml @@ -72,15 +72,15 @@ services: # fastgpt sandbox: container_name: sandbox - image: ghcr.io/labring/fastgpt-sandbox:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt-sandbox:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.20 # 阿里云 networks: - fastgpt restart: always fastgpt: container_name: fastgpt - image: ghcr.io/labring/fastgpt:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.20 # 阿里云 ports: - 3000:3000 networks: diff --git a/files/docker/docker-compose-zilliz.yml b/files/docker/docker-compose-zilliz.yml index 6b53232e71b1..f30498b7890b 100644 --- a/files/docker/docker-compose-zilliz.yml +++ b/files/docker/docker-compose-zilliz.yml @@ -53,15 +53,15 @@ services: wait $$! sandbox: container_name: sandbox - image: ghcr.io/labring/fastgpt-sandbox:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt-sandbox:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.20 # 阿里云 networks: - fastgpt restart: always fastgpt: container_name: fastgpt - image: ghcr.io/labring/fastgpt:v4.8.17 # git - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.17 # 阿里云 + image: ghcr.io/labring/fastgpt:v4.8.20 # git + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.20 # 阿里云 ports: - 3000:3000 networks: diff --git a/files/helm/fastgpt/templates/configmap-config.yaml b/files/helm/fastgpt/templates/configmap-config.yaml index a0df084570e9..0aa7dcc900a6 100644 --- a/files/helm/fastgpt/templates/configmap-config.yaml +++ b/files/helm/fastgpt/templates/configmap-config.yaml @@ -23,7 +23,6 @@ data: "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, - "usedInQueryExtension": true, "toolChoice": true, "functionCall": false, "customCQPrompt": "", @@ -45,7 +44,6 @@ data: "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, - "usedInQueryExtension": true, "toolChoice": true, "functionCall": false, "customCQPrompt": "", @@ -67,7 +65,6 @@ data: "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, - "usedInQueryExtension": true, "toolChoice": true, "functionCall": false, "customCQPrompt": "", @@ -89,7 +86,6 @@ data: "usedInClassify": false, "usedInExtractFields": false, "usedInToolCall": false, - "usedInQueryExtension": false, "toolChoice": true, "functionCall": false, "customCQPrompt": "", diff --git a/packages/global/common/error/code/user.ts b/packages/global/common/error/code/user.ts index 98d8e9a0f996..337cc1ead990 100644 --- a/packages/global/common/error/code/user.ts +++ b/packages/global/common/error/code/user.ts @@ -2,12 +2,22 @@ import { ErrType } from '../errorCode'; import { i18nT } from '../../../../web/i18n/utils'; /* team: 503000 */ export enum UserErrEnum { + notUser = 'notUser', + userExist = 'userExist', unAuthRole = 'unAuthRole', account_psw_error = 'account_psw_error', balanceNotEnough = 'balanceNotEnough', unAuthSso = 'unAuthSso' } const errList = [ + { + statusText: UserErrEnum.notUser, + message: i18nT('common:code_error.account_not_found') + }, + { + statusText: UserErrEnum.userExist, + message: i18nT('common:code_error.account_exist') + }, { statusText: UserErrEnum.account_psw_error, message: i18nT('common:code_error.account_error') diff --git a/packages/global/common/system/types/index.d.ts b/packages/global/common/system/types/index.d.ts index 64b7bd0a42ff..5f376e8a9a7f 100644 --- a/packages/global/common/system/types/index.d.ts +++ b/packages/global/common/system/types/index.d.ts @@ -3,7 +3,7 @@ import type { ChatModelItemType, FunctionModelItemType, LLMModelItemType, - VectorModelItemType, + EmbeddingModelItemType, AudioSpeechModels, STTModelType, ReRankModelItemType @@ -31,11 +31,13 @@ export type FastGPTConfigFileType = { feConfigs: FastGPTFeConfigsType; systemEnv: SystemEnvType; subPlans?: SubPlanType; - llmModels: ChatModelItemType[]; - vectorModels: VectorModelItemType[]; - reRankModels: ReRankModelItemType[]; - audioSpeechModels: AudioSpeechModelType[]; - whisperModel: STTModelType; + + // Abandon + llmModels?: ChatModelItemType[]; + vectorModels?: EmbeddingModelItemType[]; + reRankModels?: ReRankModelItemType[]; + audioSpeechModels?: TTSModelType[]; + whisperModel?: STTModelType; }; export type FastGPTFeConfigsType = { diff --git a/packages/global/core/ai/constants.ts b/packages/global/core/ai/constants.ts index f01859ab1832..45e7155f16c1 100644 --- a/packages/global/core/ai/constants.ts +++ b/packages/global/core/ai/constants.ts @@ -15,15 +15,13 @@ export enum LLMModelTypeEnum { all = 'all', classify = 'classify', extractFields = 'extractFields', - toolCall = 'toolCall', - queryExtension = 'queryExtension' + toolCall = 'toolCall' } export const llmModelTypeFilterMap = { [LLMModelTypeEnum.all]: 'model', [LLMModelTypeEnum.classify]: 'usedInClassify', [LLMModelTypeEnum.extractFields]: 'usedInExtractFields', - [LLMModelTypeEnum.toolCall]: 'usedInToolCall', - [LLMModelTypeEnum.queryExtension]: 'usedInQueryExtension' + [LLMModelTypeEnum.toolCall]: 'usedInToolCall' }; export enum EmbeddingTypeEnm { diff --git a/packages/global/core/ai/model.d.ts b/packages/global/core/ai/model.d.ts index 533ced31d88a..235dd0e6f570 100644 --- a/packages/global/core/ai/model.d.ts +++ b/packages/global/core/ai/model.d.ts @@ -1,3 +1,4 @@ +import { ModelTypeEnum } from './model'; import type { ModelProviderIdType } from './provider'; type PriceType = { @@ -7,68 +8,74 @@ type PriceType = { inputPrice?: number; // 1k tokens=n points outputPrice?: number; // 1k tokens=n points }; -export type LLMModelItemType = PriceType & { +type BaseModelItemType = { provider: ModelProviderIdType; model: string; name: string; avatar?: string; // model icon, from provider - maxContext: number; - maxResponse: number; - quoteMaxToken: number; - maxTemperature: number; - censor?: boolean; - vision?: boolean; + isActive?: boolean; + isCustom?: boolean; + isDefault?: boolean; - // diff function model - datasetProcess?: boolean; // dataset - usedInClassify?: boolean; // classify - usedInExtractFields?: boolean; // extract fields - usedInToolCall?: boolean; // tool call - usedInQueryExtension?: boolean; // query extension + // If has requestUrl, it will request the model directly + requestUrl?: string; + requestAuth?: string; +}; - functionCall: boolean; - toolChoice: boolean; +export type LLMModelItemType = PriceType & + BaseModelItemType & { + type: ModelTypeEnum.llm; + maxContext: number; + maxResponse: number; + quoteMaxToken: number; + maxTemperature?: number; - customCQPrompt: string; - customExtractPrompt: string; + censor?: boolean; + vision?: boolean; + reasoning?: boolean; - defaultSystemChatPrompt?: string; - defaultConfig?: Record; - fieldMap?: Record; -}; + // diff function model + datasetProcess?: boolean; // dataset + usedInClassify?: boolean; // classify + usedInExtractFields?: boolean; // extract fields + usedInToolCall?: boolean; // tool call -export type VectorModelItemType = PriceType & { - provider: ModelProviderIdType; - model: string; // model name - name: string; // show name - avatar?: string; - defaultToken: number; // split text default token - maxToken: number; // model max token - weight: number; // training weight - hidden?: boolean; // Disallow creation - defaultConfig?: Record; // post request config - dbConfig?: Record; // Custom parameters for storage - queryConfig?: Record; // Custom parameters for query -}; + functionCall: boolean; + toolChoice: boolean; -export type ReRankModelItemType = PriceType & { - provider: ModelProviderIdType; - model: string; - name: string; - requestUrl: string; - requestAuth: string; -}; + customCQPrompt: string; + customExtractPrompt: string; -export type AudioSpeechModelType = PriceType & { - provider: ModelProviderIdType; - model: string; - name: string; - voices: { label: string; value: string; bufferId: string }[]; -}; + defaultSystemChatPrompt?: string; + defaultConfig?: Record; + fieldMap?: Record; + }; -export type STTModelType = PriceType & { - provider: ModelProviderIdType; - model: string; - name: string; -}; +export type EmbeddingModelItemType = PriceType & + BaseModelItemType & { + type: ModelTypeEnum.embedding; + defaultToken: number; // split text default token + maxToken: number; // model max token + weight: number; // training weight + hidden?: boolean; // Disallow creation + defaultConfig?: Record; // post request config + dbConfig?: Record; // Custom parameters for storage + queryConfig?: Record; // Custom parameters for query + }; + +export type ReRankModelItemType = PriceType & + BaseModelItemType & { + type: ModelTypeEnum.rerank; + }; + +export type TTSModelType = PriceType & + BaseModelItemType & { + type: ModelTypeEnum.tts; + voices: { label: string; value: string }[]; + }; + +export type STTModelType = PriceType & + BaseModelItemType & { + type: ModelTypeEnum.stt; + }; diff --git a/packages/global/core/ai/model.ts b/packages/global/core/ai/model.ts index 4a40c83c558c..8588b68eb535 100644 --- a/packages/global/core/ai/model.ts +++ b/packages/global/core/ai/model.ts @@ -1,9 +1,18 @@ import { i18nT } from '../../../web/i18n/utils'; -import type { LLMModelItemType, STTModelType, VectorModelItemType } from './model.d'; +import type { LLMModelItemType, STTModelType, EmbeddingModelItemType } from './model.d'; import { getModelProvider, ModelProviderIdType } from './provider'; +export enum ModelTypeEnum { + llm = 'llm', + embedding = 'embedding', + tts = 'tts', + stt = 'stt', + rerank = 'rerank' +} + export const defaultQAModels: LLMModelItemType[] = [ { + type: ModelTypeEnum.llm, provider: 'OpenAI', model: 'gpt-4o-mini', name: 'gpt-4o-mini', @@ -24,8 +33,9 @@ export const defaultQAModels: LLMModelItemType[] = [ } ]; -export const defaultVectorModels: VectorModelItemType[] = [ +export const defaultVectorModels: EmbeddingModelItemType[] = [ { + type: ModelTypeEnum.embedding, provider: 'OpenAI', model: 'text-embedding-3-small', name: 'Embedding-2', @@ -36,12 +46,15 @@ export const defaultVectorModels: VectorModelItemType[] = [ } ]; -export const defaultWhisperModel: STTModelType = { - provider: 'OpenAI', - model: 'whisper-1', - name: 'whisper-1', - charsPointsPrice: 0 -}; +export const defaultSTTModels: STTModelType[] = [ + { + type: ModelTypeEnum.stt, + provider: 'OpenAI', + model: 'whisper-1', + name: 'whisper-1', + charsPointsPrice: 0 + } +]; export const getModelFromList = ( modelList: { provider: ModelProviderIdType; name: string; model: string }[], @@ -55,15 +68,10 @@ export const getModelFromList = ( }; }; -export enum ModelTypeEnum { - chat = 'chat', - embedding = 'embedding', - tts = 'tts', - stt = 'stt' -} export const modelTypeList = [ - { label: i18nT('common:model.type.chat'), value: ModelTypeEnum.chat }, + { label: i18nT('common:model.type.chat'), value: ModelTypeEnum.llm }, { label: i18nT('common:model.type.embedding'), value: ModelTypeEnum.embedding }, { label: i18nT('common:model.type.tts'), value: ModelTypeEnum.tts }, - { label: i18nT('common:model.type.stt'), value: ModelTypeEnum.stt } + { label: i18nT('common:model.type.stt'), value: ModelTypeEnum.stt }, + { label: i18nT('common:model.type.reRank'), value: ModelTypeEnum.rerank } ]; diff --git a/packages/global/core/ai/provider.ts b/packages/global/core/ai/provider.ts index efdfb2334248..f1bfc9370457 100644 --- a/packages/global/core/ai/provider.ts +++ b/packages/global/core/ai/provider.ts @@ -7,11 +7,12 @@ export type ModelProviderIdType = | 'Meta' | 'MistralAI' | 'Groq' + | 'Grok' | 'AliCloud' | 'Qwen' | 'Doubao' - | 'ChatGLM' | 'DeepSeek' + | 'ChatGLM' | 'Ernie' | 'Moonshot' | 'MiniMax' @@ -20,6 +21,7 @@ export type ModelProviderIdType = | 'Baichuan' | 'StepFun' | 'Yi' + | 'Siliconflow' | 'Ollama' | 'BAAI' | 'FishAudio' @@ -29,7 +31,7 @@ export type ModelProviderIdType = export type ModelProviderType = { id: ModelProviderIdType; - name: string; + name: any; avatar: string; }; @@ -59,6 +61,11 @@ export const ModelProviderList: ModelProviderType[] = [ name: 'MistralAI', avatar: 'model/mistral' }, + { + id: 'Grok', + name: 'Grok', + avatar: 'model/grok' + }, { id: 'Groq', name: 'Groq', @@ -155,6 +162,11 @@ export const ModelProviderList: ModelProviderType[] = [ name: i18nT('common:model_moka'), avatar: 'model/moka' }, + { + id: 'Siliconflow', + name: i18nT('common:model_siliconflow'), + avatar: 'model/siliconflow' + }, { id: 'Other', name: i18nT('common:model_other'), @@ -165,6 +177,7 @@ export const ModelProviderMap = Object.fromEntries( ModelProviderList.map((item, index) => [item.id, { ...item, order: index }]) ); -export const getModelProvider = (provider: ModelProviderIdType) => { +export const getModelProvider = (provider?: ModelProviderIdType) => { + if (!provider) return ModelProviderMap.Other; return ModelProviderMap[provider] ?? ModelProviderMap.Other; }; diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts index 899628936ed9..1008344d23aa 100644 --- a/packages/global/core/app/type.d.ts +++ b/packages/global/core/app/type.d.ts @@ -80,6 +80,7 @@ export type AppSimpleEditFormType = { maxToken?: number; isResponseAnswerText: boolean; maxHistories: number; + [NodeInputKeyEnum.aiChatReasoning]?: boolean; }; dataset: { datasets: SelectedDatasetType; @@ -117,6 +118,7 @@ export type SettingAIDataType = { isResponseAnswerText?: boolean; maxHistories?: number; [NodeInputKeyEnum.aiChatVision]?: boolean; // Is open vision mode + [NodeInputKeyEnum.aiChatReasoning]?: boolean; // Is open reasoning mode }; // variable diff --git a/packages/global/core/app/utils.ts b/packages/global/core/app/utils.ts index 1c793cfead89..708964b380e8 100644 --- a/packages/global/core/app/utils.ts +++ b/packages/global/core/app/utils.ts @@ -16,7 +16,8 @@ export const getDefaultAppForm = (): AppSimpleEditFormType => { temperature: 0, isResponseAnswerText: true, maxHistories: 6, - maxToken: 4000 + maxToken: 4000, + aiChatReasoning: true }, dataset: { datasets: [], diff --git a/packages/global/core/chat/constants.ts b/packages/global/core/chat/constants.ts index ac0d27875c60..34c6ff1e0ce8 100644 --- a/packages/global/core/chat/constants.ts +++ b/packages/global/core/chat/constants.ts @@ -25,7 +25,8 @@ export enum ChatItemValueTypeEnum { text = 'text', file = 'file', tool = 'tool', - interactive = 'interactive' + interactive = 'interactive', + reasoning = 'reasoning' } export enum ChatSourceEnum { @@ -75,5 +76,3 @@ export enum ChatStatusEnum { running = 'running', finish = 'finish' } - -export const MARKDOWN_QUOTE_SIGN = 'QUOTE SIGN'; diff --git a/packages/global/core/chat/type.d.ts b/packages/global/core/chat/type.d.ts index a9171b1568e2..4e010c68f749 100644 --- a/packages/global/core/chat/type.d.ts +++ b/packages/global/core/chat/type.d.ts @@ -70,14 +70,23 @@ export type SystemChatItemType = { obj: ChatRoleEnum.System; value: SystemChatItemValueItemType[]; }; + export type AIChatItemValueItemType = { - type: ChatItemValueTypeEnum.text | ChatItemValueTypeEnum.tool | ChatItemValueTypeEnum.interactive; + type: + | ChatItemValueTypeEnum.text + | ChatItemValueTypeEnum.reasoning + | ChatItemValueTypeEnum.tool + | ChatItemValueTypeEnum.interactive; text?: { content: string; }; + reasoning?: { + content: string; + }; tools?: ToolModuleResponseItemType[]; interactive?: WorkflowInteractiveResponseType; }; + export type AIChatItemType = { obj: ChatRoleEnum.AI; value: AIChatItemValueItemType[]; diff --git a/packages/global/core/dataset/type.d.ts b/packages/global/core/dataset/type.d.ts index 70d3211d1b8c..9e1f42b665f2 100644 --- a/packages/global/core/dataset/type.d.ts +++ b/packages/global/core/dataset/type.d.ts @@ -1,4 +1,4 @@ -import type { LLMModelItemType, VectorModelItemType } from '../../core/ai/model.d'; +import type { LLMModelItemType, EmbeddingModelItemType } from '../../core/ai/model.d'; import { PermissionTypeEnum } from '../../support/permission/constant'; import { PushDatasetDataChunkProps } from './api'; import { @@ -152,7 +152,7 @@ export type DatasetSimpleItemType = { _id: string; avatar: string; name: string; - vectorModel: VectorModelItemType; + vectorModel: EmbeddingModelItemType; }; export type DatasetListItemType = { _id: string; @@ -163,14 +163,14 @@ export type DatasetListItemType = { intro: string; type: `${DatasetTypeEnum}`; permission: DatasetPermission; - vectorModel: VectorModelItemType; + vectorModel: EmbeddingModelItemType; inheritPermission: boolean; private?: boolean; sourceMember?: SourceMemberType; }; export type DatasetItemType = Omit & { - vectorModel: VectorModelItemType; + vectorModel: EmbeddingModelItemType; agentModel: LLMModelItemType; permission: DatasetPermission; }; diff --git a/packages/global/core/workflow/api.d.ts b/packages/global/core/workflow/api.d.ts index 2851b3e9be57..ad45ac7388a7 100644 --- a/packages/global/core/workflow/api.d.ts +++ b/packages/global/core/workflow/api.d.ts @@ -1,4 +1,4 @@ -import { VectorModelItemType } from '../ai/model.d'; +import { EmbeddingModelItemType } from '../ai/model.d'; import { NodeInputKeyEnum } from './constants'; export type SelectedDatasetType = { datasetId: string }[]; diff --git a/packages/global/core/workflow/constants.ts b/packages/global/core/workflow/constants.ts index 175f0c19dd06..9aa4620bd61a 100644 --- a/packages/global/core/workflow/constants.ts +++ b/packages/global/core/workflow/constants.ts @@ -141,6 +141,7 @@ export enum NodeInputKeyEnum { aiChatDatasetQuote = 'quoteQA', aiChatVision = 'aiChatVision', stringQuoteText = 'stringQuoteText', + aiChatReasoning = 'aiChatReasoning', // dataset datasetSelectList = 'datasets', @@ -220,7 +221,8 @@ export enum NodeOutputKeyEnum { // common userChatInput = 'userChatInput', history = 'history', - answerText = 'answerText', // module answer. the value will be show and save to history + answerText = 'answerText', // node answer. the value will be show and save to history + reasoningText = 'reasoningText', // node reasoning. the value will be show but not save to history success = 'success', failed = 'failed', error = 'error', diff --git a/packages/global/core/workflow/runtime/type.d.ts b/packages/global/core/workflow/runtime/type.d.ts index 995302b65ed8..fdf1bfeba030 100644 --- a/packages/global/core/workflow/runtime/type.d.ts +++ b/packages/global/core/workflow/runtime/type.d.ts @@ -220,6 +220,7 @@ export type AIChatNodeProps = { [NodeInputKeyEnum.aiChatMaxToken]?: number; [NodeInputKeyEnum.aiChatIsResponseText]: boolean; [NodeInputKeyEnum.aiChatVision]?: boolean; + [NodeInputKeyEnum.aiChatReasoning]?: boolean; [NodeInputKeyEnum.aiChatQuoteRole]?: AiChatQuoteRoleType; [NodeInputKeyEnum.aiChatQuoteTemplate]?: string; diff --git a/packages/global/core/workflow/runtime/utils.ts b/packages/global/core/workflow/runtime/utils.ts index e7523f123309..27c819ba6fec 100644 --- a/packages/global/core/workflow/runtime/utils.ts +++ b/packages/global/core/workflow/runtime/utils.ts @@ -176,6 +176,7 @@ export const checkNodeRunStatus = ({ } visited.add(edge.source); + // 递归检测后面的 edge,如果有其中一个成环,则返回 true const nextEdges = allEdges.filter((item) => item.target === edge.source); return nextEdges.some((nextEdge) => checkIsCircular(nextEdge, new Set(visited))); }; @@ -207,7 +208,23 @@ export const checkNodeRunStatus = ({ currentNode: node }); - // check skip(其中一组边,全 skip) + // check active(其中一组边,至少有一个 active,且没有 waiting 即可运行) + if ( + commonEdges.length > 0 && + commonEdges.some((item) => item.status === 'active') && + commonEdges.every((item) => item.status !== 'waiting') + ) { + return 'run'; + } + if ( + recursiveEdges.length > 0 && + recursiveEdges.some((item) => item.status === 'active') && + recursiveEdges.every((item) => item.status !== 'waiting') + ) { + return 'run'; + } + + // check skip(其中一组边,全是 skiped 则跳过运行) if (commonEdges.length > 0 && commonEdges.every((item) => item.status === 'skipped')) { return 'skip'; } @@ -215,14 +232,6 @@ export const checkNodeRunStatus = ({ return 'skip'; } - // check active(有一类边,不全是 wait 即可运行) - if (commonEdges.length > 0 && commonEdges.every((item) => item.status !== 'waiting')) { - return 'run'; - } - if (recursiveEdges.length > 0 && recursiveEdges.every((item) => item.status !== 'waiting')) { - return 'run'; - } - return 'wait'; }; @@ -355,12 +364,14 @@ export function replaceEditorVariable({ export const textAdaptGptResponse = ({ text, + reasoning_content, model = '', finish_reason = null, extraData = {} }: { model?: string; - text: string | null; + text?: string | null; + reasoning_content?: string | null; finish_reason?: null | 'stop'; extraData?: Object; }) => { @@ -372,10 +383,11 @@ export const textAdaptGptResponse = ({ model, choices: [ { - delta: - text === null - ? {} - : { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text }, + delta: { + role: ChatCompletionRequestMessageRoleEnum.Assistant, + content: text, + ...(reasoning_content && { reasoning_content }) + }, index: 0, finish_reason } diff --git a/packages/global/core/workflow/template/system/aiChat/index.ts b/packages/global/core/workflow/template/system/aiChat/index.ts index a346371b21c1..103d5f311499 100644 --- a/packages/global/core/workflow/template/system/aiChat/index.ts +++ b/packages/global/core/workflow/template/system/aiChat/index.ts @@ -63,14 +63,14 @@ export const AiChatModule: FlowNodeTemplateType = { key: NodeInputKeyEnum.aiChatTemperature, renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window label: '', - value: 0, + value: undefined, valueType: WorkflowIOValueTypeEnum.number }, { key: NodeInputKeyEnum.aiChatMaxToken, renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window label: '', - value: 2000, + value: undefined, valueType: WorkflowIOValueTypeEnum.number }, @@ -91,6 +91,13 @@ export const AiChatModule: FlowNodeTemplateType = { valueType: WorkflowIOValueTypeEnum.boolean, value: true }, + { + key: NodeInputKeyEnum.aiChatReasoning, + renderTypeList: [FlowNodeInputTypeEnum.hidden], + label: '', + valueType: WorkflowIOValueTypeEnum.boolean, + value: true + }, // settings modal --- { ...Input_Template_System_Prompt, diff --git a/packages/global/core/workflow/template/system/queryExtension.ts b/packages/global/core/workflow/template/system/queryExtension.ts index 57a458ecfdba..dbfcd4e454d6 100644 --- a/packages/global/core/workflow/template/system/queryExtension.ts +++ b/packages/global/core/workflow/template/system/queryExtension.ts @@ -31,10 +31,7 @@ export const AiQueryExtension: FlowNodeTemplateType = { showStatus: true, version: '481', inputs: [ - { - ...Input_Template_SelectAIModel, - llmModelType: LLMModelTypeEnum.queryExtension - }, + Input_Template_SelectAIModel, { key: NodeInputKeyEnum.aiSystemPrompt, renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference], diff --git a/packages/global/core/workflow/template/system/tools.ts b/packages/global/core/workflow/template/system/tools.ts index 29406a19326c..f1472e4953bd 100644 --- a/packages/global/core/workflow/template/system/tools.ts +++ b/packages/global/core/workflow/template/system/tools.ts @@ -43,14 +43,14 @@ export const ToolModule: FlowNodeTemplateType = { key: NodeInputKeyEnum.aiChatTemperature, renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window label: '', - value: 0, + value: undefined, valueType: WorkflowIOValueTypeEnum.number }, { key: NodeInputKeyEnum.aiChatMaxToken, renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window label: '', - value: 2000, + value: undefined, valueType: WorkflowIOValueTypeEnum.number }, { diff --git a/packages/global/support/wallet/usage/api.d.ts b/packages/global/support/wallet/usage/api.d.ts index 9c6825b22a6a..785eb257d2d7 100644 --- a/packages/global/support/wallet/usage/api.d.ts +++ b/packages/global/support/wallet/usage/api.d.ts @@ -6,6 +6,22 @@ export type CreateTrainingUsageProps = { datasetId: string; }; +export type GetUsageProps = { + dateStart: Date; + dateEnd: Date; + sources?: UsageSourceEnum[]; + teamMemberIds?: string[]; + projectName?: string; +}; + +export type GetUsageDashboardProps = GetUsageProps & { + unit: 'day' | 'month'; +}; +export type GetUsageDashboardResponseItem = { + date: Date; + totalPoints: number; +}; + export type ConcatUsageProps = UsageListItemCountType & { teamId: string; tmbId: string; diff --git a/packages/global/support/wallet/usage/constants.ts b/packages/global/support/wallet/usage/constants.ts index dfbff7f4df00..b20bc8a6de2a 100644 --- a/packages/global/support/wallet/usage/constants.ts +++ b/packages/global/support/wallet/usage/constants.ts @@ -18,30 +18,30 @@ export const UsageSourceMap = { label: i18nT('common:core.chat.logs.online') }, [UsageSourceEnum.api]: { - label: 'Api' + label: 'API' }, [UsageSourceEnum.shareLink]: { label: i18nT('common:core.chat.logs.free_login') }, [UsageSourceEnum.training]: { - label: 'dataset.Training Name' + label: i18nT('common:dataset.Training Name') }, [UsageSourceEnum.cronJob]: { label: i18nT('common:cron_job_run_app') }, [UsageSourceEnum.feishu]: { - label: i18nT('user:usage.feishu') + label: i18nT('account_usage:feishu') }, [UsageSourceEnum.official_account]: { - label: i18nT('user:usage.official_account') + label: i18nT('account_usage:official_account') }, [UsageSourceEnum.share]: { - label: i18nT('user:usage.share') + label: i18nT('account_usage:share') }, [UsageSourceEnum.wecom]: { - label: i18nT('user:usage.wecom') + label: i18nT('account_usage:wecom') }, [UsageSourceEnum.dingtalk]: { - label: i18nT('user:usage.dingtalk') + label: i18nT('account_usage:dingtalk') } }; diff --git a/packages/global/support/wallet/usage/type.d.ts b/packages/global/support/wallet/usage/type.d.ts index 076c589b5861..f34feb580abc 100644 --- a/packages/global/support/wallet/usage/type.d.ts +++ b/packages/global/support/wallet/usage/type.d.ts @@ -1,3 +1,4 @@ +import { SourceMemberType } from '../../../support/user/type'; import { CreateUsageProps } from './api'; import { UsageSourceEnum } from './constants'; @@ -10,6 +11,7 @@ export type UsageListItemCountType = { // deprecated tokens?: number; }; + export type UsageListItemType = UsageListItemCountType & { moduleName: string; amount: number; @@ -28,4 +30,5 @@ export type UsageItemType = { source: UsageSchemaType['source']; totalPoints: number; list: UsageSchemaType['list']; + sourceMember: SourceMemberType; }; diff --git a/packages/service/common/file/image/controller.ts b/packages/service/common/file/image/controller.ts index 27bc7ade5c97..5734f7ab958d 100644 --- a/packages/service/common/file/image/controller.ts +++ b/packages/service/common/file/image/controller.ts @@ -40,7 +40,7 @@ export async function uploadMongoImg({ expiredTime: forever ? undefined : addHours(new Date(), 1) }); - return `${process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL || ''}${imageBaseUrl}${String(_id)}.${extension}`; + return `${process.env.NEXT_PUBLIC_BASE_URL || ''}${imageBaseUrl}${String(_id)}.${extension}`; } const getIdFromPath = (path?: string) => { diff --git a/packages/service/common/middle/reqFrequencyLimit.ts b/packages/service/common/middle/reqFrequencyLimit.ts index de7249483aa2..6205c47c6298 100644 --- a/packages/service/common/middle/reqFrequencyLimit.ts +++ b/packages/service/common/middle/reqFrequencyLimit.ts @@ -1,6 +1,5 @@ import { ApiRequestProps } from '../../type/next'; import requestIp from 'request-ip'; -import { ERROR_ENUM } from '@fastgpt/global/common/error/errorCode'; import { authFrequencyLimit } from '../system/frequencyLimit/utils'; import { addSeconds } from 'date-fns'; import { NextApiResponse } from 'next'; @@ -9,7 +8,17 @@ import { jsonRes } from '../response'; // unit: times/s // how to use? // export default NextAPI(useQPSLimit(10), handler); // limit 10 times per second for a ip -export function useReqFrequencyLimit(seconds: number, limit: number, force = false) { +export function useIPFrequencyLimit({ + id, + seconds, + limit, + force = false +}: { + id: string; + seconds: number; + limit: number; + force?: boolean; +}) { return async (req: ApiRequestProps, res: NextApiResponse) => { const ip = requestIp.getClientIp(req); if (!ip || (process.env.USE_IP_LIMIT !== 'true' && !force)) { @@ -17,14 +26,14 @@ export function useReqFrequencyLimit(seconds: number, limit: number, force = fal } try { await authFrequencyLimit({ - eventId: 'ip-qps-limit' + ip, + eventId: `ip-qps-limit-${id}-` + ip, maxAmount: limit, expiredTime: addSeconds(new Date(), seconds) }); } catch (_) { jsonRes(res, { code: 429, - error: ERROR_ENUM.tooManyRequest + error: `Too many request, request ${limit} times every ${seconds} seconds` }); } }; diff --git a/packages/service/common/response/index.ts b/packages/service/common/response/index.ts index a6de2e38a92d..e713433d9b02 100644 --- a/packages/service/common/response/index.ts +++ b/packages/service/common/response/index.ts @@ -33,7 +33,15 @@ export const jsonRes = ( addLog.error(`Api response error: ${url}`, ERROR_RESPONSE[errResponseKey]); - return res.status(code).json(ERROR_RESPONSE[errResponseKey]); + res.status(code); + + if (message) { + res.send(message); + } else { + res.json(ERROR_RESPONSE[errResponseKey]); + } + + return; } // another error diff --git a/packages/service/common/system/config/controller.ts b/packages/service/common/system/config/controller.ts index aa79f916d8bf..5eb6d1bc1345 100644 --- a/packages/service/common/system/config/controller.ts +++ b/packages/service/common/system/config/controller.ts @@ -6,8 +6,7 @@ import { FastGPTProUrl } from '../constants'; export const getFastGPTConfigFromDB = async () => { if (!FastGPTProUrl) { return { - config: {} as FastGPTConfigFileType, - configId: undefined + config: {} as FastGPTConfigFileType }; } @@ -18,9 +17,35 @@ export const getFastGPTConfigFromDB = async () => { }); const config = res?.value || {}; + // 利用配置文件的创建时间(更新时间)来做缓存,如果前端命中缓存,则不需要再返回配置文件 + global.systemInitBufferId = res ? res.createTime.getTime().toString() : undefined; return { - configId: res ? String(res._id) : undefined, config: config as FastGPTConfigFileType }; }; + +export const updateFastGPTConfigBuffer = async () => { + const res = await MongoSystemConfigs.findOne({ + type: SystemConfigsTypeEnum.fastgpt + }).sort({ + createTime: -1 + }); + + if (!res) return; + + res.createTime = new Date(); + await res.save(); + + global.systemInitBufferId = res.createTime.getTime().toString(); +}; + +export const reloadFastGPTConfigBuffer = async () => { + const res = await MongoSystemConfigs.findOne({ + type: SystemConfigsTypeEnum.fastgpt + }).sort({ + createTime: -1 + }); + if (!res) return; + global.systemInitBufferId = res.createTime.getTime().toString(); +}; diff --git a/packages/service/common/system/tools.ts b/packages/service/common/system/tools.ts index 4d195c8e12fa..a52e2a79b93a 100644 --- a/packages/service/common/system/tools.ts +++ b/packages/service/common/system/tools.ts @@ -13,15 +13,6 @@ export const initFastGPTConfig = (config?: FastGPTConfigFileType) => { global.feConfigs = config.feConfigs; global.systemEnv = config.systemEnv; global.subPlans = config.subPlans; - - global.llmModels = config.llmModels; - global.llmModelPriceType = global.llmModels.some((item) => typeof item.inputPrice === 'number') - ? 'IO' - : 'Tokens'; - global.vectorModels = config.vectorModels; - global.audioSpeechModels = config.audioSpeechModels; - global.whisperModel = config.whisperModel; - global.reRankModels = config.reRankModels; }; export const systemStartCb = () => { diff --git a/packages/service/common/vectorStore/controller.ts b/packages/service/common/vectorStore/controller.ts index 156ce70d114a..48c8f3c82824 100644 --- a/packages/service/common/vectorStore/controller.ts +++ b/packages/service/common/vectorStore/controller.ts @@ -2,7 +2,7 @@ import { PgVectorCtrl } from './pg/class'; import { getVectorsByText } from '../../core/ai/embedding'; import { InsertVectorProps } from './controller.d'; -import { VectorModelItemType } from '@fastgpt/global/core/ai/model.d'; +import { EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d'; import { MILVUS_ADDRESS, PG_ADDRESS } from './constants'; import { MilvusCtrl } from './milvus/class'; @@ -28,7 +28,7 @@ export const insertDatasetDataVector = async ({ ...props }: InsertVectorProps & { query: string; - model: VectorModelItemType; + model: EmbeddingModelItemType; }) => { const { vectors, tokens } = await getVectorsByText({ model, diff --git a/packages/service/core/ai/audio/speech.ts b/packages/service/core/ai/audio/speech.ts index fe805d1513a6..3d82f68c6179 100644 --- a/packages/service/core/ai/audio/speech.ts +++ b/packages/service/core/ai/audio/speech.ts @@ -1,5 +1,6 @@ import type { NextApiResponse } from 'next'; import { getAIApi } from '../config'; +import { getTTSModel } from '../model'; export async function text2Speech({ res, @@ -18,15 +19,26 @@ export async function text2Speech({ voice: string; speed?: number; }) { + const modelData = getTTSModel(model)!; const ai = getAIApi(); - const response = await ai.audio.speech.create({ - model, - // @ts-ignore - voice, - input, - response_format: 'mp3', - speed - }); + const response = await ai.audio.speech.create( + { + model, + // @ts-ignore + voice, + input, + response_format: 'mp3', + speed + }, + modelData.requestUrl && modelData.requestAuth + ? { + path: modelData.requestUrl, + headers: { + Authorization: `Bearer ${modelData.requestAuth}` + } + } + : {} + ); const readableStream = response.body as unknown as NodeJS.ReadableStream; readableStream.pipe(res); diff --git a/packages/service/core/ai/audio/transcriptions.ts b/packages/service/core/ai/audio/transcriptions.ts index 718dd5ad1bcc..753f8b4817ca 100644 --- a/packages/service/core/ai/audio/transcriptions.ts +++ b/packages/service/core/ai/audio/transcriptions.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import { getAxiosConfig } from '../config'; import axios from 'axios'; import FormData from 'form-data'; +import { getSTTModel } from '../model'; export const aiTranscriptions = async ({ model, @@ -14,13 +15,21 @@ export const aiTranscriptions = async ({ data.append('model', model); data.append('file', fileStream); + const modelData = getSTTModel(model); const aiAxiosConfig = getAxiosConfig(); + const { data: result } = await axios<{ text: string }>({ method: 'post', - baseURL: aiAxiosConfig.baseUrl, - url: '/audio/transcriptions', + ...(modelData.requestUrl + ? { url: modelData.requestUrl } + : { + baseURL: aiAxiosConfig.baseUrl, + url: modelData.requestUrl || '/audio/transcriptions' + }), headers: { - Authorization: aiAxiosConfig.authorization, + Authorization: modelData.requestAuth + ? `Bearer ${modelData.requestAuth}` + : aiAxiosConfig.authorization, ...data.getHeaders() }, data: data diff --git a/packages/service/core/ai/config.ts b/packages/service/core/ai/config.ts index 0db12a4b01f4..859bbb80d176 100644 --- a/packages/service/core/ai/config.ts +++ b/packages/service/core/ai/config.ts @@ -7,14 +7,14 @@ import { getErrText } from '@fastgpt/global/common/error/utils'; import { addLog } from '../../common/system/log'; import { i18nT } from '../../../web/i18n/utils'; import { OpenaiAccountType } from '@fastgpt/global/support/user/team/type'; +import { getLLMModel } from './model'; export const openaiBaseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'; export const getAIApi = (props?: { userKey?: OpenaiAccountType; timeout?: number }) => { const { userKey, timeout } = props || {}; - const baseUrl = - userKey?.baseUrl || global?.systemEnv?.oneapiUrl || process.env.ONEAPI_URL || openaiBaseUrl; + const baseUrl = userKey?.baseUrl || global?.systemEnv?.oneapiUrl || openaiBaseUrl; const apiKey = userKey?.key || global?.systemEnv?.chatApiKey || process.env.CHAT_API_KEY || ''; return new OpenAI({ @@ -29,8 +29,7 @@ export const getAIApi = (props?: { userKey?: OpenaiAccountType; timeout?: number export const getAxiosConfig = (props?: { userKey?: OpenaiAccountType }) => { const { userKey } = props || {}; - const baseUrl = - userKey?.baseUrl || global?.systemEnv?.oneapiUrl || process.env.ONEAPI_URL || openaiBaseUrl; + const baseUrl = userKey?.baseUrl || global?.systemEnv?.oneapiUrl || openaiBaseUrl; const apiKey = userKey?.key || global?.systemEnv?.chatApiKey || process.env.CHAT_API_KEY || ''; return { @@ -63,12 +62,23 @@ export const createChatCompletion = async ({ getEmptyResponseTip: () => string; }> => { try { + const modelConstantsData = getLLMModel(body.model); + const formatTimeout = timeout ? timeout : body.stream ? 60000 : 600000; const ai = getAIApi({ userKey, timeout: formatTimeout }); - const response = await ai.chat.completions.create(body, options); + const response = await ai.chat.completions.create(body, { + ...options, + ...(modelConstantsData.requestUrl ? { path: modelConstantsData.requestUrl } : {}), + headers: { + ...options?.headers, + ...(modelConstantsData.requestAuth + ? { Authorization: `Bearer ${modelConstantsData.requestAuth}` } + : {}) + } + }); const isStreamResponse = typeof response === 'object' && diff --git a/packages/service/core/ai/config/embedding/text-embedding-ada-002.json b/packages/service/core/ai/config/embedding/text-embedding-ada-002.json deleted file mode 100644 index 4f6290f7549f..000000000000 --- a/packages/service/core/ai/config/embedding/text-embedding-ada-002.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "provider": "OpenAI", - "model": "text-embedding-ada-002", - "name": "text-embedding-ada-002", - - "defaultToken": 512, // 默认分块 token - "maxToken": 3000, // 最大分块 token - "weight": 0, // 权重 - - "charsPointsPrice": 0 // 积分/1k token -} diff --git a/packages/service/core/ai/config/llm/gpt-4o-mini.json b/packages/service/core/ai/config/llm/gpt-4o-mini.json deleted file mode 100644 index 0bcf7f6defc2..000000000000 --- a/packages/service/core/ai/config/llm/gpt-4o-mini.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "provider": "OpenAI", - "model": "gpt-4o-mini", - "name": "GPT-4o-mini", // alias - - "maxContext": 125000, // 最大上下文 - "maxResponse": 16000, // 最大回复 - "quoteMaxToken": 60000, // 最大引用 - "maxTemperature": 1.2, // 最大温度 - "presencePenaltyRange": [-2, 2], // 惩罚系数范围 - "frequencyPenaltyRange": [-2, 2], // 频率惩罚系数范围 - "responseFormatList": ["text", "json_object", "json_schema"], // 响应格式 - "showStopSign": true, // 是否显示停止符号 - - "vision": true, // 是否支持图片识别 - "toolChoice": true, // 是否支持工具调用 - "functionCall": false, // 是否支持函数调用(一般都可以 false 了,基本不用了) - "defaultSystemChatPrompt": "", // 默认系统提示 - - "datasetProcess": true, // 用于知识库文本处理 - "usedInClassify": true, // 用于问题分类 - "customCQPrompt": "", // 自定义问题分类提示 - "usedInExtractFields": true, // 用于提取字段 - "customExtractPrompt": "", // 自定义提取提示 - "usedInToolCall": true, // 用于工具调用 - "usedInQueryExtension": true, // 用于问题优化 - - "defaultConfig": {}, // 额外的自定义 body - "fieldMap": {}, // body 字段映射 - - "censor": false, // 是否开启敏感词过滤 - "charsPointsPrice": 0 // n 积分/1k token -} diff --git a/packages/service/core/ai/config/provider/AliCloud.json b/packages/service/core/ai/config/provider/AliCloud.json new file mode 100644 index 000000000000..703ed71d03d0 --- /dev/null +++ b/packages/service/core/ai/config/provider/AliCloud.json @@ -0,0 +1,4 @@ +{ + "provider": "AliCloud", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/BAAI.json b/packages/service/core/ai/config/provider/BAAI.json new file mode 100644 index 000000000000..86237c65461d --- /dev/null +++ b/packages/service/core/ai/config/provider/BAAI.json @@ -0,0 +1,17 @@ +{ + "provider": "BAAI", + "list": [ + { + "model": "bge-m3", + "name": "bge-m3", + "defaultToken": 512, + "maxToken": 8000, + "type": "embedding" + }, + { + "model": "bge-reranker-v2-m3", + "name": "bge-reranker-v2-m3", + "type": "rerank" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Baichuan.json b/packages/service/core/ai/config/provider/Baichuan.json new file mode 100644 index 000000000000..e5599e5c610a --- /dev/null +++ b/packages/service/core/ai/config/provider/Baichuan.json @@ -0,0 +1,4 @@ +{ + "provider": "Baichuan", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/ChatGLM.json b/packages/service/core/ai/config/provider/ChatGLM.json new file mode 100644 index 000000000000..e687be24333f --- /dev/null +++ b/packages/service/core/ai/config/provider/ChatGLM.json @@ -0,0 +1,147 @@ +{ + "provider": "ChatGLM", + "list": [ + { + "model": "glm-4-air", + "name": "glm-4-air", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 0.99, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "glm-4-flash", + "name": "glm-4-flash", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 0.99, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "glm-4-long", + "name": "glm-4-long", + "maxContext": 1000000, + "maxResponse": 4000, + "quoteMaxToken": 900000, + "maxTemperature": 0.99, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "glm-4-plus", + "name": "GLM-4-plus", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 0.99, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "glm-4v-flash", + "name": "glm-4v-flash", + "maxContext": 8000, + "maxResponse": 1000, + "quoteMaxToken": 6000, + "maxTemperature": 0.99, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "glm-4v-plus", + "name": "GLM-4v-plus", + "maxContext": 8000, + "maxResponse": 1000, + "quoteMaxToken": 6000, + "maxTemperature": 0.99, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "embedding-3", + "name": "embedding-3", + "defaultToken": 512, + "maxToken": 8000, + "defaultConfig": { + "dimensions": 1024 + }, + "type": "embedding" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Claude.json b/packages/service/core/ai/config/provider/Claude.json new file mode 100644 index 000000000000..0b43edc2190b --- /dev/null +++ b/packages/service/core/ai/config/provider/Claude.json @@ -0,0 +1,93 @@ +{ + "provider": "Claude", + "list": [ + { + "model": "claude-3-5-haiku-20241022", + "name": "claude-3-5-haiku-20241022", + "maxContext": 200000, + "maxResponse": 8000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "claude-3-5-sonnet-20240620", + "name": "Claude-3-5-sonnet-20240620", + "maxContext": 200000, + "maxResponse": 8000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "claude-3-5-sonnet-20241022", + "name": "Claude-3-5-sonnet-20241022", + "maxContext": 200000, + "maxResponse": 8000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "claude-3-opus-20240229", + "name": "claude-3-opus-20240229", + "maxContext": 200000, + "maxResponse": 4096, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/DeepSeek.json b/packages/service/core/ai/config/provider/DeepSeek.json new file mode 100644 index 000000000000..1aee2c1ab264 --- /dev/null +++ b/packages/service/core/ai/config/provider/DeepSeek.json @@ -0,0 +1,48 @@ +{ + "provider": "DeepSeek", + "list": [ + { + "model": "deepseek-chat", + "name": "Deepseek-chat", + "maxContext": 64000, + "maxResponse": 4096, + "quoteMaxToken": 60000, + "maxTemperature": 1.5, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "type": "llm" + }, + { + "model": "deepseek-reasoner", + "name": "Deepseek-reasoner", + "maxContext": 64000, + "maxResponse": 4096, + "quoteMaxToken": 60000, + "maxTemperature": null, + "vision": false, + "reasoning": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Doubao.json b/packages/service/core/ai/config/provider/Doubao.json new file mode 100644 index 000000000000..64924b0e4ebb --- /dev/null +++ b/packages/service/core/ai/config/provider/Doubao.json @@ -0,0 +1,195 @@ +{ + "provider": "Doubao", + "list": [ + { + "model": "Doubao-lite-4k", + "name": "Doubao-lite-4k", + "maxContext": 4000, + "maxResponse": 4000, + "quoteMaxToken": 4000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-lite-32k", + "name": "Doubao-lite-32k", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-lite-128k", + "name": "Doubao-lite-128k", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-vision-lite-32k", + "name": "Doubao-vision-lite-32k", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-pro-4k", + "name": "Doubao-pro-4k", + "maxContext": 4000, + "maxResponse": 4000, + "quoteMaxToken": 4000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-pro-32k", + "name": "Doubao-pro-32k", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-pro-128k", + "name": "Doubao-pro-128k", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-vision-pro-32k", + "name": "Doubao-vision-pro-32k", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Doubao-embedding-large", + "name": "Doubao-embedding-large", + "defaultToken": 512, + "maxToken": 4096, + "type": "embedding" + }, + { + "model": "Doubao-embedding", + "name": "Doubao-embedding", + "defaultToken": 512, + "maxToken": 4096, + "type": "embedding" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Ernie.json b/packages/service/core/ai/config/provider/Ernie.json new file mode 100644 index 000000000000..0eaf786998b8 --- /dev/null +++ b/packages/service/core/ai/config/provider/Ernie.json @@ -0,0 +1,107 @@ +{ + "provider": "Ernie", + "list": [ + { + "model": "ERNIE-4.0-8K", + "name": "ERNIE-4.0-8K", + "maxContext": 8000, + "maxResponse": 2048, + "quoteMaxToken": 5000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "ERNIE-4.0-Turbo-8K", + "name": "ERNIE-4.0-Turbo-8K", + "maxContext": 8000, + "maxResponse": 2048, + "quoteMaxToken": 5000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "ERNIE-Lite-8K", + "name": "ERNIE-lite-8k", + "maxContext": 8000, + "maxResponse": 2048, + "quoteMaxToken": 6000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "ERNIE-Speed-128K", + "name": "ERNIE-Speed-128K", + "maxContext": 128000, + "maxResponse": 4096, + "quoteMaxToken": 120000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Embedding-V1", + "name": "Embedding-V1", + "defaultToken": 512, + "maxToken": 1000, + "type": "embedding" + }, + { + "model": "tao-8k", + "name": "tao-8k", + "defaultToken": 512, + "maxToken": 8000, + "type": "embedding" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/FishAudio.json b/packages/service/core/ai/config/provider/FishAudio.json new file mode 100644 index 000000000000..083d565d5134 --- /dev/null +++ b/packages/service/core/ai/config/provider/FishAudio.json @@ -0,0 +1,4 @@ +{ + "provider": "FishAudio", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Gemini.json b/packages/service/core/ai/config/provider/Gemini.json new file mode 100644 index 000000000000..a29dde0a7a10 --- /dev/null +++ b/packages/service/core/ai/config/provider/Gemini.json @@ -0,0 +1,144 @@ +{ + "provider": "Gemini", + "list": [ + { + "model": "gemini-1.5-flash", + "name": "gemini-1.5-flash", + "maxContext": 1000000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gemini-1.5-pro", + "name": "gemini-1.5-pro", + "maxContext": 2000000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gemini-2.0-flash-exp", + "name": "gemini-2.0-flash-exp", + "maxContext": 1000000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gemini-2.0-flash-thinking-exp-1219", + "name": "gemini-2.0-flash-thinking-exp-1219", + "maxContext": 1000000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gemini-2.0-flash-thinking-exp-01-21", + "name": "gemini-2.0-flash-thinking-exp-01-21", + "maxContext": 1000000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gemini-exp-1206", + "name": "gemini-exp-1206", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 120000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "text-embedding-004", + "name": "text-embedding-004", + "defaultToken": 512, + "maxToken": 2000, + "type": "embedding" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Grok.json b/packages/service/core/ai/config/provider/Grok.json new file mode 100644 index 000000000000..3c6336109b2d --- /dev/null +++ b/packages/service/core/ai/config/provider/Grok.json @@ -0,0 +1,4 @@ +{ + "provider": "Grok", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Groq.json b/packages/service/core/ai/config/provider/Groq.json new file mode 100644 index 000000000000..22fc70b49c44 --- /dev/null +++ b/packages/service/core/ai/config/provider/Groq.json @@ -0,0 +1,47 @@ +{ + "provider": "Groq", + "list": [ + { + "model": "llama-3.1-8b-instant", + "name": "Groq-llama-3.1-8b-instant", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "type": "llm" + }, + { + "model": "llama-3.3-70b-versatile", + "name": "Groq-llama-3.3-70b-versatile", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "type": "llm" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Hunyuan.json b/packages/service/core/ai/config/provider/Hunyuan.json new file mode 100644 index 000000000000..cf6a4317abad --- /dev/null +++ b/packages/service/core/ai/config/provider/Hunyuan.json @@ -0,0 +1,166 @@ +{ + "provider": "Hunyuan", + "list": [ + { + "model": "hunyuan-large", + "name": "hunyuan-large", + "maxContext": 28000, + "maxResponse": 4000, + "quoteMaxToken": 20000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-lite", + "name": "hunyuan-lite", + "maxContext": 250000, + "maxResponse": 6000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-pro", + "name": "hunyuan-pro", + "maxContext": 28000, + "maxResponse": 4000, + "quoteMaxToken": 28000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-standard", + "name": "hunyuan-standard", + "maxContext": 32000, + "maxResponse": 2000, + "quoteMaxToken": 20000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-turbo-vision", + "name": "hunyuan-turbo-vision", + "maxContext": 6000, + "maxResponse": 2000, + "quoteMaxToken": 6000, + "maxTemperature": 1, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-turbo", + "name": "hunyuan-turbo", + "maxContext": 28000, + "maxResponse": 4000, + "quoteMaxToken": 20000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-vision", + "name": "hunyuan-vision", + "maxContext": 6000, + "maxResponse": 2000, + "quoteMaxToken": 4000, + "maxTemperature": 1, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "hunyuan-embedding", + "name": "hunyuan-embedding", + "defaultToken": 512, + "maxToken": 1024, + "type": "embedding" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Intern.json b/packages/service/core/ai/config/provider/Intern.json new file mode 100644 index 000000000000..45adf4a52f6c --- /dev/null +++ b/packages/service/core/ai/config/provider/Intern.json @@ -0,0 +1,49 @@ +{ + "provider": "Intern", + "list": [ + { + "model": "internlm2-pro-chat", + "name": "internlm2-pro-chat", + "maxContext": 32000, + "maxResponse": 8000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "internlm3-8b-instruct", + "name": "internlm3-8b-instruct", + "maxContext": 32000, + "maxResponse": 8000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Meta.json b/packages/service/core/ai/config/provider/Meta.json new file mode 100644 index 000000000000..a99db0bc8b42 --- /dev/null +++ b/packages/service/core/ai/config/provider/Meta.json @@ -0,0 +1,4 @@ +{ + "provider": "Meta", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/MiniMax.json b/packages/service/core/ai/config/provider/MiniMax.json new file mode 100644 index 000000000000..de0520088c78 --- /dev/null +++ b/packages/service/core/ai/config/provider/MiniMax.json @@ -0,0 +1,240 @@ +{ + "provider": "MiniMax", + "list": [ + { + "model": "MiniMax-Text-01", + "name": "MiniMax-Text-01", + "maxContext": 1000000, + "maxResponse": 1000000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "abab6.5s-chat", + "name": "MiniMax-abab6.5s", + "maxContext": 245000, + "maxResponse": 10000, + "quoteMaxToken": 240000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "speech-01-turbo", + "name": "speech-01-turbo", + "voices": [ + { + "label": "male-qn-qingse", + "value": "male-qn-qingse" + }, + { + "label": "male-qn-jingying", + "value": "male-qn-jingying" + }, + { + "label": "male-qn-badao", + "value": "male-qn-badao" + }, + { + "label": "male-qn-daxuesheng", + "value": "male-qn-daxuesheng" + }, + { + "label": "female-shaonv", + "value": "female-shaonv" + }, + { + "label": "female-yujie", + "value": "female-yujie" + }, + { + "label": "female-chengshu", + "value": "female-chengshu" + }, + { + "label": "female-tianmei", + "value": "female-tianmei" + }, + { + "label": "presenter_male", + "value": "presenter_male" + }, + { + "label": "presenter_female", + "value": "presenter_female" + }, + { + "label": "audiobook_male_1", + "value": "audiobook_male_1" + }, + { + "label": "audiobook_male_2", + "value": "audiobook_male_2" + }, + { + "label": "audiobook_female_1", + "value": "audiobook_female_1" + }, + { + "label": "audiobook_female_2", + "value": "audiobook_female_2" + }, + { + "label": "male-qn-qingse-jingpin", + "value": "male-qn-qingse-jingpin" + }, + { + "label": "male-qn-jingying-jingpin", + "value": "male-qn-jingying-jingpin" + }, + { + "label": "male-qn-badao-jingpin", + "value": "male-qn-badao-jingpin" + }, + { + "label": "male-qn-daxuesheng-jingpin", + "value": "male-qn-daxuesheng-jingpin" + }, + { + "label": "female-shaonv-jingpin", + "value": "female-shaonv-jingpin" + }, + { + "label": "female-yujie-jingpin", + "value": "female-yujie-jingpin" + }, + { + "label": "female-chengshu-jingpin", + "value": "female-chengshu-jingpin" + }, + { + "label": "female-tianmei-jingpin", + "value": "female-tianmei-jingpin" + }, + { + "label": "clever_boy", + "value": "clever_boy" + }, + { + "label": "cute_boy", + "value": "cute_boy" + }, + { + "label": "lovely_girl", + "value": "lovely_girl" + }, + { + "label": "cartoon_pig", + "value": "cartoon_pig" + }, + { + "label": "bingjiao_didi", + "value": "bingjiao_didi" + }, + { + "label": "junlang_nanyou", + "value": "junlang_nanyou" + }, + { + "label": "chunzhen_xuedi", + "value": "chunzhen_xuedi" + }, + { + "label": "lengdan_xiongzhang", + "value": "lengdan_xiongzhang" + }, + { + "label": "badao_shaoye", + "value": "badao_shaoye" + }, + { + "label": "tianxin_xiaoling", + "value": "tianxin_xiaoling" + }, + { + "label": "qiaopi_mengmei", + "value": "qiaopi_mengmei" + }, + { + "label": "wumei_yujie", + "value": "wumei_yujie" + }, + { + "label": "diadia_xuemei", + "value": "diadia_xuemei" + }, + { + "label": "danya_xuejie", + "value": "danya_xuejie" + }, + { + "label": "Santa_Claus", + "value": "Santa_Claus" + }, + { + "label": "Grinch", + "value": "Grinch" + }, + { + "label": "Rudolph", + "value": "Rudolph" + }, + { + "label": "Arnold", + "value": "Arnold" + }, + { + "label": "Charming_Santa", + "value": "Charming_Santa" + }, + { + "label": "Charming_Lady", + "value": "Charming_Lady" + }, + { + "label": "Sweet_Girl", + "value": "Sweet_Girl" + }, + { + "label": "Cute_Elf", + "value": "Cute_Elf" + }, + { + "label": "Attractive_Girl", + "value": "Attractive_Girl" + }, + { + "label": "Serene_Woman", + "value": "Serene_Woman" + } + ], + "type": "tts" + } + ] +} diff --git a/packages/service/core/ai/config/provider/MistralAI.json b/packages/service/core/ai/config/provider/MistralAI.json new file mode 100644 index 000000000000..3d271db2aba4 --- /dev/null +++ b/packages/service/core/ai/config/provider/MistralAI.json @@ -0,0 +1,93 @@ +{ + "provider": "MistralAI", + "list": [ + { + "model": "ministral-3b-latest", + "name": "Ministral-3b-latest", + "maxContext": 130000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "ministral-8b-latest", + "name": "Ministral-8b-latest", + "maxContext": 130000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "mistral-large-latest", + "name": "Mistral-large-latest", + "maxContext": 130000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "mistral-small-latest", + "name": "Mistral-small-latest", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1.2, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Moka.json b/packages/service/core/ai/config/provider/Moka.json new file mode 100644 index 000000000000..90b68c9fffcc --- /dev/null +++ b/packages/service/core/ai/config/provider/Moka.json @@ -0,0 +1,4 @@ +{ + "provider": "Moka", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Moonshot.json b/packages/service/core/ai/config/provider/Moonshot.json new file mode 100644 index 000000000000..9b733677c4d8 --- /dev/null +++ b/packages/service/core/ai/config/provider/Moonshot.json @@ -0,0 +1,71 @@ +{ + "provider": "Moonshot", + "list": [ + { + "model": "moonshot-v1-8k", + "name": "moonshot-v1-8k", + "maxContext": 8000, + "maxResponse": 4000, + "quoteMaxToken": 6000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "moonshot-v1-32k", + "name": "moonshot-v1-32k", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "moonshot-v1-128k", + "name": "moonshot-v1-128k", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Ollama.json b/packages/service/core/ai/config/provider/Ollama.json new file mode 100644 index 000000000000..6343aa95071e --- /dev/null +++ b/packages/service/core/ai/config/provider/Ollama.json @@ -0,0 +1,4 @@ +{ + "provider": "Ollama", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/OpenAI.json b/packages/service/core/ai/config/provider/OpenAI.json new file mode 100644 index 000000000000..a852cf22dbea --- /dev/null +++ b/packages/service/core/ai/config/provider/OpenAI.json @@ -0,0 +1,252 @@ +{ + "provider": "OpenAI", + "list": [ + { + "model": "gpt-4o-mini", + "name": "GPT-4o-mini", + "maxContext": 128000, + "maxResponse": 16000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": true, + "functionCall": true, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "gpt-4o", + "name": "GPT-4o", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": true, + "functionCall": true, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "o3-mini", + "name": "o3-mini", + "maxContext": 200000, + "maxResponse": 100000, + "quoteMaxToken": 120000, + "maxTemperature": null, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": { + "stream": false + }, + "fieldMap": { + "max_tokens": "max_completion_tokens" + }, + "type": "llm" + }, + { + "model": "o1-mini", + "name": "o1-mini", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": null, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": { + "stream": false + }, + "fieldMap": { + "max_tokens": "max_completion_tokens" + }, + "type": "llm" + }, + { + "model": "o1", + "name": "o1", + "maxContext": 195000, + "maxResponse": 8000, + "quoteMaxToken": 120000, + "maxTemperature": null, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": { + "stream": false + }, + "fieldMap": { + "max_tokens": "max_completion_tokens" + }, + "type": "llm" + }, + { + "model": "o1-preview", + "name": "o1-preview", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": null, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": { + "stream": false + }, + "fieldMap": { + "max_tokens": "max_completion_tokens" + }, + "type": "llm" + }, + { + "model": "gpt-3.5-turbo", + "name": "gpt-3.5-turbo", + "maxContext": 16000, + "maxResponse": 4000, + "quoteMaxToken": 13000, + "maxTemperature": 1.2, + "vision": false, + "toolChoice": true, + "functionCall": true, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "type": "llm" + }, + { + "model": "gpt-4-turbo", + "name": "gpt-4-turbo", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 60000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": true, + "functionCall": true, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "type": "llm" + }, + { + "model": "text-embedding-3-large", + "name": "text-embedding-3-large", + "defaultToken": 512, + "maxToken": 8000, + "defaultConfig": { + "dimensions": 1024 + }, + "type": "embedding" + }, + { + "model": "text-embedding-3-small", + "name": "text-embedding-3-small", + "defaultToken": 512, + "maxToken": 8000, + "type": "embedding" + }, + { + "model": "text-embedding-ada-002", + "name": "text-embedding-ada-002", + "defaultToken": 512, + "maxToken": 8000, + "type": "embedding" + }, + { + "model": "tts-1", + "name": "TTS1", + "voices": [ + { + "label": "Alloy", + "value": "alloy" + }, + { + "label": "Echo", + "value": "echo" + }, + { + "label": "Fable", + "value": "fable" + }, + { + "label": "Onyx", + "value": "onyx" + }, + { + "label": "Nova", + "value": "nova" + }, + { + "label": "Shimmer", + "value": "shimmer" + } + ], + "type": "tts" + }, + { + "model": "whisper-1", + "name": "whisper-1", + "type": "stt" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Other.json b/packages/service/core/ai/config/provider/Other.json new file mode 100644 index 000000000000..4405e6086c32 --- /dev/null +++ b/packages/service/core/ai/config/provider/Other.json @@ -0,0 +1,4 @@ +{ + "provider": "Other", + "list": [] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/provider/Qwen.json b/packages/service/core/ai/config/provider/Qwen.json new file mode 100644 index 000000000000..cde27ac13037 --- /dev/null +++ b/packages/service/core/ai/config/provider/Qwen.json @@ -0,0 +1,223 @@ +{ + "provider": "Qwen", + "list": [ + { + "model": "qwen-turbo", + "name": "Qwen-turbo", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 100000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen-plus", + "name": "Qwen-plus", + "maxContext": 64000, + "maxResponse": 8000, + "quoteMaxToken": 60000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen-vl-plus", + "name": "qwen-vl-plus", + "maxContext": 32000, + "maxResponse": 2000, + "quoteMaxToken": 20000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "type": "llm" + }, + { + "model": "qwen-max", + "name": "Qwen-max", + "maxContext": 8000, + "maxResponse": 4000, + "quoteMaxToken": 6000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen-vl-max", + "name": "qwen-vl-max", + "maxContext": 32000, + "maxResponse": 2000, + "quoteMaxToken": 20000, + "maxTemperature": 1.2, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen-coder-turbo", + "name": "qwen-coder-turbo", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen2.5-7b-instruct", + "name": "qwen2.5-7b-instruct", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen2.5-14b-instruct", + "name": "qwen2.5-14b-instruct", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen2.5-32b-instruct", + "name": "qwen2.5-32b-instruct", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "qwen2.5-72b-instruct", + "name": "Qwen2.5-72B-instruct", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Siliconflow.json b/packages/service/core/ai/config/provider/Siliconflow.json new file mode 100644 index 000000000000..f1e8a042a4ab --- /dev/null +++ b/packages/service/core/ai/config/provider/Siliconflow.json @@ -0,0 +1,204 @@ +{ + "provider": "Siliconflow", + "list": [ + { + "model": "Qwen/Qwen2.5-72B-Instruct", + "name": "Qwen/Qwen2.5-72B-Instruct", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 50000, + "maxTemperature": 1, + "vision": false, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "Qwen/Qwen2-VL-72B-Instruct", + "name": "Qwen/Qwen2-VL-72B-Instruct", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "censor": false, + "vision": true, + "datasetProcess": false, + "usedInClassify": false, + "usedInExtractFields": false, + "usedInToolCall": false, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "defaultConfig": {}, + "type": "llm" + }, + { + "model": "deepseek-ai/DeepSeek-V2.5", + "name": "deepseek-ai/DeepSeek-V2.5", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": true, + "toolChoice": true, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "BAAI/bge-m3", + "name": "BAAI/bge-m3", + "defaultToken": 512, + "maxToken": 8000, + "type": "embedding" + }, + { + "model": "FunAudioLLM/CosyVoice2-0.5B", + "name": "FunAudioLLM/CosyVoice2-0.5B", + "voices": [ + { + "label": "alex", + "value": "FunAudioLLM/CosyVoice2-0.5B:alex" + }, + { + "label": "anna", + "value": "FunAudioLLM/CosyVoice2-0.5B:anna" + }, + { + "label": "bella", + "value": "FunAudioLLM/CosyVoice2-0.5B:bella" + }, + { + "label": "benjamin", + "value": "FunAudioLLM/CosyVoice2-0.5B:benjamin" + }, + { + "label": "charles", + "value": "FunAudioLLM/CosyVoice2-0.5B:charles" + }, + { + "label": "claire", + "value": "FunAudioLLM/CosyVoice2-0.5B:claire" + }, + { + "label": "david", + "value": "FunAudioLLM/CosyVoice2-0.5B:david" + }, + { + "label": "diana", + "value": "FunAudioLLM/CosyVoice2-0.5B:diana" + } + ], + "type": "tts" + }, + { + "model": "RVC-Boss/GPT-SoVITS", + "name": "RVC-Boss/GPT-SoVITS", + "voices": [ + { + "label": "alex", + "value": "RVC-Boss/GPT-SoVITS:alex" + }, + { + "label": "anna", + "value": "RVC-Boss/GPT-SoVITS:anna" + }, + { + "label": "bella", + "value": "RVC-Boss/GPT-SoVITS:bella" + }, + { + "label": "benjamin", + "value": "RVC-Boss/GPT-SoVITS:benjamin" + }, + { + "label": "charles", + "value": "RVC-Boss/GPT-SoVITS:charles" + }, + { + "label": "claire", + "value": "RVC-Boss/GPT-SoVITS:claire" + }, + { + "label": "david", + "value": "RVC-Boss/GPT-SoVITS:david" + }, + { + "label": "diana", + "value": "RVC-Boss/GPT-SoVITS:diana" + } + ], + "type": "tts" + }, + { + "model": "fishaudio/fish-speech-1.5", + "name": "fish-speech-1.5", + "voices": [ + { + "label": "alex", + "value": "fishaudio/fish-speech-1.5:alex" + }, + { + "label": "anna", + "value": "fishaudio/fish-speech-1.5:anna" + }, + { + "label": "bella", + "value": "fishaudio/fish-speech-1.5:bella" + }, + { + "label": "benjamin", + "value": "fishaudio/fish-speech-1.5:benjamin" + }, + { + "label": "charles", + "value": "fishaudio/fish-speech-1.5:charles" + }, + { + "label": "claire", + "value": "fishaudio/fish-speech-1.5:claire" + }, + { + "label": "david", + "value": "fishaudio/fish-speech-1.5:david" + }, + { + "label": "diana", + "value": "fishaudio/fish-speech-1.5:diana" + } + ], + "type": "tts" + }, + { + "model": "FunAudioLLM/SenseVoiceSmall", + "name": "FunAudioLLM/SenseVoiceSmall", + "type": "stt" + }, + { + "model": "BAAI/bge-reranker-v2-m3", + "name": "BAAI/bge-reranker-v2-m3", + "type": "rerank" + } + ] +} diff --git a/packages/service/core/ai/config/provider/SparkDesk.json b/packages/service/core/ai/config/provider/SparkDesk.json new file mode 100644 index 000000000000..095136850bcf --- /dev/null +++ b/packages/service/core/ai/config/provider/SparkDesk.json @@ -0,0 +1,129 @@ +{ + "provider": "SparkDesk", + "list": [ + { + "model": "lite", + "name": "SparkDesk-lite", + "maxContext": 32000, + "maxResponse": 4000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "generalv3", + "name": "SparkDesk-Pro", + "maxContext": 8000, + "maxResponse": 8000, + "quoteMaxToken": 8000, + "maxTemperature": 1, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "pro-128k", + "name": "SparkDesk-Pro-128k", + "maxContext": 128000, + "maxResponse": 4000, + "quoteMaxToken": 128000, + "maxTemperature": 1, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "generalv3.5", + "name": "SparkDesk-max", + "maxContext": 8000, + "maxResponse": 8000, + "quoteMaxToken": 8000, + "maxTemperature": 1, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "max-32k", + "name": "SparkDesk-max-32k", + "maxContext": 32000, + "maxResponse": 8000, + "quoteMaxToken": 32000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "4.0Ultra", + "name": "SparkDesk-v4.0 Ultra", + "maxContext": 8000, + "maxResponse": 8000, + "quoteMaxToken": 8000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} diff --git a/packages/service/core/ai/config/provider/StepFun.json b/packages/service/core/ai/config/provider/StepFun.json new file mode 100644 index 000000000000..87c896117c39 --- /dev/null +++ b/packages/service/core/ai/config/provider/StepFun.json @@ -0,0 +1,308 @@ +{ + "provider": "StepFun", + "list": [ + { + "model": "step-1-flash", + "name": "step-1-flash", + "maxContext": 8000, + "maxResponse": 4000, + "quoteMaxToken": 6000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1-8k", + "name": "step-1-8k", + "maxContext": 8000, + "maxResponse": 8000, + "quoteMaxToken": 8000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1-32k", + "name": "step-1-32k", + "maxContext": 32000, + "maxResponse": 8000, + "quoteMaxToken": 32000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1-128k", + "name": "step-1-128k", + "maxContext": 128000, + "maxResponse": 8000, + "quoteMaxToken": 128000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1-256k", + "name": "step-1-256k", + "maxContext": 256000, + "maxResponse": 8000, + "quoteMaxToken": 256000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1o-vision-32k", + "name": "step-1o-vision-32k", + "maxContext": 32000, + "quoteMaxToken": 32000, + "maxResponse": 8000, + "maxTemperature": 2, + "vision": true, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1v-8k", + "name": "step-1v-8k", + "maxContext": 8000, + "maxResponse": 8000, + "quoteMaxToken": 8000, + "maxTemperature": 2, + "vision": true, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-1v-32k", + "name": "step-1v-32k", + "maxContext": 32000, + "quoteMaxToken": 32000, + "maxResponse": 8000, + "maxTemperature": 2, + "vision": true, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-2-mini", + "name": "step-2-mini", + "maxContext": 8000, + "maxResponse": 4000, + "quoteMaxToken": 6000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-2-16k", + "name": "step-2-16k", + "maxContext": 16000, + "maxResponse": 4000, + "quoteMaxToken": 4000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-2-16k-exp", + "name": "step-2-16k-exp", + "maxContext": 16000, + "maxResponse": 4000, + "quoteMaxToken": 4000, + "maxTemperature": 2, + "vision": false, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": false, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "type": "llm" + }, + { + "model": "step-tts-mini", + "name": "step-tts-mini", + "voices": [ + { + "label": "cixingnansheng", + "value": "cixingnansheng" + }, + { + "label": "zhengpaiqingnian", + "value": "zhengpaiqingnian" + }, + { + "label": "yuanqinansheng", + "value": "yuanqinansheng" + }, + { + "label": "qingniandaxuesheng", + "value": "qingniandaxuesheng" + }, + { + "label": "boyinnansheng", + "value": "boyinnansheng" + }, + { + "label": "ruyananshi", + "value": "ruyananshi" + }, + { + "label": "shenchennanyin", + "value": "shenchennanyin" + }, + { + "label": "qinqienvsheng", + "value": "qinqienvsheng" + }, + { + "label": "wenrounvsheng", + "value": "wenrounvsheng" + }, + { + "label": "jilingshaonv", + "value": "jilingshaonv" + }, + { + "label": "yuanqishaonv", + "value": "yuanqishaonv" + }, + { + "label": "ruanmengnvsheng", + "value": "ruanmengnvsheng" + }, + { + "label": "youyanvsheng", + "value": "youyanvsheng" + }, + { + "label": "lengyanyujie", + "value": "lengyanyujie" + }, + { + "label": "shuangkuaijiejie", + "value": "shuangkuaijiejie" + }, + { + "label": "wenjingxuejie", + "value": "wenjingxuejie" + }, + { + "label": "linjiajiejie", + "value": "linjiajiejie" + }, + { + "label": "linjiameimei", + "value": "linjiameimei" + }, + { + "label": "zhixingjiejie", + "value": "zhixingjiejie" + } + ], + "type": "tts" + } + ] +} diff --git a/packages/service/core/ai/config/provider/Yi.json b/packages/service/core/ai/config/provider/Yi.json new file mode 100644 index 000000000000..b43a9ba90887 --- /dev/null +++ b/packages/service/core/ai/config/provider/Yi.json @@ -0,0 +1,49 @@ +{ + "provider": "Yi", + "list": [ + { + "model": "yi-lightning", + "name": "yi-lightning", + "maxContext": 16000, + "maxResponse": 4000, + "quoteMaxToken": 12000, + "maxTemperature": 1, + "vision": false, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + }, + { + "model": "yi-vision-v2", + "name": "yi-vision-v2", + "maxContext": 16000, + "maxResponse": 4000, + "quoteMaxToken": 12000, + "maxTemperature": 1, + "vision": true, + "toolChoice": false, + "functionCall": false, + "defaultSystemChatPrompt": "", + "datasetProcess": true, + "usedInClassify": true, + "customCQPrompt": "", + "usedInExtractFields": true, + "usedInQueryExtension": true, + "customExtractPrompt": "", + "usedInToolCall": true, + "defaultConfig": {}, + "fieldMap": {}, + "type": "llm" + } + ] +} \ No newline at end of file diff --git a/packages/service/core/ai/config/rerank/bge-reranker-v2-m3.json b/packages/service/core/ai/config/rerank/bge-reranker-v2-m3.json deleted file mode 100644 index 3cc1a33b5a42..000000000000 --- a/packages/service/core/ai/config/rerank/bge-reranker-v2-m3.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "provider": "BAAI", - "model": "bge-reranker-v2-m3", - "name": "bge-reranker-v2-m3", - "charsPointsPrice": 0 -} diff --git a/packages/service/core/ai/config/schema.ts b/packages/service/core/ai/config/schema.ts new file mode 100644 index 000000000000..33a422792fbd --- /dev/null +++ b/packages/service/core/ai/config/schema.ts @@ -0,0 +1,21 @@ +import { connectionMongo, getMongoModel } from '../../../common/mongo'; +const { Schema } = connectionMongo; +import type { SystemModelSchemaType } from '../type'; + +const SystemModelSchema = new Schema({ + model: { + type: String, + required: true, + unique: true + }, + metadata: { + type: Object, + required: true, + default: {} + } +}); + +export const MongoSystemModel = getMongoModel( + 'system_models', + SystemModelSchema +); diff --git a/packages/service/core/ai/config/stt/whisper-1.json b/packages/service/core/ai/config/stt/whisper-1.json deleted file mode 100644 index 2d8639786266..000000000000 --- a/packages/service/core/ai/config/stt/whisper-1.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "provider": "OpenAI", - "model": "whisper-1", - "name": "whisper-1", - "charsPointsPrice": 0 -} diff --git a/packages/service/core/ai/config/tts/tts-1.json b/packages/service/core/ai/config/tts/tts-1.json deleted file mode 100644 index 80105c227767..000000000000 --- a/packages/service/core/ai/config/tts/tts-1.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "provider": "OpenAI", - "model": "tts-1", - "name": "TTS1", - "charsPointsPrice": 0, - "voices": [ - { - "label": "Alloy", - "value": "alloy" - }, - { - "label": "Echo", - "value": "echo" - }, - { - "label": "Fable", - "value": "fable" - }, - { - "label": "Onyx", - "value": "onyx" - }, - { - "label": "Nova", - "value": "nova" - }, - { - "label": "Shimmer", - "value": "shimmer" - } - ] -} diff --git a/packages/service/core/ai/config/utils.ts b/packages/service/core/ai/config/utils.ts new file mode 100644 index 000000000000..e39ee1a38ccb --- /dev/null +++ b/packages/service/core/ai/config/utils.ts @@ -0,0 +1,195 @@ +import path from 'path'; +import * as fs from 'fs'; +import { SystemModelItemType } from '../type'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; +import { MongoSystemModel } from './schema'; +import { + LLMModelItemType, + EmbeddingModelItemType, + TTSModelType, + STTModelType, + ReRankModelItemType +} from '@fastgpt/global/core/ai/model.d'; +import { debounce } from 'lodash'; +import { ModelProviderType } from '@fastgpt/global/core/ai/provider'; +import { findModelFromAlldata } from '../model'; +import { + reloadFastGPTConfigBuffer, + updateFastGPTConfigBuffer +} from '../../../common/system/config/controller'; +import { delay } from '@fastgpt/global/common/system/utils'; + +/* + TODO: 分优先级读取: + 1. 有外部挂载目录,则读取外部的 + 2. 没有外部挂载目录,则读取本地的。然后试图拉取云端的进行覆盖。 +*/ +export const loadSystemModels = async (init = false) => { + const getProviderList = () => { + const currentFileUrl = new URL(import.meta.url); + const modelsPath = path.join(path.dirname(currentFileUrl.pathname), 'provider'); + + return fs.readdirSync(modelsPath) as string[]; + }; + const pushModel = (model: SystemModelItemType) => { + global.systemModelList.push(model); + + if (model.isActive) { + global.systemActiveModelList.push(model); + + if (model.type === ModelTypeEnum.llm) { + global.llmModelMap.set(model.model, model); + global.llmModelMap.set(model.name, model); + if (model.isDefault) { + global.systemDefaultModel.llm = model; + } + } else if (model.type === ModelTypeEnum.embedding) { + global.embeddingModelMap.set(model.model, model); + global.embeddingModelMap.set(model.name, model); + if (model.isDefault) { + global.systemDefaultModel.embedding = model; + } + } else if (model.type === ModelTypeEnum.tts) { + global.ttsModelMap.set(model.model, model); + global.ttsModelMap.set(model.name, model); + if (model.isDefault) { + global.systemDefaultModel.tts = model; + } + } else if (model.type === ModelTypeEnum.stt) { + global.sttModelMap.set(model.model, model); + global.sttModelMap.set(model.name, model); + if (model.isDefault) { + global.systemDefaultModel.stt = model; + } + } else if (model.type === ModelTypeEnum.rerank) { + global.reRankModelMap.set(model.model, model); + global.reRankModelMap.set(model.name, model); + if (model.isDefault) { + global.systemDefaultModel.rerank = model; + } + } + } + }; + + if (!init && global.systemModelList) return; + + global.systemModelList = []; + global.systemActiveModelList = []; + global.llmModelMap = new Map(); + global.embeddingModelMap = new Map(); + global.ttsModelMap = new Map(); + global.sttModelMap = new Map(); + global.reRankModelMap = new Map(); + // @ts-ignore + global.systemDefaultModel = {}; + + try { + const dbModels = await MongoSystemModel.find({}).lean(); + const providerList = getProviderList(); + + // System model + await Promise.all( + providerList.map(async (name) => { + const fileContent = (await import(`./provider/${name}`))?.default as { + provider: ModelProviderType; + list: SystemModelItemType[]; + }; + + fileContent.list.forEach((fileModel) => { + const dbModel = dbModels.find((item) => item.model === fileModel.model); + + const modelData: any = { + ...fileModel, + ...dbModel?.metadata, + provider: dbModel?.metadata?.provider || fileContent.provider, + type: dbModel?.metadata?.type || fileModel.type, + isCustom: false + }; + + pushModel(modelData); + }); + }) + ); + + // Custom model + dbModels.forEach((dbModel) => { + if (global.systemModelList.find((item) => item.model === dbModel.model)) return; + + pushModel({ + ...dbModel.metadata, + isCustom: true + }); + }); + + // Default model check + if (!global.systemDefaultModel.llm) { + global.systemDefaultModel.llm = Array.from(global.llmModelMap.values())[0]; + } + if (!global.systemDefaultModel.embedding) { + global.systemDefaultModel.embedding = Array.from(global.embeddingModelMap.values())[0]; + } + if (!global.systemDefaultModel.tts) { + global.systemDefaultModel.tts = Array.from(global.ttsModelMap.values())[0]; + } + if (!global.systemDefaultModel.stt) { + global.systemDefaultModel.stt = Array.from(global.sttModelMap.values())[0]; + } + if (!global.systemDefaultModel.rerank) { + global.systemDefaultModel.rerank = Array.from(global.reRankModelMap.values())[0]; + } + + console.log('Load models success', JSON.stringify(global.systemActiveModelList, null, 2)); + } catch (error) { + console.error('Load models error', error); + // @ts-ignore + global.systemModelList = undefined; + } +}; + +export const getSystemModelConfig = async (model: string): Promise => { + const modelData = findModelFromAlldata(model); + if (!modelData) return Promise.reject('Model is not found'); + if (modelData.isCustom) return Promise.reject('Custom model not data'); + + // Read file + const fileContent = (await import(`./provider/${modelData.provider}`))?.default as { + provider: ModelProviderType; + list: SystemModelItemType[]; + }; + + const config = fileContent.list.find((item) => item.model === model); + + if (!config) return Promise.reject('Model config is not found'); + + return { + ...config, + provider: modelData.provider, + isCustom: false + }; +}; + +export const watchSystemModelUpdate = () => { + const changeStream = MongoSystemModel.watch(); + + changeStream.on( + 'change', + debounce(async () => { + try { + // Main node will reload twice + await loadSystemModels(true); + // All node reaload buffer + await reloadFastGPTConfigBuffer(); + } catch (error) {} + }, 500) + ); +}; + +// 更新完模型后,需要重载缓存 +export const updatedReloadSystemModel = async () => { + // 1. 更新模型(所有节点都会触发) + await loadSystemModels(true); + // 2. 更新缓存(仅主节点触发) + await updateFastGPTConfigBuffer(); + // 3. 延迟1秒,等待其他节点刷新 + await delay(1000); +}; diff --git a/packages/service/core/ai/embedding/index.ts b/packages/service/core/ai/embedding/index.ts index 89bb91b1fdd5..adf3db7dcf67 100644 --- a/packages/service/core/ai/embedding/index.ts +++ b/packages/service/core/ai/embedding/index.ts @@ -1,11 +1,11 @@ -import { VectorModelItemType } from '@fastgpt/global/core/ai/model.d'; +import { EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d'; import { getAIApi } from '../config'; import { countPromptTokens } from '../../../common/string/tiktoken/index'; import { EmbeddingTypeEnm } from '@fastgpt/global/core/ai/constants'; import { addLog } from '../../../common/system/log'; type GetVectorProps = { - model: VectorModelItemType; + model: EmbeddingModelItemType; input: string; type?: `${EmbeddingTypeEnm}`; }; @@ -24,13 +24,23 @@ export async function getVectorsByText({ model, input, type }: GetVectorProps) { // input text to vector const result = await ai.embeddings - .create({ - ...model.defaultConfig, - ...(type === EmbeddingTypeEnm.db && model.dbConfig), - ...(type === EmbeddingTypeEnm.query && model.queryConfig), - model: model.model, - input: [input] - }) + .create( + { + ...model.defaultConfig, + ...(type === EmbeddingTypeEnm.db && model.dbConfig), + ...(type === EmbeddingTypeEnm.query && model.queryConfig), + model: model.model, + input: [input] + }, + model.requestUrl && model.requestAuth + ? { + path: model.requestUrl, + headers: { + Authorization: `Bearer ${model.requestAuth}` + } + } + : {} + ) .then(async (res) => { if (!res.data) { addLog.error('Embedding API is not responding', res); diff --git a/packages/service/core/ai/functions/queryExtension.ts b/packages/service/core/ai/functions/queryExtension.ts index 31bb9ee8df06..c4b85ffcda03 100644 --- a/packages/service/core/ai/functions/queryExtension.ts +++ b/packages/service/core/ai/functions/queryExtension.ts @@ -2,10 +2,12 @@ import { replaceVariable } from '@fastgpt/global/common/string/tools'; import { createChatCompletion } from '../config'; import { ChatItemType } from '@fastgpt/global/core/chat/type'; import { countGptMessagesTokens, countPromptTokens } from '../../../common/string/tiktoken/index'; -import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt'; +import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; import { getLLMModel } from '../model'; import { llmCompletionsBodyFormat } from '../utils'; import { addLog } from '../../../common/system/log'; +import { filterGPTMessageByMaxContext } from '../../chat/utils'; +import json5 from 'json5'; /* query extension - 问题扩展 @@ -13,72 +15,73 @@ import { addLog } from '../../../common/system/log'; */ const title = global.feConfigs?.systemTitle || 'FastAI'; -const defaultPrompt = `作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。 +const defaultPrompt = `## 你的任务 +你作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。 生成的问题要求指向对象清晰明确,并与“原问题语言相同”。 -参考 标中的示例来完成任务。 +## 参考示例 - 历史记录: """ +null """ 原问题: 介绍下剧情。 检索词: ["介绍下故事的背景。","故事的主题是什么?","介绍下故事的主要人物。"] ---------------- 历史记录: """ -Q: 对话背景。 -A: 当前对话是关于 Nginx 的介绍和使用等。 +user: 对话背景。 +assistant: 当前对话是关于 Nginx 的介绍和使用等。 """ 原问题: 怎么下载 检索词: ["Nginx 如何下载?","下载 Nginx 需要什么条件?","有哪些渠道可以下载 Nginx?"] ---------------- 历史记录: """ -Q: 对话背景。 -A: 当前对话是关于 Nginx 的介绍和使用等。 -Q: 报错 "no connection" -A: 报错"no connection"可能是因为…… +user: 对话背景。 +assistant: 当前对话是关于 Nginx 的介绍和使用等。 +user: 报错 "no connection" +assistant: 报错"no connection"可能是因为…… """ 原问题: 怎么解决 检索词: ["Nginx报错"no connection"如何解决?","造成'no connection'报错的原因。","Nginx提示'no connection',要怎么办?"] ---------------- 历史记录: """ -Q: 护产假多少天? -A: 护产假的天数根据员工所在的城市而定。请提供您所在的城市,以便我回答您的问题。 +user: How long is the maternity leave? +assistant: The number of days of maternity leave depends on the city in which the employee is located. Please provide your city so that I can answer your questions. """ -原问题: 沈阳 -检索词: ["沈阳的护产假多少天?","沈阳的护产假政策。","沈阳的护产假标准。"] +原问题: ShenYang +检索词: ["How many days is maternity leave in Shenyang?","Shenyang's maternity leave policy.","The standard of maternity leave in Shenyang."] ---------------- 历史记录: """ -Q: 作者是谁? -A: ${title} 的作者是 labring。 +user: 作者是谁? +assistant: ${title} 的作者是 labring。 """ 原问题: Tell me about him 检索词: ["Introduce labring, the author of ${title}." ," Background information on author labring." "," Why does labring do ${title}?"] ---------------- 历史记录: """ -Q: 对话背景。 -A: 关于 ${title} 的介绍和使用等问题。 +user: 对话背景。 +assistant: 关于 ${title} 的介绍和使用等问题。 """ 原问题: 你好。 检索词: ["你好"] ---------------- 历史记录: """ -Q: ${title} 如何收费? -A: ${title} 收费可以参考…… +user: ${title} 如何收费? +assistant: ${title} 收费可以参考…… """ 原问题: 你知道 laf 么? 检索词: ["laf 的官网地址是多少?","laf 的使用教程。","laf 有什么特点和优势。"] ---------------- 历史记录: """ -Q: ${title} 的优势 -A: 1. 开源 +user: ${title} 的优势 +assistant: 1. 开源 2. 简便 3. 扩展性强 """ @@ -87,18 +90,20 @@ A: 1. 开源 ---------------- 历史记录: """ -Q: 什么是 ${title}? -A: ${title} 是一个 RAG 平台。 -Q: 什么是 Laf? -A: Laf 是一个云函数开发平台。 +user: 什么是 ${title}? +assistant: ${title} 是一个 RAG 平台。 +user: 什么是 Laf? +assistant: Laf 是一个云函数开发平台。 """ 原问题: 它们有什么关系? 检索词: ["${title}和Laf有什么关系?","介绍下${title}","介绍下Laf"] - ------ +## 输出要求 -下面是正式的任务: +1. 输出格式为 JSON 数组,数组中每个元素为字符串。无需对输出进行任何解释。 +2. 输出语言与原问题相同。原问题为中文则输出中文;原问题为英文则输出英文。 + +## 开始任务 历史记录: """ @@ -125,26 +130,39 @@ export const queryExtension = async ({ outputTokens: number; }> => { const systemFewShot = chatBg - ? `Q: 对话背景。 -A: ${chatBg} + ? `user: 对话背景。 +assistant: ${chatBg} ` : ''; - const historyFewShot = histories + + const modelData = getLLMModel(model); + const filterHistories = await filterGPTMessageByMaxContext({ + messages: chats2GPTMessages({ messages: histories, reserveId: false }), + maxContext: modelData.maxContext - 1000 + }); + + const historyFewShot = filterHistories .map((item) => { - const role = item.obj === 'Human' ? 'Q' : 'A'; - return `${role}: ${chatValue2RuntimePrompt(item.value).text}`; + const role = item.role; + const content = item.content; + if ((role === 'user' || role === 'assistant') && content) { + if (typeof content === 'string') { + return `${role}: ${content}`; + } else { + return `${role}: ${content.map((item) => (item.type === 'text' ? item.text : '')).join('\n')}`; + } + } }) + .filter(Boolean) .join('\n'); const concatFewShot = `${systemFewShot}${historyFewShot}`.trim(); - const modelData = getLLMModel(model); - const messages = [ { role: 'user', content: replaceVariable(defaultPrompt, { query: `${query}`, - histories: concatFewShot + histories: concatFewShot || 'null' }) } ] as any; @@ -154,7 +172,7 @@ A: ${chatBg} { stream: false, model: modelData.model, - temperature: 0.01, + temperature: 0.1, messages }, modelData @@ -172,22 +190,41 @@ A: ${chatBg} }; } + const start = answer.indexOf('['); + const end = answer.lastIndexOf(']'); + if (start === -1 || end === -1) { + addLog.warn('Query extension failed, not a valid JSON', { + answer + }); + return { + rawQuery: query, + extensionQueries: [], + model, + inputTokens: 0, + outputTokens: 0 + }; + } + // Intercept the content of [] and retain [] - answer = answer.match(/\[.*?\]/)?.[0] || ''; - answer = answer.replace(/\\"/g, '"'); + const jsonStr = answer + .substring(start, end + 1) + .replace(/(\\n|\\)/g, '') + .replace(/ /g, ''); try { - const queries = JSON.parse(answer) as string[]; + const queries = json5.parse(jsonStr) as string[]; return { rawQuery: query, - extensionQueries: Array.isArray(queries) ? queries : [], + extensionQueries: (Array.isArray(queries) ? queries : []).slice(0, 5), model, inputTokens: await countGptMessagesTokens(messages), outputTokens: await countPromptTokens(answer) }; } catch (error) { - addLog.error(`Query extension error`, error); + addLog.warn('Query extension failed, not a valid JSON', { + answer + }); return { rawQuery: query, extensionQueries: [], diff --git a/packages/service/core/ai/model.ts b/packages/service/core/ai/model.ts index 4d5a8633ed38..185881a23f67 100644 --- a/packages/service/core/ai/model.ts +++ b/packages/service/core/ai/model.ts @@ -1,51 +1,52 @@ +import { SystemModelItemType } from './type'; + +export const getDefaultLLMModel = () => global?.systemDefaultModel.llm!; export const getLLMModel = (model?: string) => { - return ( - global.llmModels.find((item) => item.model === model || item.name === model) ?? - global.llmModels[0] - ); + if (!model) return getDefaultLLMModel(); + return global.llmModelMap.get(model) || getDefaultLLMModel(); }; export const getDatasetModel = (model?: string) => { return ( - global.llmModels + Array.from(global.llmModelMap.values()) ?.filter((item) => item.datasetProcess) - ?.find((item) => item.model === model || item.name === model) ?? global.llmModels[0] + ?.find((item) => item.model === model || item.name === model) ?? getDefaultLLMModel() ); }; -export const getVectorModel = (model?: string) => { - return ( - global.vectorModels.find((item) => item.model === model || item.name === model) || - global.vectorModels[0] - ); +export const getDefaultEmbeddingModel = () => global?.systemDefaultModel.embedding!; +export const getEmbeddingModel = (model?: string) => { + if (!model) return getDefaultEmbeddingModel(); + return global.embeddingModelMap.get(model) || getDefaultEmbeddingModel(); }; -export function getAudioSpeechModel(model?: string) { - return ( - global.audioSpeechModels.find((item) => item.model === model || item.name === model) || - global.audioSpeechModels[0] - ); +export const getDefaultTTSModel = () => global?.systemDefaultModel.tts!; +export function getTTSModel(model?: string) { + if (!model) return getDefaultTTSModel(); + return global.ttsModelMap.get(model) || getDefaultTTSModel(); } -export function getWhisperModel(model?: string) { - return global.whisperModel; +export const getDefaultSTTModel = () => global?.systemDefaultModel.stt!; +export function getSTTModel(model?: string) { + if (!model) return getDefaultSTTModel(); + return global.sttModelMap.get(model) || getDefaultSTTModel(); } +export const getDefaultRerankModel = () => global?.systemDefaultModel.rerank!; export function getReRankModel(model?: string) { - return global.reRankModels.find((item) => item.model === model); + if (!model) return getDefaultRerankModel(); + return global.reRankModelMap.get(model) || getDefaultRerankModel(); } -export enum ModelTypeEnum { - llm = 'llm', - vector = 'vector', - audioSpeech = 'audioSpeech', - whisper = 'whisper', - rerank = 'rerank' -} -export const getModelMap = { - [ModelTypeEnum.llm]: getLLMModel, - [ModelTypeEnum.vector]: getVectorModel, - [ModelTypeEnum.audioSpeech]: getAudioSpeechModel, - [ModelTypeEnum.whisper]: getWhisperModel, - [ModelTypeEnum.rerank]: getReRankModel +export const findAIModel = (model: string): SystemModelItemType | undefined => { + return ( + global.llmModelMap.get(model) || + global.embeddingModelMap.get(model) || + global.ttsModelMap.get(model) || + global.sttModelMap.get(model) || + global.reRankModelMap.get(model) + ); +}; +export const findModelFromAlldata = (model: string) => { + return global.systemModelList.find((item) => item.model === model); }; diff --git a/packages/service/core/ai/rerank/index.ts b/packages/service/core/ai/rerank/index.ts index b7eb54588f7f..9ad231d89841 100644 --- a/packages/service/core/ai/rerank/index.ts +++ b/packages/service/core/ai/rerank/index.ts @@ -1,5 +1,8 @@ import { addLog } from '../../../common/system/log'; import { POST } from '../../../common/api/serverRequest'; +import { getDefaultRerankModel } from '../model'; +import { getAxiosConfig } from '../config'; +import { ReRankModelItemType } from '@fastgpt/global/core/ai/model.d'; type PostReRankResponse = { id: string; @@ -11,21 +14,23 @@ type PostReRankResponse = { type ReRankCallResult = { id: string; score?: number }[]; export function reRankRecall({ + model = getDefaultRerankModel(), query, documents }: { + model?: ReRankModelItemType; query: string; documents: { id: string; text: string }[]; }): Promise { - const model = global.reRankModels[0]; - - if (!model || !model?.requestUrl) { + if (!model) { return Promise.reject('no rerank model'); } + const { baseUrl, authorization } = getAxiosConfig({}); + let start = Date.now(); return POST( - model.requestUrl, + model.requestUrl ? model.requestUrl : `${baseUrl}/rerank`, { model: model.model, query, @@ -33,7 +38,7 @@ export function reRankRecall({ }, { headers: { - Authorization: `Bearer ${model.requestAuth}` + Authorization: model.requestAuth ? model.requestAuth : authorization }, timeout: 30000 } @@ -53,6 +58,6 @@ export function reRankRecall({ .catch((err) => { addLog.error('rerank error', err); - return []; + return Promise.reject(err); }); } diff --git a/packages/service/core/ai/type.d.ts b/packages/service/core/ai/type.d.ts new file mode 100644 index 000000000000..c014ed6046e8 --- /dev/null +++ b/packages/service/core/ai/type.d.ts @@ -0,0 +1,42 @@ +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; +import { + STTModelType, + ReRankModelItemType, + TTSModelType, + EmbeddingModelItemType, + LLMModelItemType +} from '@fastgpt/global/core/ai/model.d'; + +export type SystemModelSchemaType = { + _id: string; + model: string; + metadata: SystemModelItemType; +}; + +export type SystemModelItemType = + | LLMModelItemType + | EmbeddingModelItemType + | TTSModelType + | STTModelType + | ReRankModelItemType; + +export type SystemDefaultModelType = { + [ModelTypeEnum.llm]?: LLMModelItemType; + [ModelTypeEnum.embedding]?: EmbeddingModelItemType; + [ModelTypeEnum.tts]?: TTSModelType; + [ModelTypeEnum.stt]?: STTModelType; + [ModelTypeEnum.rerank]?: ReRankModelItemType; +}; + +declare global { + var systemModelList: SystemModelItemType[]; + // var systemModelMap: Map; + var llmModelMap: Map; + var embeddingModelMap: Map; + var ttsModelMap: Map; + var sttModelMap: Map; + var reRankModelMap: Map; + + var systemActiveModelList: SystemModelItemType[]; + var systemDefaultModel: SystemDefaultModelType; +} diff --git a/packages/service/core/ai/utils.ts b/packages/service/core/ai/utils.ts index aad1cb1efeab..40951a3724b0 100644 --- a/packages/service/core/ai/utils.ts +++ b/packages/service/core/ai/utils.ts @@ -2,32 +2,23 @@ import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import { ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming, - ChatCompletionMessageParam + StreamChatType } from '@fastgpt/global/core/ai/type'; -import { countGptMessagesTokens } from '../../common/string/tiktoken'; import { getLLMModel } from './model'; -export const computedMaxToken = async ({ +/* + Count response max token +*/ +export const computedMaxToken = ({ maxToken, - model, - filterMessages = [] + model }: { maxToken?: number; model: LLMModelItemType; - filterMessages: ChatCompletionMessageParam[]; }) => { if (maxToken === undefined) return; maxToken = Math.min(maxToken, model.maxResponse); - const tokensLimit = model.maxContext; - - /* count response max token */ - const promptsToken = await countGptMessagesTokens(filterMessages); - maxToken = promptsToken + maxToken > tokensLimit ? tokensLimit - promptsToken : maxToken; - - if (maxToken <= 0) { - maxToken = 200; - } return maxToken; }; @@ -39,6 +30,7 @@ export const computedTemperature = ({ model: LLMModelItemType; temperature: number; }) => { + if (typeof model.maxTemperature !== 'number') return undefined; temperature = +(model.maxTemperature * (temperature / 10)).toFixed(2); temperature = Math.max(temperature, 0.01); @@ -87,3 +79,12 @@ export const llmCompletionsBodyFormat = ( return requestBody as InferCompletionsBody; }; + +export const llmStreamResponseToText = async (response: StreamChatType) => { + let answer = ''; + for await (const part of response) { + const content = part.choices?.[0]?.delta?.content || ''; + answer += content; + } + return answer; +}; diff --git a/packages/service/core/chat/utils.ts b/packages/service/core/chat/utils.ts index ed35466e88d4..b0b62170a7df 100644 --- a/packages/service/core/chat/utils.ts +++ b/packages/service/core/chat/utils.ts @@ -1,6 +1,9 @@ import { countGptMessagesTokens } from '../../common/string/tiktoken/index'; import type { + ChatCompletionAssistantMessageParam, ChatCompletionContentPart, + ChatCompletionContentPartRefusal, + ChatCompletionContentPartText, ChatCompletionMessageParam, SdkChatCompletionMessageParam } from '@fastgpt/global/core/ai/type.d'; @@ -11,36 +14,19 @@ import { serverRequestBaseUrl } from '../../common/api/serverRequest'; import { i18nT } from '../../../web/i18n/utils'; import { addLog } from '../../common/system/log'; -export const filterGPTMessageByMaxTokens = async ({ +export const filterGPTMessageByMaxContext = async ({ messages = [], - maxTokens + maxContext }: { messages: ChatCompletionMessageParam[]; - maxTokens: number; + maxContext: number; }) => { if (!Array.isArray(messages)) { return []; } - const rawTextLen = messages.reduce((sum, item) => { - if (typeof item.content === 'string') { - return sum + item.content.length; - } - if (Array.isArray(item.content)) { - return ( - sum + - item.content.reduce((sum, item) => { - if (item.type === 'text') { - return sum + item.text.length; - } - return sum; - }, 0) - ); - } - return sum; - }, 0); // If the text length is less than half of the maximum token, no calculation is required - if (rawTextLen < maxTokens * 0.5) { + if (messages.length < 4) { return messages; } @@ -52,7 +38,7 @@ export const filterGPTMessageByMaxTokens = async ({ const chatPrompts: ChatCompletionMessageParam[] = messages.slice(chatStartIndex); // reduce token of systemPrompt - maxTokens -= await countGptMessagesTokens(systemPrompts); + maxContext -= await countGptMessagesTokens(systemPrompts); // Save the last chat prompt(question) const question = chatPrompts.pop(); @@ -70,9 +56,9 @@ export const filterGPTMessageByMaxTokens = async ({ } const tokens = await countGptMessagesTokens([assistant, user]); - maxTokens -= tokens; + maxContext -= tokens; /* 整体 tokens 超出范围,截断 */ - if (maxTokens < 0) { + if (maxContext < 0) { break; } @@ -102,223 +88,324 @@ export const loadRequestMessages = async ({ useVision?: boolean; origin?: string; }) => { - // Load image to base64 - const loadImageToBase64 = async (messages: ChatCompletionContentPart[]) => { - return Promise.all( - messages.map(async (item) => { - if (item.type === 'image_url') { - // Remove url origin - const imgUrl = (() => { - if (origin && item.image_url.url.startsWith(origin)) { - return item.image_url.url.replace(origin, ''); - } - return item.image_url.url; - })(); + const replaceLinkUrl = (text: string) => { + const baseURL = process.env.FE_DOMAIN; + if (!baseURL) return text; + // 匹配 /api/system/img/xxx.xx 的图片链接,并追加 baseURL + return text.replace(/(\/api\/system\/img\/[^\s.]*\.[^\s]*)/g, (match, p1) => `${baseURL}${p1}`); + }; + const parseSystemMessage = ( + content: string | ChatCompletionContentPartText[] + ): string | ChatCompletionContentPartText[] | undefined => { + if (typeof content === 'string') { + if (!content) return; + return replaceLinkUrl(content); + } - // base64 image - if (imgUrl.startsWith('data:image/')) { - return item; + const arrayContent = content + .filter((item) => item.text) + .map((item) => ({ ...item, text: replaceLinkUrl(item.text) })); + if (arrayContent.length === 0) return; + return arrayContent; + }; + // Parse user content(text and img) Store history => api messages + const parseUserContent = async (content: string | ChatCompletionContentPart[]) => { + // Split question text and image + const parseStringWithImages = (input: string): ChatCompletionContentPart[] => { + if (!useVision || input.length > 500) { + return [{ type: 'text', text: input }]; + } + + // 正则表达式匹配图片URL + const imageRegex = + /(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi; + + const result: ChatCompletionContentPart[] = []; + + // 提取所有HTTPS图片URL并添加到result开头 + const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))]; + httpsImages.forEach((url) => { + result.push({ + type: 'image_url', + image_url: { + url: url } + }); + }); - try { - // If imgUrl is a local path, load image from local, and set url to base64 - if (imgUrl.startsWith('/') || process.env.MULTIPLE_DATA_TO_BASE64 === 'true') { - addLog.debug('Load image from local server', { - baseUrl: serverRequestBaseUrl, - requestUrl: imgUrl - }); - const response = await axios.get(imgUrl, { - baseURL: serverRequestBaseUrl, - responseType: 'arraybuffer', - proxy: false - }); - const base64 = Buffer.from(response.data, 'binary').toString('base64'); - const imageType = - getFileContentTypeFromHeader(response.headers['content-type']) || - guessBase64ImageType(base64); - - return { - ...item, - image_url: { - ...item.image_url, - url: `data:${imageType};base64,${base64}` - } - }; + // Too many images return text + if (httpsImages.length > 4) { + return [{ type: 'text', text: input }]; + } + + // 添加原始input作为文本 + result.push({ type: 'text', text: input }); + return result; + }; + // Load image to base64 + const loadUserContentImage = async (content: ChatCompletionContentPart[]) => { + return Promise.all( + content.map(async (item) => { + if (item.type === 'image_url') { + // Remove url origin + const imgUrl = (() => { + if (origin && item.image_url.url.startsWith(origin)) { + return item.image_url.url.replace(origin, ''); + } + return item.image_url.url; + })(); + + // base64 image + if (imgUrl.startsWith('data:image/')) { + return item; } - // 检查下这个图片是否可以被访问,如果不行的话,则过滤掉 - const response = await axios.head(imgUrl, { - timeout: 10000 - }); - if (response.status < 200 || response.status >= 400) { - addLog.info(`Filter invalid image: ${imgUrl}`); + try { + // If imgUrl is a local path, load image from local, and set url to base64 + if (imgUrl.startsWith('/') || process.env.MULTIPLE_DATA_TO_BASE64 === 'true') { + addLog.debug('Load image from local server', { + baseUrl: serverRequestBaseUrl, + requestUrl: imgUrl + }); + const response = await axios.get(imgUrl, { + baseURL: serverRequestBaseUrl, + responseType: 'arraybuffer', + proxy: false + }); + const base64 = Buffer.from(response.data, 'binary').toString('base64'); + const imageType = + getFileContentTypeFromHeader(response.headers['content-type']) || + guessBase64ImageType(base64); + + return { + ...item, + image_url: { + ...item.image_url, + url: `data:${imageType};base64,${base64}` + } + }; + } + + // 检查下这个图片是否可以被访问,如果不行的话,则过滤掉 + const response = await axios.head(imgUrl, { + timeout: 10000 + }); + if (response.status < 200 || response.status >= 400) { + addLog.info(`Filter invalid image: ${imgUrl}`); + return; + } + } catch (error) { return; } - } catch (error) { - return; } - } - return item; - }) - ).then((res) => res.filter(Boolean) as ChatCompletionContentPart[]); - }; - // Split question text and image - const parseStringWithImages = (input: string): ChatCompletionContentPart[] => { - if (!useVision || input.length > 500) { - return [{ type: 'text', text: input || '' }]; + return item; + }) + ).then((res) => res.filter(Boolean) as ChatCompletionContentPart[]); + }; + + if (content === undefined) return; + if (typeof content === 'string') { + if (content === '') return; + + const loadImageContent = await loadUserContentImage(parseStringWithImages(content)); + if (loadImageContent.length === 0) return; + return loadImageContent; } - // 正则表达式匹配图片URL - const imageRegex = - /(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi; + const result = ( + await Promise.all( + content.map(async (item) => { + if (item.type === 'text') { + if (item.text) return parseStringWithImages(item.text); + return; + } + if (item.type === 'file_url') return; // LLM not support file_url + if (item.type === 'image_url') { + // close vision, remove image_url + if (!useVision) return; + // remove empty image_url + if (!item.image_url.url) return; + } - const result: ChatCompletionContentPart[] = []; + return item; + }) + ) + ) + .flat() + .filter(Boolean) as ChatCompletionContentPart[]; - // 提取所有HTTPS图片URL并添加到result开头 - const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))]; - httpsImages.forEach((url) => { - result.push({ - type: 'image_url', - image_url: { - url: url - } - }); - }); + const loadImageContent = await loadUserContentImage(result); - // Too many images return text - if (httpsImages.length > 4) { - return [{ type: 'text', text: input || '' }]; - } + if (loadImageContent.length === 0) return; + return loadImageContent; + }; - // 添加原始input作为文本 - result.push({ type: 'text', text: input }); - return result; + const formatAssistantItem = (item: ChatCompletionAssistantMessageParam) => { + return { + role: item.role, + content: item.content, + function_call: item.function_call, + name: item.name, + refusal: item.refusal, + tool_calls: item.tool_calls + }; }; - // Parse user content(text and img) Store history => api messages - const parseUserContent = async (content: string | ChatCompletionContentPart[]) => { + const parseAssistantContent = ( + content: + | string + | (ChatCompletionContentPartText | ChatCompletionContentPartRefusal)[] + | null + | undefined + ) => { if (typeof content === 'string') { - return loadImageToBase64(parseStringWithImages(content)); + return content || ''; } + // 交互节点 + if (!content) return ''; - const result = await Promise.all( - content.map(async (item) => { - if (item.type === 'text') return parseStringWithImages(item.text); - if (item.type === 'file_url') return; // LLM not support file_url - - if (!item.image_url.url) return item; - - return item; - }) - ); + const result = content.filter((item) => item?.type === 'text'); + if (result.length === 0) return ''; - return loadImageToBase64(result.flat().filter(Boolean) as ChatCompletionContentPart[]); + return result.map((item) => item.text).join('\n'); }; - // format GPT messages, concat text messages - const clearInvalidMessages = (messages: ChatCompletionMessageParam[]) => { - return messages - .map((item) => { - if (item.role === ChatCompletionRequestMessageRoleEnum.System && !item.content) { - return; - } - if (item.role === ChatCompletionRequestMessageRoleEnum.User) { - if (item.content === undefined) return; - - if (typeof item.content === 'string') { - return { - ...item, - content: item.content.trim() - }; - } - - // array - if (item.content.length === 0) return; - if (item.content.length === 1 && item.content[0].type === 'text') { - return { - ...item, - content: item.content[0].text - }; - } - } - if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) { - if (item.content === undefined && !item.tool_calls && !item.function_call) return; - } + if (messages.length === 0) { + return Promise.reject(i18nT('common:core.chat.error.Messages empty')); + } - return item; - }) - .filter(Boolean) as ChatCompletionMessageParam[]; - }; - /* - Merge data for some consecutive roles - 1. Contiguous assistant and both have content, merge content - */ - const mergeConsecutiveMessages = ( - messages: ChatCompletionMessageParam[] - ): ChatCompletionMessageParam[] => { + // 合并相邻 role 的内容,只保留一个 role, content 变成数组。 assistant 的话,工具调用不合并。 + const mergeMessages = ((messages: ChatCompletionMessageParam[]): ChatCompletionMessageParam[] => { return messages.reduce((mergedMessages: ChatCompletionMessageParam[], currentMessage) => { const lastMessage = mergedMessages[mergedMessages.length - 1]; + if (!lastMessage) { + return [currentMessage]; + } + if ( - lastMessage && - currentMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant && + lastMessage.role === ChatCompletionRequestMessageRoleEnum.System && + currentMessage.role === ChatCompletionRequestMessageRoleEnum.System + ) { + const lastContent: ChatCompletionContentPartText[] = Array.isArray(lastMessage.content) + ? lastMessage.content + : [{ type: 'text', text: lastMessage.content || '' }]; + const currentContent: ChatCompletionContentPartText[] = Array.isArray( + currentMessage.content + ) + ? currentMessage.content + : [{ type: 'text', text: currentMessage.content || '' }]; + lastMessage.content = [...lastContent, ...currentContent]; + } // Handle user messages + else if ( + lastMessage.role === ChatCompletionRequestMessageRoleEnum.User && + currentMessage.role === ChatCompletionRequestMessageRoleEnum.User + ) { + const lastContent: ChatCompletionContentPart[] = Array.isArray(lastMessage.content) + ? lastMessage.content + : [{ type: 'text', text: lastMessage.content }]; + const currentContent: ChatCompletionContentPart[] = Array.isArray(currentMessage.content) + ? currentMessage.content + : [{ type: 'text', text: currentMessage.content }]; + lastMessage.content = [...lastContent, ...currentContent]; + } else if ( lastMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant && - typeof lastMessage.content === 'string' && - typeof currentMessage.content === 'string' + currentMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant ) { - lastMessage.content += currentMessage ? `\n${currentMessage.content}` : ''; + // Content 不为空的对象,或者是交互节点 + if ( + (typeof lastMessage.content === 'string' || + Array.isArray(lastMessage.content) || + lastMessage.interactive) && + (typeof currentMessage.content === 'string' || + Array.isArray(currentMessage.content) || + currentMessage.interactive) + ) { + const lastContent: (ChatCompletionContentPartText | ChatCompletionContentPartRefusal)[] = + Array.isArray(lastMessage.content) + ? lastMessage.content + : [{ type: 'text', text: lastMessage.content || '' }]; + const currentContent: ( + | ChatCompletionContentPartText + | ChatCompletionContentPartRefusal + )[] = Array.isArray(currentMessage.content) + ? currentMessage.content + : [{ type: 'text', text: currentMessage.content || '' }]; + + lastMessage.content = [...lastContent, ...currentContent]; + } else { + // 有其中一个没有 content,说明不是连续的文本输出 + mergedMessages.push(currentMessage); + } } else { mergedMessages.push(currentMessage); } return mergedMessages; }, []); - }; + })(messages); + + const loadMessages = ( + await Promise.all( + mergeMessages.map(async (item, i) => { + if (item.role === ChatCompletionRequestMessageRoleEnum.System) { + const content = parseSystemMessage(item.content); + if (!content) return; + return { + ...item, + content + }; + } else if (item.role === ChatCompletionRequestMessageRoleEnum.User) { + const content = await parseUserContent(item.content); + if (!content) { + return { + ...item, + content: 'null' + }; + } - if (messages.length === 0) { - return Promise.reject(i18nT('common:core.chat.error.Messages empty')); - } + const formatContent = (() => { + if (Array.isArray(content) && content.length === 1 && content[0].type === 'text') { + return content[0].text; + } + return content; + })(); - // filter messages file - const filterMessages = messages.map((item) => { - // If useVision=false, only retain text. - if ( - item.role === ChatCompletionRequestMessageRoleEnum.User && - Array.isArray(item.content) && - !useVision - ) { - return { - ...item, - content: item.content.filter((item) => item.type === 'text') - }; - } + return { + ...item, + content: formatContent + }; + } else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) { + if (item.tool_calls || item.function_call) { + return formatAssistantItem(item); + } - return item; - }); - - const loadMessages = (await Promise.all( - filterMessages.map(async (item) => { - if (item.role === ChatCompletionRequestMessageRoleEnum.User) { - return { - ...item, - content: await parseUserContent(item.content) - }; - } else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) { - // remove invalid field - return { - role: item.role, - content: item.content, - function_call: item.function_call, - name: item.name, - refusal: item.refusal, - tool_calls: item.tool_calls - }; - } else { - return item; - } - }) - )) as ChatCompletionMessageParam[]; + const parseContent = parseAssistantContent(item.content); + + // 如果内容为空,且前后不再是 assistant,需要补充成 null,避免丢失 user-assistant 的交互 + const formatContent = (() => { + const lastItem = mergeMessages[i - 1]; + const nextItem = mergeMessages[i + 1]; + if ( + parseContent === '' && + (lastItem?.role === ChatCompletionRequestMessageRoleEnum.Assistant || + nextItem?.role === ChatCompletionRequestMessageRoleEnum.Assistant) + ) { + return; + } + return parseContent || 'null'; + })(); + if (!formatContent) return; + + return { + ...formatAssistantItem(item), + content: formatContent + }; + } else { + return item; + } + }) + ) + ).filter(Boolean) as ChatCompletionMessageParam[]; - return mergeConsecutiveMessages( - clearInvalidMessages(loadMessages) - ) as SdkChatCompletionMessageParam[]; + return loadMessages as SdkChatCompletionMessageParam[]; }; diff --git a/packages/service/core/dataset/collection/controller.ts b/packages/service/core/dataset/collection/controller.ts index 061543274989..4ba57bb35669 100644 --- a/packages/service/core/dataset/collection/controller.ts +++ b/packages/service/core/dataset/collection/controller.ts @@ -19,7 +19,7 @@ import { predictDataLimitLength } from '../../../../global/core/dataset/utils'; import { mongoSessionRun } from '../../../common/mongo/sessionRun'; import { createTrainingUsage } from '../../../support/wallet/usage/controller'; import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; -import { getLLMModel, getVectorModel } from '../../ai/model'; +import { getLLMModel, getEmbeddingModel } from '../../ai/model'; import { pushDataListToTrainingQueue } from '../training/controller'; import { MongoImage } from '../../../common/file/image/schema'; import { hashStr } from '@fastgpt/global/common/string/tools'; @@ -93,7 +93,7 @@ export const createCollectionAndInsertData = async ({ tmbId, appName: usageName, billSource: UsageSourceEnum.training, - vectorModel: getVectorModel(dataset.vectorModel)?.name, + vectorModel: getEmbeddingModel(dataset.vectorModel)?.name, agentModel: getLLMModel(dataset.agentModel)?.name, session }); diff --git a/packages/service/core/dataset/data/dataTextSchema.ts b/packages/service/core/dataset/data/dataTextSchema.ts index e0564ed2b61b..f23a7f7d09e5 100644 --- a/packages/service/core/dataset/data/dataTextSchema.ts +++ b/packages/service/core/dataset/data/dataTextSchema.ts @@ -33,7 +33,18 @@ const DatasetDataTextSchema = new Schema({ }); try { - DatasetDataTextSchema.index({ teamId: 1, datasetId: 1, fullTextToken: 'text' }); + DatasetDataTextSchema.index( + { teamId: 1, datasetId: 1, fullTextToken: 'text' }, + { + name: 'teamId_1_datasetId_1_fullTextToken_text', + default_language: 'none', + collation: { + locale: 'simple', // 使用简单匹配规则 + strength: 2, // 忽略大小写 + caseLevel: false // 进一步确保大小写不敏感 + } + } + ); DatasetDataTextSchema.index({ dataId: 1 }, { unique: true }); } catch (error) { console.log(error); diff --git a/packages/service/core/dataset/search/controller.ts b/packages/service/core/dataset/search/controller.ts index 7a3ea9a3f796..df458f6320b9 100644 --- a/packages/service/core/dataset/search/controller.ts +++ b/packages/service/core/dataset/search/controller.ts @@ -5,10 +5,9 @@ import { } from '@fastgpt/global/core/dataset/constants'; import { recallFromVectorStore } from '../../../common/vectorStore/controller'; import { getVectorsByText } from '../../ai/embedding'; -import { getVectorModel } from '../../ai/model'; +import { getEmbeddingModel, getDefaultRerankModel } from '../../ai/model'; import { MongoDatasetData } from '../data/schema'; import { - DatasetDataSchemaType, DatasetDataTextSchemaType, SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; @@ -67,7 +66,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) { /* init params */ searchMode = DatasetSearchModeMap[searchMode] ? searchMode : DatasetSearchModeEnum.embedding; - usingReRank = usingReRank && global.reRankModels.length > 0; + usingReRank = usingReRank && !!getDefaultRerankModel(); // Compatible with topk limit let set = new Set(); @@ -253,7 +252,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) { filterCollectionIdList?: string[]; }) => { const { vectors, tokens } = await getVectorsByText({ - model: getVectorModel(model), + model: getEmbeddingModel(model), input: query, type: 'query' }); @@ -348,119 +347,6 @@ export async function searchDatasetData(props: SearchDatasetDataProps) { }; } - const searchResults = ( - await Promise.all( - datasetIds.map(async (id) => { - return MongoDatasetData.aggregate( - [ - { - $match: { - teamId: new Types.ObjectId(teamId), - datasetId: new Types.ObjectId(id), - $text: { $search: jiebaSplit({ text: query }) }, - ...(filterCollectionIdList - ? { - collectionId: { - $in: filterCollectionIdList.map((id) => new Types.ObjectId(id)) - } - } - : {}), - ...(forbidCollectionIdList && forbidCollectionIdList.length > 0 - ? { - collectionId: { - $nin: forbidCollectionIdList.map((id) => new Types.ObjectId(id)) - } - } - : {}) - } - }, - { - $sort: { - score: { $meta: 'textScore' } - } - }, - { - $limit: limit - }, - { - $project: { - _id: 1, - datasetId: 1, - collectionId: 1, - updateTime: 1, - q: 1, - a: 1, - chunkIndex: 1, - score: { $meta: 'textScore' } - } - } - ], - { - ...readFromSecondary - } - ); - }) - ) - ).flat() as (DatasetDataSchemaType & { score: number })[]; - - // Get data and collections - const collections = await MongoDatasetCollection.find( - { - _id: { $in: searchResults.map((item) => item.collectionId) } - }, - '_id name fileId rawLink externalFileId externalFileUrl', - { ...readFromSecondary } - ).lean(); - - return { - fullTextRecallResults: searchResults - .map((data, index) => { - const collection = collections.find( - (col) => String(col._id) === String(data.collectionId) - ); - if (!collection) { - console.log('Collection is not found', data); - return; - } - - return { - id: String(data._id), - datasetId: String(data.datasetId), - collectionId: String(data.collectionId), - updateTime: data.updateTime, - q: data.q, - a: data.a, - chunkIndex: data.chunkIndex, - indexes: data.indexes, - ...getCollectionSourceData(collection), - score: [{ type: SearchScoreTypeEnum.fullText, value: data.score ?? 0, index }] - }; - }) - .filter(Boolean) as SearchDataResponseItemType[], - tokenLen: 0 - }; - }; - const fullTextRecall2 = async ({ - query, - limit, - filterCollectionIdList, - forbidCollectionIdList - }: { - query: string; - limit: number; - filterCollectionIdList?: string[]; - forbidCollectionIdList: string[]; - }): Promise<{ - fullTextRecallResults: SearchDataResponseItemType[]; - tokenLen: number; - }> => { - if (limit === 0) { - return { - fullTextRecallResults: [], - tokenLen: 0 - }; - } - const searchResults = ( await Promise.all( datasetIds.map(async (id) => { @@ -637,7 +523,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) { filterCollectionIdList }), // FullText tmp - fullTextRecall2({ + fullTextRecall({ query, limit: fullTextLimit, filterCollectionIdList, diff --git a/packages/service/core/dataset/training/controller.ts b/packages/service/core/dataset/training/controller.ts index fdae75d42f63..a8bbe9417aaf 100644 --- a/packages/service/core/dataset/training/controller.ts +++ b/packages/service/core/dataset/training/controller.ts @@ -7,7 +7,7 @@ import type { import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constants'; import { simpleText } from '@fastgpt/global/common/string/tools'; import { ClientSession } from '../../../common/mongo'; -import { getLLMModel, getVectorModel } from '../../ai/model'; +import { getLLMModel, getEmbeddingModel } from '../../ai/model'; import { addLog } from '../../../common/system/log'; import { getCollectionWithDataset } from '../controller'; import { mongoSessionRun } from '../../../common/mongo/sessionRun'; @@ -70,7 +70,7 @@ export async function pushDataListToTrainingQueue({ if (!agentModelData) { return Promise.reject(`File model ${agentModel} is inValid`); } - const vectorModelData = getVectorModel(vectorModel); + const vectorModelData = getEmbeddingModel(vectorModel); if (!vectorModelData) { return Promise.reject(`Vector model ${vectorModel} is inValid`); } diff --git a/packages/service/core/workflow/dispatch/agent/classifyQuestion.ts b/packages/service/core/workflow/dispatch/agent/classifyQuestion.ts index 12091d3e299f..034c483f6883 100644 --- a/packages/service/core/workflow/dispatch/agent/classifyQuestion.ts +++ b/packages/service/core/workflow/dispatch/agent/classifyQuestion.ts @@ -13,7 +13,7 @@ import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/ import { replaceVariable } from '@fastgpt/global/common/string/tools'; import { Prompt_CQJson } from '@fastgpt/global/core/ai/prompt/agent'; import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; -import { ModelTypeEnum, getLLMModel } from '../../../ai/model'; +import { getLLMModel } from '../../../ai/model'; import { getHistories } from '../utils'; import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; @@ -22,6 +22,7 @@ import { getHandleId } from '@fastgpt/global/core/workflow/utils'; import { loadRequestMessages } from '../../../chat/utils'; import { llmCompletionsBodyFormat } from '../../../ai/utils'; import { addLog } from '../../../../common/system/log'; +import { ModelTypeEnum } from '../../../../../global/core/ai/model'; type Props = ModuleDispatchProps<{ [NodeInputKeyEnum.aiModel]: string; diff --git a/packages/service/core/workflow/dispatch/agent/extract.ts b/packages/service/core/workflow/dispatch/agent/extract.ts index b4067ed39d38..431bdb4f6bc3 100644 --- a/packages/service/core/workflow/dispatch/agent/extract.ts +++ b/packages/service/core/workflow/dispatch/agent/extract.ts @@ -1,5 +1,5 @@ import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; -import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../chat/utils'; +import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../chat/utils'; import type { ChatItemType } from '@fastgpt/global/core/chat/type.d'; import { countMessagesTokens, @@ -16,7 +16,7 @@ import { Prompt_ExtractJson } from '@fastgpt/global/core/ai/prompt/agent'; import { replaceVariable, sliceJsonStr } from '@fastgpt/global/common/string/tools'; import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import { getHistories } from '../utils'; -import { ModelTypeEnum, getLLMModel } from '../../../ai/model'; +import { getLLMModel } from '../../../ai/model'; import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'; import json5 from 'json5'; import { @@ -28,6 +28,7 @@ import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/co import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt'; import { llmCompletionsBodyFormat } from '../../../ai/utils'; +import { ModelTypeEnum } from '../../../../../global/core/ai/model'; type Props = ModuleDispatchProps<{ [NodeInputKeyEnum.history]?: ChatItemType[]; @@ -174,9 +175,9 @@ ${description ? `- ${description}` : ''} } ]; const adaptMessages = chats2GPTMessages({ messages, reserveId: false }); - const filterMessages = await filterGPTMessageByMaxTokens({ + const filterMessages = await filterGPTMessageByMaxContext({ messages: adaptMessages, - maxTokens: extractModel.maxContext + maxContext: extractModel.maxContext }); const requestMessages = await loadRequestMessages({ messages: filterMessages, diff --git a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts index 92cdfa9cd268..fa7e27187fb1 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts @@ -1,5 +1,5 @@ import { createChatCompletion } from '../../../../ai/config'; -import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils'; +import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils'; import { ChatCompletion, StreamChatType, @@ -172,10 +172,14 @@ export const runToolWithFunctionCall = async ( }; }); + const max_tokens = computedMaxToken({ + model: toolModel, + maxToken + }); const filterMessages = ( - await filterGPTMessageByMaxTokens({ + await filterGPTMessageByMaxContext({ messages, - maxTokens: toolModel.maxContext - 300 // filter token. not response maxToken + maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken }) ).map((item) => { if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant && item.function_call) { @@ -190,16 +194,11 @@ export const runToolWithFunctionCall = async ( } return item; }); - const [requestMessages, max_tokens] = await Promise.all([ + const [requestMessages] = await Promise.all([ loadRequestMessages({ messages: filterMessages, useVision: toolModel.vision && aiChatVision, origin: requestOrigin - }), - computedMaxToken({ - model: toolModel, - maxToken, - filterMessages }) ]); const requestBody = llmCompletionsBodyFormat( diff --git a/packages/service/core/workflow/dispatch/agent/runTool/index.ts b/packages/service/core/workflow/dispatch/agent/runTool/index.ts index 590e9ab0824c..57792acc5c39 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/index.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/index.ts @@ -4,7 +4,7 @@ import type { DispatchNodeResultType, RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type'; -import { ModelTypeEnum, getLLMModel } from '../../../../ai/model'; +import { getLLMModel } from '../../../../ai/model'; import { filterToolNodeIdByEdges, getHistories } from '../../utils'; import { runToolWithToolChoice } from './toolChoice'; import { DispatchToolModuleProps, ToolNodeItemType } from './type.d'; @@ -30,6 +30,7 @@ import { parseUrlToFileType } from '@fastgpt/global/common/file/tools'; import { Prompt_DocumentQuote } from '@fastgpt/global/core/ai/prompt/AIChat'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { postTextCensor } from '../../../../../common/api/requestPlusApi'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; type Response = DispatchNodeResultType<{ [NodeOutputKeyEnum.answerText]: string; diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts index 7f380b55d787..331496852015 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts @@ -1,5 +1,5 @@ import { createChatCompletion } from '../../../../ai/config'; -import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils'; +import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils'; import { ChatCompletion, StreamChatType, @@ -196,21 +196,20 @@ export const runToolWithPromptCall = async ( return Promise.reject('Prompt call invalid input'); } - const filterMessages = await filterGPTMessageByMaxTokens({ + const max_tokens = computedMaxToken({ + model: toolModel, + maxToken + }); + const filterMessages = await filterGPTMessageByMaxContext({ messages, - maxTokens: toolModel.maxContext - 500 // filter token. not response maxToken + maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken }); - const [requestMessages, max_tokens] = await Promise.all([ + const [requestMessages] = await Promise.all([ loadRequestMessages({ messages: filterMessages, useVision: toolModel.vision && aiChatVision, origin: requestOrigin - }), - computedMaxToken({ - model: toolModel, - maxToken, - filterMessages }) ]); const requestBody = llmCompletionsBodyFormat( diff --git a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts index 71d5f40213f0..b2b845f75de3 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts @@ -1,5 +1,5 @@ import { createChatCompletion } from '../../../../ai/config'; -import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils'; +import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils'; import { ChatCompletion, ChatCompletionMessageToolCall, @@ -228,11 +228,16 @@ export const runToolWithToolChoice = async ( }; }); + const max_tokens = computedMaxToken({ + model: toolModel, + maxToken + }); + // Filter histories by maxToken const filterMessages = ( - await filterGPTMessageByMaxTokens({ + await filterGPTMessageByMaxContext({ messages, - maxTokens: toolModel.maxContext - 300 // filter token. not response maxToken + maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken }) ).map((item) => { if (item.role === 'assistant' && item.tool_calls) { @@ -248,16 +253,11 @@ export const runToolWithToolChoice = async ( return item; }); - const [requestMessages, max_tokens] = await Promise.all([ + const [requestMessages] = await Promise.all([ loadRequestMessages({ messages: filterMessages, useVision: toolModel.vision && aiChatVision, origin: requestOrigin - }), - computedMaxToken({ - model: toolModel, - maxToken, - filterMessages }) ]); const requestBody = llmCompletionsBodyFormat( @@ -272,7 +272,7 @@ export const runToolWithToolChoice = async ( }, toolModel ); - // console.log(JSON.stringify(requestBody, null, 2), '==requestBody'); + // console.log(JSON.stringify(requestMessages, null, 2), '==requestBody'); /* Run llm */ const { response: aiResponse, diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/chat/oneapi.ts index d20d1bec72a5..4b8cc865c34b 100644 --- a/packages/service/core/workflow/dispatch/chat/oneapi.ts +++ b/packages/service/core/workflow/dispatch/chat/oneapi.ts @@ -1,5 +1,5 @@ import type { NextApiResponse } from 'next'; -import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../chat/utils'; +import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../chat/utils'; import type { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type.d'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; @@ -33,7 +33,7 @@ import type { AIChatNodeProps } from '@fastgpt/global/core/workflow/runtime/type import { replaceVariable } from '@fastgpt/global/common/string/tools'; import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; import { responseWriteController } from '../../../../common/response'; -import { getLLMModel, ModelTypeEnum } from '../../../ai/model'; +import { getLLMModel } from '../../../ai/model'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; @@ -47,6 +47,7 @@ import { AiChatQuoteRoleType } from '@fastgpt/global/core/workflow/template/syst import { getFileContentFromLinks, getHistoryFileLinks } from '../tools/readFiles'; import { parseUrlToFileType } from '@fastgpt/global/common/file/tools'; import { i18nT } from '../../../../../web/i18n/utils'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; export type ChatProps = ModuleDispatchProps< AIChatNodeProps & { @@ -57,6 +58,7 @@ export type ChatProps = ModuleDispatchProps< >; export type ChatResponse = DispatchNodeResultType<{ [NodeOutputKeyEnum.answerText]: string; + [NodeOutputKeyEnum.reasoningText]?: string; [NodeOutputKeyEnum.history]: ChatItemType[]; }>; @@ -86,22 +88,24 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise { - // censor model and system key if (modelConstantsData.censor && !externalProvider.openaiAccount?.key) { return postTextCensor({ text: `${systemPrompt} @@ -148,18 +158,11 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise { + const { answerText, reasoningText } = await (async () => { if (res && isStreamResponse) { // sse response - const { answer } = await streamResponse({ + const { answer, reasoning } = await streamResponse({ res, stream: response, + aiChatReasoning, workflowStreamResponse }); return { - answerText: answer + answerText: answer, + reasoningText: reasoning }; } else { const unStreamResponse = response as ChatCompletion; const answer = unStreamResponse.choices?.[0]?.message?.content || ''; - + const reasoning = aiChatReasoning + ? // @ts-ignore + unStreamResponse.choices?.[0]?.message?.reasoning_content || '' + : ''; if (stream) { // Some models do not support streaming workflowStreamResponse?.({ event: SseResponseEventEnum.fastAnswer, data: textAdaptGptResponse({ - text: answer + text: answer, + reasoning_content: reasoning }) }); } return { - answerText: answer + answerText: answer, + reasoningText: reasoning }; } })(); @@ -240,6 +250,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise, 'nodeResponse' @@ -239,18 +241,28 @@ export async function dispatchWorkFlow(data: Props): Promise item.key === NodeInputKeyEnum.aiChatIsResponseText)?.value ?? true; - if (isResponseAnswerText) { + } else { + if (reasoningText) { chatAssistantResponse.push({ - type: ChatItemValueTypeEnum.text, - text: { - content: answerText + type: ChatItemValueTypeEnum.reasoning, + reasoning: { + content: reasoningText } }); } + if (answerText) { + // save assistant text response + const isResponseAnswerText = + inputs.find((item) => item.key === NodeInputKeyEnum.aiChatIsResponseText)?.value ?? true; + if (isResponseAnswerText) { + chatAssistantResponse.push({ + type: ChatItemValueTypeEnum.text, + text: { + content: answerText + } + }); + } + } } if (rewriteHistories) { diff --git a/packages/service/core/workflow/dispatch/tools/http468.ts b/packages/service/core/workflow/dispatch/tools/http468.ts index af8b6982fe9f..5ea110b88f2c 100644 --- a/packages/service/core/workflow/dispatch/tools/http468.ts +++ b/packages/service/core/workflow/dispatch/tools/http468.ts @@ -244,7 +244,6 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise { + try { + const result = await authCert({ req, authToken: true }); + const user = await MongoUser.findOne({ + _id: result.userId + }); + + if (user && user.username !== 'root') { + return Promise.reject(ERROR_ENUM.unAuthorization); + } + return result; + } catch (error) { + throw error; + } +}; diff --git a/packages/service/support/wallet/usage/schema.ts b/packages/service/support/wallet/usage/schema.ts index 7416d6b45725..b462b9af90f4 100644 --- a/packages/service/support/wallet/usage/schema.ts +++ b/packages/service/support/wallet/usage/schema.ts @@ -61,7 +61,8 @@ const UsageSchema = new Schema({ }); try { - UsageSchema.index({ teamId: 1, tmbId: 1, source: 1, time: -1 }); + UsageSchema.index({ teamId: 1, time: 1, tmbId: 1, source: 1 }); + UsageSchema.index({ teamId: 1, time: 1, appName: 1 }); // timer task. clear dead team // UsageSchema.index({ teamId: 1, time: -1 }); diff --git a/packages/service/support/wallet/usage/utils.ts b/packages/service/support/wallet/usage/utils.ts index d4c21347b0e1..fef3ce934bb7 100644 --- a/packages/service/support/wallet/usage/utils.ts +++ b/packages/service/support/wallet/usage/utils.ts @@ -1,5 +1,5 @@ -import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; -import { ModelTypeEnum, getModelMap } from '../../../core/ai/model'; +import { findAIModel } from '../../../core/ai/model'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; export const formatModelChars2Points = ({ model, @@ -14,7 +14,7 @@ export const formatModelChars2Points = ({ modelType: `${ModelTypeEnum}`; multiple?: number; }) => { - const modelData = getModelMap?.[modelType]?.(model) as LLMModelItemType; + const modelData = findAIModel(model); if (!modelData) { return { totalPoints: 0, diff --git a/packages/service/type.d.ts b/packages/service/type.d.ts index 11c7a6c69883..d2aa22e5673c 100644 --- a/packages/service/type.d.ts +++ b/packages/service/type.d.ts @@ -1,9 +1,9 @@ import { FastGPTFeConfigsType, SystemEnvType } from '@fastgpt/global/common/system/types'; import { - AudioSpeechModelType, + TTSModelType, ReRankModelItemType, STTModelType, - VectorModelItemType, + EmbeddingModelItemType, LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; @@ -12,17 +12,11 @@ import { Worker } from 'worker_threads'; declare global { var systemInitBufferId: string | undefined; + var systemVersion: string; var feConfigs: FastGPTFeConfigsType; var systemEnv: SystemEnvType; var subPlans: SubPlanType | undefined; - var llmModels: LLMModelItemType[]; - var llmModelPriceType: 'IO' | 'Tokens'; - var vectorModels: VectorModelItemType[]; - var audioSpeechModels: AudioSpeechModelType[]; - var whisperModel: STTModelType; - var reRankModels: ReRankModelItemType[]; - var workerPoll: Record; } diff --git a/packages/web/components/common/DateRangePicker/index.tsx b/packages/web/components/common/DateRangePicker/index.tsx index 30fe8c989e57..b033cfab8628 100644 --- a/packages/web/components/common/DateRangePicker/index.tsx +++ b/packages/web/components/common/DateRangePicker/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo, useRef } from 'react'; +import React, { useState, useMemo, useRef, useEffect } from 'react'; import { Box, Card, Flex, useTheme, useOutsideClick, Button } from '@chakra-ui/react'; import { addDays, format } from 'date-fns'; import { type DateRange, DayPicker } from 'react-day-picker'; @@ -14,12 +14,14 @@ const DateRangePicker = ({ defaultDate = { from: addDays(new Date(), -30), to: new Date() - } + }, + dateRange }: { onChange?: (date: DateRange) => void; onSuccess?: (date: DateRange) => void; position?: 'bottom' | 'top'; defaultDate?: DateRange; + dateRange?: DateRange; }) => { const { t } = useTranslation(); const theme = useTheme(); @@ -27,6 +29,12 @@ const DateRangePicker = ({ const [range, setRange] = useState(defaultDate); const [showSelected, setShowSelected] = useState(false); + useEffect(() => { + if (dateRange) { + setRange(dateRange); + } + }, [dateRange]); + const formatSelected = useMemo(() => { if (range?.from && range.to) { return `${format(range.from, 'y-MM-dd')} ~ ${format(range.to, 'y-MM-dd')}`; @@ -49,7 +57,7 @@ const DateRangePicker = ({ py={1} borderRadius={'sm'} cursor={'pointer'} - bg={'myGray.100'} + bg={'myGray.50'} fontSize={'sm'} onClick={() => setShowSelected(true)} > @@ -93,7 +101,7 @@ const DateRangePicker = ({ date.to = date.from; } setRange(date); - onChange && onChange(date); + onChange?.(date); }} footer={ @@ -108,7 +116,7 @@ const DateRangePicker = ({ + + ); + } + + // Quote + if (props.href === 'QUOTE' && typeof children?.[0] === 'string') { + return ( + runAsync(String(children))} + > + + + + + + + + {quoteData?.collection && ( + + )} + + + + + + + + + + ); + } + + return {children}; +}; + +export default A; diff --git a/projects/app/src/components/Markdown/codeBlock/Audio.tsx b/projects/app/src/components/Markdown/codeBlock/Audio.tsx new file mode 100644 index 000000000000..a1510bc4d4fd --- /dev/null +++ b/projects/app/src/components/Markdown/codeBlock/Audio.tsx @@ -0,0 +1,31 @@ +import React, { useEffect } from 'react'; +import { Box } from '@chakra-ui/react'; +import { useMarkdownWidth } from '../hooks'; + +const AudioBlock = ({ code: audioUrl }: { code: string }) => { + const { width, Ref } = useMarkdownWidth(); + + useEffect(() => { + fetch(audioUrl?.trim(), { + mode: 'cors', + credentials: 'omit' + }) + .then((response) => response.blob()) + .then((blob) => { + const url = URL.createObjectURL(blob); + const audio = document.getElementById('player'); + audio?.setAttribute('src', url); + }) + .catch((err) => { + console.log(err); + }); + }, [audioUrl]); + + return ( + + + ); +}; + +export default AudioBlock; diff --git a/projects/app/src/components/Markdown/CodeLight.tsx b/projects/app/src/components/Markdown/codeBlock/CodeLight.tsx similarity index 99% rename from projects/app/src/components/Markdown/CodeLight.tsx rename to projects/app/src/components/Markdown/codeBlock/CodeLight.tsx index 81bcbab0e109..5d2db6971040 100644 --- a/projects/app/src/components/Markdown/CodeLight.tsx +++ b/projects/app/src/components/Markdown/codeBlock/CodeLight.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { Box, Flex } from '@chakra-ui/react'; import Icon from '@fastgpt/web/components/common/Icon'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useTranslation } from 'next-i18next'; export const codeLight: { [key: string]: React.CSSProperties } = { diff --git a/projects/app/src/components/Markdown/codeBlock/Video.tsx b/projects/app/src/components/Markdown/codeBlock/Video.tsx new file mode 100644 index 000000000000..459f5bcb3f85 --- /dev/null +++ b/projects/app/src/components/Markdown/codeBlock/Video.tsx @@ -0,0 +1,31 @@ +import React, { useEffect } from 'react'; +import { Box } from '@chakra-ui/react'; +import { useMarkdownWidth } from '../hooks'; + +const VideoBlock = ({ code: videoUrl }: { code: string }) => { + const { width, Ref } = useMarkdownWidth(); + + useEffect(() => { + fetch(videoUrl?.trim(), { + mode: 'cors', + credentials: 'omit' + }) + .then((response) => response.blob()) + .then((blob) => { + const url = URL.createObjectURL(blob); + const video = document.getElementById('player'); + video?.setAttribute('src', url); + }) + .catch((err) => { + console.log(err); + }); + }, [videoUrl]); + + return ( + + + ); +}; + +export default VideoBlock; diff --git a/projects/app/src/components/Markdown/codeBlock/iframe-html.tsx b/projects/app/src/components/Markdown/codeBlock/iframe-html.tsx index 97671cab932e..d8d81bbb4585 100644 --- a/projects/app/src/components/Markdown/codeBlock/iframe-html.tsx +++ b/projects/app/src/components/Markdown/codeBlock/iframe-html.tsx @@ -12,11 +12,11 @@ import { ModalCloseButton } from '@chakra-ui/react'; import Icon from '@fastgpt/web/components/common/Icon'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useTranslation } from 'next-i18next'; import { useMarkdownWidth } from '../hooks'; import type { IconNameType } from '@fastgpt/web/components/common/Icon/type.d'; -import { codeLight } from '../CodeLight'; +import { codeLight } from './CodeLight'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; const StyledButton = ({ diff --git a/projects/app/src/components/Markdown/index.tsx b/projects/app/src/components/Markdown/index.tsx index 4aed17b97631..f8ae9ecab964 100644 --- a/projects/app/src/components/Markdown/index.tsx +++ b/projects/app/src/components/Markdown/index.tsx @@ -10,23 +10,21 @@ import RehypeExternalLinks from 'rehype-external-links'; import styles from './index.module.scss'; import dynamic from 'next/dynamic'; -import { Link, Button, Box } from '@chakra-ui/react'; -import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; -import { useTranslation } from 'next-i18next'; -import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus'; -import MyIcon from '@fastgpt/web/components/common/Icon'; -import { MARKDOWN_QUOTE_SIGN } from '@fastgpt/global/core/chat/constants'; +import { Box } from '@chakra-ui/react'; import { CodeClassNameEnum } from './utils'; -const CodeLight = dynamic(() => import('./CodeLight'), { ssr: false }); +const CodeLight = dynamic(() => import('./codeBlock/CodeLight'), { ssr: false }); const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'), { ssr: false }); const MdImage = dynamic(() => import('./img/Image'), { ssr: false }); const EChartsCodeBlock = dynamic(() => import('./img/EChartsCodeBlock'), { ssr: false }); const IframeCodeBlock = dynamic(() => import('./codeBlock/Iframe'), { ssr: false }); const IframeHtmlCodeBlock = dynamic(() => import('./codeBlock/iframe-html'), { ssr: false }); +const VideoBlock = dynamic(() => import('./codeBlock/Video'), { ssr: false }); +const AudioBlock = dynamic(() => import('./codeBlock/Audio'), { ssr: false }); const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false }); const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false }); +const A = dynamic(() => import('./A'), { ssr: false }); type Props = { source?: string; @@ -74,7 +72,10 @@ const MarkdownRender = ({ source = '', showAnimation, isDisabled, forbidZhFormat '$1$3 $2$4' ) // 处理引用标记 - .replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1'); + .replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1') + // 处理 [quote:id] 格式引用,将 [quote:675934a198f46329dfc6d05a] 转换为 [675934a198f46329dfc6d05a]() + .replace(/\[quote:?\s*([a-f0-9]{24})\](?!\()/gi, '[$1](QUOTE)') + .replace(/\[([a-f0-9]{24})\](?!\()/g, '[$1](QUOTE)'); // 还原 URL const finalText = textWithSpaces.replace( @@ -140,6 +141,12 @@ function Code(e: any) { ); } + if (codeType === CodeClassNameEnum.video) { + return ; + } + if (codeType === CodeClassNameEnum.audio) { + return ; + } return ( @@ -155,53 +162,6 @@ function Image({ src }: { src?: string }) { return ; } -function A({ children, ...props }: any) { - const { t } = useTranslation(); - - // empty href link - if (!props.href && typeof children?.[0] === 'string') { - const text = useMemo(() => String(children), [children]); - - return ( - - - - ); - } - - // quote link(未使用) - if (children?.length === 1 && typeof children?.[0] === 'string') { - const text = String(children); - if (text === MARKDOWN_QUOTE_SIGN && props.href) { - return ( - - getCollectionSourceAndOpen(props.href)} - /> - - ); - } - } - - return {children}; -} - function RewritePre({ children }: any) { const modifiedChildren = React.Children.map(children, (child) => { if (React.isValidElement(child)) { diff --git a/projects/app/src/components/Markdown/utils.ts b/projects/app/src/components/Markdown/utils.ts index 50204eb4359f..00992836ff19 100644 --- a/projects/app/src/components/Markdown/utils.ts +++ b/projects/app/src/components/Markdown/utils.ts @@ -7,7 +7,9 @@ export enum CodeClassNameEnum { files = 'files', latex = 'latex', iframe = 'iframe', - html = 'html' + html = 'html', + video = 'video', + audio = 'audio' } function htmlTableToLatex(html: string) { diff --git a/projects/app/src/components/Select/AIModelSelector.tsx b/projects/app/src/components/Select/AIModelSelector.tsx index cb90b4b0f9e8..852c25d580c0 100644 --- a/projects/app/src/components/Select/AIModelSelector.tsx +++ b/projects/app/src/components/Select/AIModelSelector.tsx @@ -3,8 +3,8 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'next-i18next'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import MySelect, { SelectProps } from '@fastgpt/web/components/common/MySelect'; -import { HUGGING_FACE_ICON, LOGO_ICON } from '@fastgpt/global/common/system/constants'; -import { Box, Flex, HStack, useDisclosure } from '@chakra-ui/react'; +import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants'; +import { Box, Flex, HStack } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import dynamic from 'next/dynamic'; @@ -22,7 +22,8 @@ type Props = SelectProps & { const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { const { t } = useTranslation(); - const { feConfigs, llmModelList, vectorModelList } = useSystemStore(); + const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = + useSystemStore(); const avatarSize = useMemo(() => { const size = { @@ -35,7 +36,16 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { }, [props.size]); const avatarList = list.map((item) => { - const modelData = getModelFromList([...llmModelList, ...vectorModelList], item.value); + const modelData = getModelFromList( + [ + ...llmModelList, + ...embeddingModelList, + ...ttsModelList, + ...sttModelList, + ...reRankModelList + ], + item.value + ); return { value: item.value, @@ -54,20 +64,6 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { }; }); - const expandList = useMemo(() => { - return feConfigs?.show_pay - ? avatarList.concat({ - label: ( - - - {t('common:support.user.Price')} - - ), - value: 'price' - }) - : avatarList; - }, [feConfigs.show_pay, avatarList, avatarSize, t]); - return ( { { if (e === 'price') { @@ -100,7 +97,8 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { }; const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { const { t } = useTranslation(); - const { llmModelList, vectorModelList } = useSystemStore(); + const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = + useSystemStore(); const [value, setValue] = useState([]); const avatarSize = useMemo(() => { @@ -136,7 +134,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => })); for (const item of list) { - const modelData = getModelFromList([...llmModelList, ...vectorModelList], item.value); + const modelData = getModelFromList([...llmModelList, ...embeddingModelList], item.value); const provider = renderList.find((item) => item.value === (modelData?.provider || 'Other')) ?? renderList[renderList.length - 1]; @@ -148,7 +146,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => } return renderList.filter((item) => item.children.length > 0); - }, [avatarSize, list, llmModelList, t, vectorModelList]); + }, [avatarSize, list, llmModelList, t, embeddingModelList]); const onSelect = useCallback( (e: string[]) => { @@ -158,7 +156,16 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => ); const SelectedModel = useMemo(() => { - const modelData = getModelFromList([...llmModelList, ...vectorModelList], props.value); + const modelData = getModelFromList( + [ + ...llmModelList, + ...embeddingModelList, + ...ttsModelList, + ...sttModelList, + ...reRankModelList + ], + props.value + ); setValue([modelData.provider, props.value]); @@ -174,7 +181,15 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {modelData?.name} ); - }, [avatarSize, llmModelList, props.value, vectorModelList]); + }, [ + llmModelList, + embeddingModelList, + ttsModelList, + sttModelList, + reRankModelList, + props.value, + avatarSize + ]); return ( value={value} rowMinWidth="160px" ButtonProps={{ - isDisabled: !!disableTip + isDisabled: !!disableTip, + h: '40px', + ...props }} /> diff --git a/projects/app/src/components/core/ai/AISettingModal/index.tsx b/projects/app/src/components/core/ai/AISettingModal/index.tsx index 2d6b17e863de..5059119c78ac 100644 --- a/projects/app/src/components/core/ai/AISettingModal/index.tsx +++ b/projects/app/src/components/core/ai/AISettingModal/index.tsx @@ -72,6 +72,7 @@ const AIChatSettingsModal = ({ defaultValues: defaultData }); const model = watch('model'); + const reasoning = watch(NodeInputKeyEnum.aiChatReasoning); const showResponseAnswerText = watch(NodeInputKeyEnum.aiChatIsResponseText) !== undefined; const showVisionSwitch = watch(NodeInputKeyEnum.aiChatVision) !== undefined; const showMaxHistoriesSlider = watch('maxHistories') !== undefined; @@ -80,8 +81,12 @@ const AIChatSettingsModal = ({ const temperature = watch('temperature'); const useVision = watch('aiChatVision'); - const selectedModel = getWebLLMModel(model); + const selectedModel = useMemo(() => { + return getWebLLMModel(model); + }, [model]); const llmSupportVision = !!selectedModel?.vision; + const llmSupportTemperature = typeof selectedModel?.maxTemperature === 'number'; + const llmSupportReasoning = !!selectedModel?.reasoning; const tokenLimit = useMemo(() => { return selectedModel?.maxResponse || 4096; @@ -244,7 +249,7 @@ const AIChatSettingsModal = ({ - - - - {t('app:temperature')} - - - { - setValue('temperature', e.target.checked ? 0 : undefined); - }} - /> - - - - { - setValue(NodeInputKeyEnum.aiChatTemperature, e); - setRefresh(!refresh); - }} - /> - - - + {llmSupportTemperature && ( + + + + {t('app:temperature')} + + + { + setValue('temperature', e.target.checked ? 0 : undefined); + }} + /> + + + { + setValue(NodeInputKeyEnum.aiChatTemperature, e); + setRefresh(!refresh); + }} + /> + + + )} + {llmSupportReasoning && ( + + + {t('app:reasoning_response')} + { + const value = e.target.checked; + setValue(NodeInputKeyEnum.aiChatReasoning, value); + }} + /> + + + )} {showResponseAnswerText && ( @@ -307,12 +327,11 @@ const AIChatSettingsModal = ({ )} {showVisionSwitch && ( - + {t('app:llm_use_vision')} - {llmSupportVision ? ( ) : ( - + {t('app:llm_not_support_vision')} )} diff --git a/projects/app/src/components/core/ai/ModelTable/index.tsx b/projects/app/src/components/core/ai/ModelTable/index.tsx index 0846b2cd3d2d..682e8aaf0340 100644 --- a/projects/app/src/components/core/ai/ModelTable/index.tsx +++ b/projects/app/src/components/core/ai/ModelTable/index.tsx @@ -26,6 +26,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyTag from '@fastgpt/web/components/common/Tag/index'; import dynamic from 'next/dynamic'; +import CopyBox from '@fastgpt/web/components/common/String/CopyBox'; const MyModal = dynamic(() => import('@fastgpt/web/components/common/MyModal')); @@ -53,7 +54,8 @@ const ModelTable = () => { const [search, setSearch] = useState(''); - const { llmModelList, audioSpeechModelList, vectorModelList, whisperModel } = useSystemStore(); + const { llmModelList, ttsModelList, embeddingModelList, sttModelList, reRankModelList } = + useSystemStore(); const modelList = useMemo(() => { const formatLLMModelList = llmModelList.map((item) => ({ @@ -80,64 +82,72 @@ const ModelTable = () => { ) : ( - {item.charsPointsPrice} + {item.charsPointsPrice || 0} {`${t('common:support.wallet.subscription.point')} / 1K Tokens`} ), tagColor: 'blue' })); - const formatVectorModelList = vectorModelList.map((item) => ({ + const formatVectorModelList = embeddingModelList.map((item) => ({ ...item, typeLabel: t('common:model.type.embedding'), priceLabel: ( - {item.charsPointsPrice} + {item.charsPointsPrice || 0} {` ${t('common:support.wallet.subscription.point')} / 1K Tokens`} ), tagColor: 'yellow' })); - const formatAudioSpeechModelList = audioSpeechModelList.map((item) => ({ + const formatAudioSpeechModelList = ttsModelList.map((item) => ({ ...item, typeLabel: t('common:model.type.tts'), priceLabel: ( - {item.charsPointsPrice} + {item.charsPointsPrice || 0} {` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`} ), tagColor: 'green' })); - const formatWhisperModel = { - ...whisperModel, + const formatWhisperModelList = sttModelList.map((item) => ({ + ...item, typeLabel: t('common:model.type.stt'), priceLabel: ( - {whisperModel.charsPointsPrice} + {item.charsPointsPrice} {` ${t('common:support.wallet.subscription.point')} / 60${t('common:unit.seconds')}`} ), tagColor: 'purple' - }; + })); + const formatRerankModelList = reRankModelList.map((item) => ({ + ...item, + typeLabel: t('common:model.type.reRank'), + priceLabel: - , + tagColor: 'red' + })); const list = (() => { - if (modelType === ModelTypeEnum.chat) return formatLLMModelList; + if (modelType === ModelTypeEnum.llm) return formatLLMModelList; if (modelType === ModelTypeEnum.embedding) return formatVectorModelList; if (modelType === ModelTypeEnum.tts) return formatAudioSpeechModelList; - if (modelType === ModelTypeEnum.stt) return [formatWhisperModel]; + if (modelType === ModelTypeEnum.stt) return formatWhisperModelList; + if (modelType === ModelTypeEnum.rerank) return formatRerankModelList; return [ ...formatLLMModelList, ...formatVectorModelList, ...formatAudioSpeechModelList, - formatWhisperModel + ...formatWhisperModelList, + ...formatRerankModelList ]; })(); const formatList = list.map((item) => { @@ -167,9 +177,10 @@ const ModelTable = () => { return filterList; }, [ llmModelList, - vectorModelList, - audioSpeechModelList, - whisperModel, + embeddingModelList, + ttsModelList, + sttModelList, + reRankModelList, t, modelType, provider, @@ -179,15 +190,16 @@ const ModelTable = () => { const filterProviderList = useMemo(() => { const allProviderIds: string[] = [ ...llmModelList, - ...vectorModelList, - ...audioSpeechModelList, - whisperModel + ...embeddingModelList, + ...ttsModelList, + ...sttModelList, + ...reRankModelList ].map((model) => model.provider); return providerList.current.filter( (item) => allProviderIds.includes(item.value) || item.value === '' ); - }, [audioSpeechModelList, llmModelList, vectorModelList, whisperModel]); + }, [ttsModelList, llmModelList, embeddingModelList, sttModelList, reRankModelList]); return ( @@ -241,7 +253,9 @@ const ModelTable = () => { - {item.name} + + {item.name} + diff --git a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx index 234828d0afd5..b5e190cc5a27 100644 --- a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx +++ b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { LLMModelTypeEnum, llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants'; import { Box, css, HStack, IconButton, useDisclosure } from '@chakra-ui/react'; @@ -7,8 +7,8 @@ import AISettingModal, { AIChatSettingsModalProps } from '@/components/core/ai/A import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import { useMount } from 'ahooks'; import AIModelSelector from '@/components/Select/AIModelSelector'; +import { getWebDefaultModel } from '@/web/common/system/utils'; type Props = { llmModelType?: `${LLMModelTypeEnum}`; @@ -39,15 +39,19 @@ const SettingLLMModel = ({ }), [llmModelList, llmModelType] ); + const defaultModel = useMemo(() => { + return getWebDefaultModel(modelList).model; + }, [modelList]); + // Set default model - useMount(() => { - if (!model && modelList.length > 0) { + useEffect(() => { + if (!modelList.find((item) => item.model === model) && !!defaultModel) { onChange({ ...defaultData, - model: modelList[0].model + model: defaultModel }); } - }); + }, [modelList, model, defaultModel, onChange]); const { isOpen: isOpenAIChatSetting, diff --git a/projects/app/src/components/core/app/DatasetParamsModal.tsx b/projects/app/src/components/core/app/DatasetParamsModal.tsx index b995633083c1..6bb846044225 100644 --- a/projects/app/src/components/core/app/DatasetParamsModal.tsx +++ b/projects/app/src/components/core/app/DatasetParamsModal.tsx @@ -65,17 +65,15 @@ const DatasetParamsModal = ({ const theme = useTheme(); const { toast } = useToast(); const { teamPlanStatus } = useUserStore(); - const { reRankModelList, llmModelList } = useSystemStore(); + const { reRankModelList, llmModelList, defaultModels } = useSystemStore(); const [refresh, setRefresh] = useState(false); const [currentTabType, setCurrentTabType] = useState(SearchSettingTabEnum.searchMode); const chatModelSelectList = (() => - llmModelList - .filter((model) => model.usedInQueryExtension) - .map((item) => ({ - value: item.model, - label: item.name - })))(); + llmModelList.map((item) => ({ + value: item.model, + label: item.name + })))(); const { register, setValue, getValues, handleSubmit, watch } = useForm({ defaultValues: { @@ -84,7 +82,7 @@ const DatasetParamsModal = ({ searchMode, usingReRank: !!usingReRank && teamPlanStatus?.standardConstants?.permissionReRank !== false, datasetSearchUsingExtensionQuery, - datasetSearchExtensionModel: datasetSearchExtensionModel || chatModelSelectList[0]?.value, + datasetSearchExtensionModel: datasetSearchExtensionModel || defaultModels.llm?.model, datasetSearchExtensionBg } }); diff --git a/projects/app/src/components/core/app/TTSSelect.tsx b/projects/app/src/components/core/app/TTSSelect.tsx index e605b2ef9c38..aaedceb25505 100644 --- a/projects/app/src/components/core/app/TTSSelect.tsx +++ b/projects/app/src/components/core/app/TTSSelect.tsx @@ -1,6 +1,6 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; -import { Box, Button, Flex, ModalBody, useDisclosure, Image } from '@chakra-ui/react'; +import { Box, Button, Flex, ModalBody, useDisclosure, Image, HStack } from '@chakra-ui/react'; import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'next-i18next'; import { TTSTypeEnum } from '@/web/core/app/constants'; @@ -9,13 +9,15 @@ import { useAudioPlay } from '@/web/common/utils/voice'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import MyModal from '@fastgpt/web/components/common/MyModal'; import MySlider from '@/components/Slider'; -import MySelect from '@fastgpt/web/components/common/MySelect'; import { defaultTTSConfig } from '@fastgpt/global/core/app/constants'; import ChatFunctionTip from './Tip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import MyImage from '@fastgpt/web/components/common/Image/MyImage'; import { useContextSelector } from 'use-context-selector'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; +import Avatar from '@fastgpt/web/components/common/Avatar'; +import { getModelProvider } from '@fastgpt/global/core/ai/provider'; +import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect'; const TTSSelect = ({ value = defaultTTSConfig, @@ -25,33 +27,62 @@ const TTSSelect = ({ onChange: (e: AppTTSConfigType) => void; }) => { const { t } = useTranslation(); - const { audioSpeechModelList } = useSystemStore(); + const { ttsModelList } = useSystemStore(); const { isOpen, onOpen, onClose } = useDisclosure(); const appId = useContextSelector(AppContext, (v) => v.appId); - const list = useMemo( + const selectorList = useMemo( () => [ - { label: t('common:core.app.tts.Close'), value: TTSTypeEnum.none }, - { label: t('common:core.app.tts.Web'), value: TTSTypeEnum.web }, - ...audioSpeechModelList.map((item) => item?.voices || []).flat() + { label: t('app:tts_close'), value: TTSTypeEnum.none, children: [] }, + { label: t('app:tts_browser'), value: TTSTypeEnum.web, children: [] }, + ...ttsModelList.map((model) => { + const providerData = getModelProvider(model.provider); + return { + label: ( + + + {t(providerData.name)} + + ), + value: model.model, + children: model.voices.map((voice) => ({ + label: voice.label, + value: voice.value + })) + }; + }) ], - [audioSpeechModelList, t] + [ttsModelList, t] ); const formatValue = useMemo(() => { if (!value || !value.type) { - return TTSTypeEnum.none; + return [TTSTypeEnum.none, undefined]; } if (value.type === TTSTypeEnum.none || value.type === TTSTypeEnum.web) { - return value.type; + return [value.type, undefined]; } - return value.voice; + + return [value.model, value.voice]; }, [value]); - const formLabel = useMemo( - () => list.find((item) => item.value === formatValue)?.label || t('common:common.UnKnow'), - [formatValue, list, t] - ); + const formLabel = useMemo(() => { + const provider = selectorList.find((item) => item.value === formatValue[0]) || selectorList[0]; + const voice = provider.children.find((item) => item.value === formatValue[1]); + return ( + + {voice ? ( + + {provider.label} + - + {voice.label} + + ) : ( + provider.label + )} + + ); + }, [formatValue, selectorList, t]); const { playAudioByText, cancelAudio, audioLoading, audioPlaying } = useAudioPlay({ appId, @@ -59,25 +90,20 @@ const TTSSelect = ({ }); const onclickChange = useCallback( - (e: string) => { - if (e === TTSTypeEnum.none || e === TTSTypeEnum.web) { - onChange({ type: e as `${TTSTypeEnum}` }); + (e: string[]) => { + console.log(e, '-='); + if (e[0] === TTSTypeEnum.none || e[0] === TTSTypeEnum.web) { + onChange({ type: e[0] }); } else { - const audioModel = audioSpeechModelList.find((item) => - item.voices?.find((voice) => voice.value === e) - ); - if (!audioModel) { - return; - } onChange({ ...value, type: TTSTypeEnum.model, - model: audioModel.model, - voice: e + model: e[0], + voice: e[1] }); } }, - [audioSpeechModelList, onChange, value] + [ttsModelList, onChange, value] ); const onCloseTTSModal = useCallback(() => { @@ -113,7 +139,13 @@ const TTSSelect = ({ {t('common:core.app.tts.Speech model')} - + {formLabel}} + value={formatValue} + list={selectorList} + onSelect={onclickChange} + /> {t('common:core.app.tts.Speech speed')} @@ -135,7 +167,7 @@ const TTSSelect = ({ }} /> - {formatValue !== TTSTypeEnum.none && ( + {formatValue[0] !== TTSTypeEnum.none && ( {audioPlaying ? ( diff --git a/projects/app/src/components/core/app/VariableEdit.tsx b/projects/app/src/components/core/app/VariableEdit.tsx index bc4b873f4c7b..30ae8d83b182 100644 --- a/projects/app/src/components/core/app/VariableEdit.tsx +++ b/projects/app/src/components/core/app/VariableEdit.tsx @@ -30,7 +30,7 @@ import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/workflow/ut import ChatFunctionTip from './Tip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; -import InputTypeConfig from '@/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig'; +import InputTypeConfig from '@/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig'; import MyIconButton from '@fastgpt/web/components/common/Icon/button'; export const defaultVariable: VariableItemType = { diff --git a/projects/app/src/components/core/app/WelcomeTextConfig.tsx b/projects/app/src/components/core/app/WelcomeTextConfig.tsx index 67a3139fff54..b1dfc4f47b77 100644 --- a/projects/app/src/components/core/app/WelcomeTextConfig.tsx +++ b/projects/app/src/components/core/app/WelcomeTextConfig.tsx @@ -25,7 +25,7 @@ const WelcomeTextConfig = (props: TextareaProps) => { mt={1.5} rows={6} fontSize={'sm'} - bg={'white'} + bg={'myGray.50'} minW={'384px'} placeholder={t('common:core.app.tip.welcomeTextTip')} autoHeight diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx index 48a53780797d..715a3c22b350 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx @@ -107,7 +107,7 @@ const ChatInput = ({ ); /* whisper init */ - const { whisperModel } = useSystemStore(); + const { sttModelList } = useSystemStore(); const canvasRef = useRef(null); const { isSpeaking, @@ -293,7 +293,7 @@ const ChatInput = ({ /> {/* voice-input */} - {whisperConfig.open && !inputValue && !isChatting && !!whisperModel && ( + {whisperConfig.open && !inputValue && !isChatting && sttModelList.length > 0 && ( <> import('@/pages/dataset/detail/components/InputDataModal')); +const InputDataModal = dynamic(() => import('@/pageComponents/dataset/detail/InputDataModal')); export type AdminMarkType = { feedbackDataId?: string; diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx index 54534b622e73..d86e706b69e8 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx @@ -201,6 +201,7 @@ const ChatBox = ({ ({ event, text = '', + reasoningText, status, name, tool, @@ -225,6 +226,25 @@ const ChatBox = ({ status, moduleName: name }; + } else if (event === SseResponseEventEnum.answer && reasoningText) { + if (lastValue.type === ChatItemValueTypeEnum.reasoning && lastValue.reasoning) { + lastValue.reasoning.content += reasoningText; + return { + ...item, + value: item.value.slice(0, -1).concat(lastValue) + }; + } else { + const val: AIChatItemValueItemType = { + type: ChatItemValueTypeEnum.reasoning, + reasoning: { + content: reasoningText + } + }; + return { + ...item, + value: item.value.concat(val) + }; + } } else if ( (event === SseResponseEventEnum.answer || event === SseResponseEventEnum.fastAnswer) && text diff --git a/projects/app/src/components/core/chat/ChatContainer/type.d.ts b/projects/app/src/components/core/chat/ChatContainer/type.d.ts index 74774e227a30..a8b8494a7e54 100644 --- a/projects/app/src/components/core/chat/ChatContainer/type.d.ts +++ b/projects/app/src/components/core/chat/ChatContainer/type.d.ts @@ -6,6 +6,7 @@ import { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/t export type generatingMessageProps = { event: SseResponseEventEnum; text?: string; + reasoningText?: string; name?: string; status?: 'running' | 'finish'; tool?: ToolModuleResponseItemType; diff --git a/projects/app/src/components/core/chat/components/AIResponseBox.tsx b/projects/app/src/components/core/chat/components/AIResponseBox.tsx index 2f14b6f8cbf8..c91623a63ae0 100644 --- a/projects/app/src/components/core/chat/components/AIResponseBox.tsx +++ b/projects/app/src/components/core/chat/components/AIResponseBox.tsx @@ -8,6 +8,7 @@ import { Box, Button, Flex, + HStack, Textarea } from '@chakra-ui/react'; import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; @@ -139,6 +140,58 @@ ${toolResponse}`} }, (prevProps, nextProps) => isEqual(prevProps, nextProps) ); +const RenderResoningContent = React.memo(function RenderResoningContent({ + content, + isChatting, + isLastResponseValue +}: { + content: string; + isChatting: boolean; + isLastResponseValue: boolean; +}) { + const { t } = useTranslation(); + const showAnimation = isChatting && isLastResponseValue; + + return ( + + + + + + {t('chat:ai_reasoning')} + + + {showAnimation && } + + + + + + + + ); +}); const RenderUserSelectInteractive = React.memo(function RenderInteractive({ interactive }: { @@ -290,6 +343,14 @@ const AIResponseBox = ({ value, isLastResponseValue, isChatting }: props) => { return ( ); + if (value.type === ChatItemValueTypeEnum.reasoning && value.reasoning) + return ( + + ); if (value.type === ChatItemValueTypeEnum.tool && value.tools) return ; if (value.type === ChatItemValueTypeEnum.interactive && value.interactive) { diff --git a/projects/app/src/components/core/dataset/QuoteItem.tsx b/projects/app/src/components/core/dataset/QuoteItem.tsx index b9ad40ce2204..a897138b5633 100644 --- a/projects/app/src/components/core/dataset/QuoteItem.tsx +++ b/projects/app/src/components/core/dataset/QuoteItem.tsx @@ -12,7 +12,7 @@ import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/da import type { readCollectionSourceBody } from '@/pages/api/core/dataset/collection/read'; import Markdown from '@/components/Markdown'; -const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal')); +const InputDataModal = dynamic(() => import('@/pageComponents/dataset/detail/InputDataModal')); type ScoreItemType = SearchDataResponseItemType['score'][0]; const scoreTheme: Record< diff --git a/projects/app/src/components/support/apikey/Table.tsx b/projects/app/src/components/support/apikey/Table.tsx index 38e606375812..30574b55b6a9 100644 --- a/projects/app/src/components/support/apikey/Table.tsx +++ b/projects/app/src/components/support/apikey/Table.tsx @@ -26,7 +26,7 @@ import { import type { EditApiKeyProps } from '@/global/support/openapi/api.d'; import dayjs from 'dayjs'; import { AddIcon } from '@chakra-ui/icons'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; diff --git a/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx b/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx index 4d77f9ef8a48..d1eeaf408223 100644 --- a/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx +++ b/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx @@ -353,8 +353,9 @@ function MemberModal({ _hover={{ bgColor: 'myGray.200' }} - onClick={() => { + onClick={(e) => { setParentPath(getOrgChildrenPath(org)); + e.stopPropagation(); }} /> )} diff --git a/projects/app/src/components/support/user/team/TeamTagModal/index.tsx b/projects/app/src/components/support/user/team/TeamTagModal/index.tsx index 3d2396fe6492..aa4590ed9360 100644 --- a/projects/app/src/components/support/user/team/TeamTagModal/index.tsx +++ b/projects/app/src/components/support/user/team/TeamTagModal/index.tsx @@ -18,7 +18,7 @@ import type { TeamTagItemType } from '@fastgpt/global/support/user/team/type'; import { useRequest } from '@fastgpt/web/hooks/useRequest'; import { RepeatIcon } from '@chakra-ui/icons'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useUserStore } from '@/web/support/user/useUserStore'; import { useQuery } from '@tanstack/react-query'; import { getTeamsTags, loadTeamTagsByDomain } from '@/web/support/user/team/api'; diff --git a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx index fa4590428c93..9b82c0a45241 100644 --- a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx +++ b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx @@ -3,8 +3,8 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import { useTranslation } from 'next-i18next'; import { Box, Button, Flex, ModalBody, ModalFooter, useDisclosure } from '@chakra-ui/react'; import { NotSufficientModalType, useSystemStore } from '@/web/common/system/useSystemStore'; -import ExtraPlan from '@/pages/price/components/ExtraPlan'; -import StandardPlan from '@/pages/price/components/Standard'; +import ExtraPlan from '@/pageComponents/price/ExtraPlan'; +import StandardPlan from '@/pageComponents/price/Standard'; import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import { useUserStore } from '@/web/support/user/useUserStore'; @@ -29,7 +29,10 @@ const NotSufficientModal = ({ type }: { type: NotSufficientModalType }) => { [TeamErrEnum.datasetSizeNotEnough]: t('common:support.wallet.Dataset_not_sufficient'), [TeamErrEnum.datasetAmountNotEnough]: t('common:support.wallet.Dataset_amount_not_sufficient'), [TeamErrEnum.teamMemberOverSize]: t('common:support.wallet.Team_member_over_size'), - [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient') + [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), + [TeamErrEnum.pluginAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), + [TeamErrEnum.websiteSyncNotEnough]: t('common:code_error.team_error.website_sync_not_enough'), + [TeamErrEnum.reRankNotEnough]: t('common:code_error.team_error.re_rank_not_enough') }; return ( diff --git a/projects/app/src/components/support/wallet/QRCodePayModal.tsx b/projects/app/src/components/support/wallet/QRCodePayModal.tsx index 6b3fe5bd5ad7..306ab1a3481b 100644 --- a/projects/app/src/components/support/wallet/QRCodePayModal.tsx +++ b/projects/app/src/components/support/wallet/QRCodePayModal.tsx @@ -1,14 +1,12 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; -import React, { useCallback, useEffect, useRef } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'next-i18next'; import { Box, ModalBody } from '@chakra-ui/react'; import { checkBalancePayResult } from '@/web/support/wallet/bill/api'; import { useToast } from '@fastgpt/web/hooks/useToast'; -import { useRouter } from 'next/router'; -import { getErrText } from '@fastgpt/global/common/error/utils'; import LightTip from '@fastgpt/web/components/common/LightTip'; -import Script from 'next/script'; -import { getWebReqUrl } from '@fastgpt/web/common/system/utils'; +import QRCode from 'qrcode'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; export type QRPayProps = { readPrice: number; @@ -27,71 +25,56 @@ const QRCodePayModal = ({ }: QRPayProps & { tip?: string; onSuccess?: () => any }) => { const { t } = useTranslation(); const { toast } = useToast(); - const dom = useRef(null); + const canvasRef = useRef(null); const drawCode = useCallback(() => { - if (dom.current && window.QRCode && !dom.current.innerHTML) { - new window.QRCode(dom.current, { - text: codeUrl, - width: qrCodeSize, - height: qrCodeSize, - colorDark: '#000000', - colorLight: '#ffffff', - correctLevel: window.QRCode.CorrectLevel.H + const canvas = document.createElement('canvas'); + QRCode.toCanvas(canvas, codeUrl, { + width: qrCodeSize, + margin: 0, + color: { + dark: '#000000', + light: '#ffffff' + } + }) + .then(() => { + if (canvasRef.current) { + canvasRef.current.innerHTML = ''; + canvasRef.current.appendChild(canvas); + } else { + drawCode(); + } + }) + .catch((err) => { + console.error('QRCode generation error:', err); }); - } }, [codeUrl]); useEffect(() => { - let timer: NodeJS.Timeout; - const check = async () => { - try { - const res = await checkBalancePayResult(billId); - if (res) { - try { - await onSuccess?.(); - toast({ - title: res, - status: 'success' - }); - return; - } catch (error) { - toast({ - title: getErrText(error), - status: 'error' - }); - } - } - } catch (error) {} - - drawCode(); + drawCode(); + }, [drawCode]); - timer = setTimeout(check, 2000); - }; - - check(); - - return () => clearTimeout(timer); - }, [billId, drawCode, onSuccess, toast]); + useRequest2(() => checkBalancePayResult(billId), { + manual: false, + pollingInterval: 2000, + onSuccess: (res) => { + if (res) { + onSuccess?.(); + } + }, + errorToast: '' + }); return ( - <> - - - - - {tip && } - - - {t('common:pay.wechat', { price: readPrice })} - - - - + + + {tip && } + + + {t('common:pay.wechat', { price: readPrice })} + + + ); }; diff --git a/projects/app/src/global/common/api/systemRes.d.ts b/projects/app/src/global/common/api/systemRes.d.ts index f10c14d91301..e2c4831dd62c 100644 --- a/projects/app/src/global/common/api/systemRes.d.ts +++ b/projects/app/src/global/common/api/systemRes.d.ts @@ -1,6 +1,6 @@ import type { LLMModelItemType, - VectorModelItemType, + EmbeddingModelItemType, AudioSpeechModels, STTModelType, ReRankModelItemType @@ -8,15 +8,15 @@ import type { import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d'; import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; +import { SystemDefaultModelType, SystemModelItemType } from '@fastgpt/service/core/ai/type'; export type InitDateResponse = { bufferId?: string; - llmModels: LLMModelItemType[]; - vectorModels: VectorModelItemType[]; - audioSpeechModels: AudioSpeechModels[]; - reRankModels: ReRankModelItemType[]; - whisperModel: STTModelType; - feConfigs: FastGPTFeConfigsType; + + feConfigs?: FastGPTFeConfigsType; subPlans?: SubPlanType; systemVersion: string; + + activeModelList?: SystemModelItemType[]; + defaultModels?: SystemDefaultModelType; }; diff --git a/projects/app/src/pages/account/components/AccountContainer.tsx b/projects/app/src/pageComponents/account/AccountContainer.tsx similarity index 100% rename from projects/app/src/pages/account/components/AccountContainer.tsx rename to projects/app/src/pageComponents/account/AccountContainer.tsx diff --git a/projects/app/src/pages/account/components/TeamSelector.tsx b/projects/app/src/pageComponents/account/TeamSelector.tsx similarity index 100% rename from projects/app/src/pages/account/components/TeamSelector.tsx rename to projects/app/src/pageComponents/account/TeamSelector.tsx diff --git a/projects/app/src/pages/account/bill/components/ApplyInvoiceModal.tsx b/projects/app/src/pageComponents/account/bill/ApplyInvoiceModal.tsx similarity index 98% rename from projects/app/src/pages/account/bill/components/ApplyInvoiceModal.tsx rename to projects/app/src/pageComponents/account/bill/ApplyInvoiceModal.tsx index 557dd227ace9..ce8aad28c0b7 100644 --- a/projects/app/src/pages/account/bill/components/ApplyInvoiceModal.tsx +++ b/projects/app/src/pageComponents/account/bill/ApplyInvoiceModal.tsx @@ -27,7 +27,7 @@ import dayjs from 'dayjs'; import { useTranslation } from 'next-i18next'; import { useCallback, useState } from 'react'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import Divider from '@/pages/app/detail/components/WorkflowComponents/Flow/components/Divider'; +import Divider from '@/pageComponents/app/detail/WorkflowComponents/Flow/components/Divider'; import { TeamInvoiceHeaderType } from '@fastgpt/global/support/user/team/type'; import { InvoiceHeaderSingleForm } from './InvoiceHeaderForm'; import MyBox from '@fastgpt/web/components/common/MyBox'; diff --git a/projects/app/src/pages/account/bill/components/BillTable.tsx b/projects/app/src/pageComponents/account/bill/BillTable.tsx similarity index 99% rename from projects/app/src/pages/account/bill/components/BillTable.tsx rename to projects/app/src/pageComponents/account/bill/BillTable.tsx index 228de85cb68d..5e993c1a3c26 100644 --- a/projects/app/src/pages/account/bill/components/BillTable.tsx +++ b/projects/app/src/pageComponents/account/bill/BillTable.tsx @@ -32,6 +32,7 @@ import MySelect from '@fastgpt/web/components/common/MySelect'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { usePagination } from '@fastgpt/web/hooks/usePagination'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; + const BillTable = () => { const { t } = useTranslation(); const { toast } = useToast(); @@ -177,6 +178,7 @@ export default BillTable; function BillDetailModal({ bill, onClose }: { bill: BillSchemaType; onClose: () => void }) { const { t } = useTranslation(); + return ( import('@fastgpt/web/components/common/MyModal')); + +const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => { + const { t } = useTranslation(); + const { userInfo } = useUserStore(); + const { defaultModels, feConfigs } = useSystemStore(); + + const isRoot = userInfo?.username === 'root'; + + const [provider, setProvider] = useState(''); + const providerList = useRef<{ label: any; value: ModelProviderIdType | '' }[]>([ + { label: t('common:common.All'), value: '' }, + ...ModelProviderList.map((item) => ({ + label: ( + + + {t(item.name as any)} + + ), + value: item.id + })) + ]); + + const [modelType, setModelType] = useState(''); + const selectModelTypeList = useRef<{ label: string; value: ModelTypeEnum | '' }[]>([ + { label: t('common:common.All'), value: '' }, + ...modelTypeList.map((item) => ({ label: t(item.label), value: item.value })) + ]); + + const [search, setSearch] = useState(''); + const [showActive, setShowActive] = useState(false); + + const { + data: systemModelList = [], + runAsync: refreshSystemModelList, + loading: loadingModels + } = useRequest2(getSystemModelList, { + manual: false + }); + const refreshModels = useCallback(async () => { + clientInitData(); + refreshSystemModelList(); + }, [refreshSystemModelList]); + + const modelList = useMemo(() => { + const formatLLMModelList = systemModelList + .filter((item) => item.type === ModelTypeEnum.llm) + .map((item) => ({ + ...item, + typeLabel: t('common:model.type.chat'), + priceLabel: + typeof item.inputPrice === 'number' ? ( + + + {`${t('common:common.Input')}:`} + + {item.inputPrice || 0} + + {`${t('common:support.wallet.subscription.point')} / 1K Tokens`} + + + {`${t('common:common.Output')}:`} + + {item.outputPrice || 0} + + {`${t('common:support.wallet.subscription.point')} / 1K Tokens`} + + + ) : ( + + + {item.charsPointsPrice || 0} + + {`${t('common:support.wallet.subscription.point')} / 1K Tokens`} + + ), + tagColor: 'blue' + })); + const formatVectorModelList = systemModelList + .filter((item) => item.type === ModelTypeEnum.embedding) + .map((item) => ({ + ...item, + typeLabel: t('common:model.type.embedding'), + priceLabel: ( + + + {item.charsPointsPrice || 0} + + {` ${t('common:support.wallet.subscription.point')} / 1K Tokens`} + + ), + tagColor: 'yellow' + })); + const formatAudioSpeechModelList = systemModelList + .filter((item) => item.type === ModelTypeEnum.tts) + .map((item) => ({ + ...item, + typeLabel: t('common:model.type.tts'), + priceLabel: ( + + + {item.charsPointsPrice || 0} + + {` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`} + + ), + tagColor: 'green' + })); + const formatWhisperModel = systemModelList + .filter((item) => item.type === ModelTypeEnum.stt) + .map((item) => ({ + ...item, + typeLabel: t('common:model.type.stt'), + priceLabel: ( + + + {item.charsPointsPrice || 0} + + {` ${t('common:support.wallet.subscription.point')} / 60${t('common:unit.seconds')}`} + + ), + tagColor: 'purple' + })); + const formatRerankModelList = systemModelList + .filter((item) => item.type === ModelTypeEnum.rerank) + .map((item) => ({ + ...item, + typeLabel: t('common:model.type.reRank'), + priceLabel: - , + tagColor: 'red' + })); + + const list = (() => { + if (modelType === ModelTypeEnum.llm) return formatLLMModelList; + if (modelType === ModelTypeEnum.embedding) return formatVectorModelList; + if (modelType === ModelTypeEnum.tts) return formatAudioSpeechModelList; + if (modelType === ModelTypeEnum.stt) return formatWhisperModel; + if (modelType === ModelTypeEnum.rerank) return formatRerankModelList; + + return [ + ...formatLLMModelList, + ...formatVectorModelList, + ...formatAudioSpeechModelList, + ...formatWhisperModel, + ...formatRerankModelList + ]; + })(); + + const formatList = list.map((item) => { + const provider = getModelProvider(item.provider); + return { + ...item, + avatar: provider.avatar, + providerId: provider.id, + providerName: t(provider.name as any), + order: provider.order + }; + }); + formatList.sort((a, b) => a.order - b.order); + + const filterList = formatList.filter((item) => { + const providerFilter = provider ? item.providerId === provider : true; + + const regx = new RegExp(search, 'i'); + const nameFilter = search ? regx.test(item.name) : true; + + const activeFilter = showActive ? item.isActive : true; + + return providerFilter && nameFilter && activeFilter; + }); + + return filterList; + }, [systemModelList, t, modelType, provider, search, showActive]); + const activeModelLength = useMemo(() => { + return modelList.filter((item) => item.isActive).length; + }, [modelList]); + + const filterProviderList = useMemo(() => { + const allProviderIds: string[] = systemModelList.map((model) => model.provider); + + return providerList.current.filter( + (item) => allProviderIds.includes(item.value) || item.value === '' + ); + }, [systemModelList]); + + const { runAsync: onTestModel, loading: testingModel } = useRequest2(getTestModel, { + manual: true, + successToast: t('common:common.Success') + }); + const { runAsync: updateModel, loading: updatingModel } = useRequest2(putSystemModel, { + onSuccess: refreshModels + }); + + const { ConfirmModal, openConfirm } = useConfirm({ + type: 'delete', + content: t('account:model.delete_model_confirm') + }); + const { runAsync: deleteModel } = useRequest2(deleteSystemModel, { + onSuccess: refreshModels + }); + + const [editModelData, setEditModelData] = useState(); + const { runAsync: onEditModel, loading: loadingData } = useRequest2( + (modelId: string) => getSystemModelDetail(modelId), + { + onSuccess: (data: SystemModelItemType) => { + setEditModelData(data); + } + } + ); + const onCreateModel = (type: ModelTypeEnum) => { + const defaultModel = defaultModels[type]; + + setEditModelData({ + ...defaultModel, + model: '', + name: '', + charsPointsPrice: 0, + inputPrice: undefined, + outputPrice: undefined, + + isCustom: true, + isActive: true, + // @ts-ignore + type + }); + }; + + const { + isOpen: isOpenJsonConfig, + onOpen: onOpenJsonConfig, + onClose: onCloseJsonConfig + } = useDisclosure(); + const { + onOpen: onOpenDefaultModel, + onClose: onCloseDefaultModel, + isOpen: isOpenDefaultModel + } = useDisclosure(); + + const isLoading = loadingModels || loadingData || updatingModel || testingModel; + + const [showModelId, setShowModelId] = useState(true); + + return ( + <> + {isRoot && ( + + {Tab} + + + + {t('account:create_model')}} + menuList={[ + { + children: [ + { + label: t('common:model.type.chat'), + onClick: () => onCreateModel(ModelTypeEnum.llm) + }, + { + label: t('common:model.type.embedding'), + onClick: () => onCreateModel(ModelTypeEnum.embedding) + }, + { + label: t('common:model.type.tts'), + onClick: () => onCreateModel(ModelTypeEnum.tts) + }, + { + label: t('common:model.type.stt'), + onClick: () => onCreateModel(ModelTypeEnum.stt) + }, + { + label: t('common:model.type.reRank'), + onClick: () => onCreateModel(ModelTypeEnum.rerank) + } + ] + } + ]} + /> + + )} + + + + + + {t('common:model.provider')} + + + + + + {t('common:model.model_type')} + + + + + + setSearch(e.target.value)} + placeholder={t('common:model.search_name_placeholder')} + /> + + + + + + + + + {feConfigs?.isPlus && } + + + + + + {modelList.map((item, index) => ( + + + + {feConfigs?.isPlus && } + + + + ))} + +
+ setShowModelId(!showModelId)} + > + + {showModelId ? t('account:model.model_id') : t('common:model.name')} + + + + {t('common:model.model_type')}{t('common:model.billing')} + setShowActive(!showActive)} + color={showActive ? 'primary.600' : 'myGray.600'} + > + {t('account:model.active')}({activeModelLength}) + +
+ + + + {showModelId ? item.model : item.name} + + + + {item.contextToken && ( + + {Math.floor(item.contextToken / 1000)}k + + )} + {item.vision && ( + + {t('account:model.vision_tag')} + + )} + {item.toolChoice && ( + + {t('account:model.tool_choice_tag')} + + )} + + + {item.typeLabel} + {item.priceLabel} + + updateModel({ + model: item.model, + metadata: { isActive: e.target.checked } + }) + } + colorScheme={'myBlue'} + /> + + + onTestModel(item.model)} + /> + onEditModel(item.model)} + /> + {item.isCustom && ( + openConfirm(() => deleteModel({ model: item.model }))()} + /> + )} + +
+
+
+
+ + + {!!editModelData && ( + setEditModelData(undefined)} + /> + )} + {isOpenJsonConfig && ( + + )} + {isOpenDefaultModel && ( + + )} + + ); +}; + +const InputStyles = { + maxW: '300px', + bg: 'myGray.50', + w: '100%', + rows: 3 +}; +const ModelEditModal = ({ + modelData, + onSuccess, + onClose +}: { + modelData: SystemModelItemType; + onSuccess: () => void; + onClose: () => void; +}) => { + const { t } = useTranslation(); + const { feConfigs } = useSystemStore(); + + const { register, getValues, setValue, handleSubmit, watch, reset } = + useForm({ + defaultValues: modelData + }); + + const isCustom = !!modelData.isCustom; + const isLLMModel = modelData?.type === ModelTypeEnum.llm; + const isEmbeddingModel = modelData?.type === ModelTypeEnum.embedding; + const isTTSModel = modelData?.type === ModelTypeEnum.tts; + const isSTTModel = modelData?.type === ModelTypeEnum.stt; + const isRerankModel = modelData?.type === ModelTypeEnum.rerank; + + const provider = watch('provider'); + const providerData = useMemo(() => getModelProvider(provider), [provider]); + + const providerList = useRef<{ label: any; value: ModelProviderIdType }[]>( + ModelProviderList.map((item) => ({ + label: ( + + + {t(item.name as any)} + + ), + value: item.id + })) + ); + + const priceUnit = useMemo(() => { + if (isLLMModel || isEmbeddingModel) return '/ 1k Tokens'; + if (isTTSModel) return `/ 1k ${t('common:unit.character')}`; + if (isSTTModel) return `/ 60 ${t('common:unit.seconds')}`; + return ''; + return ''; + }, [isLLMModel, isEmbeddingModel, isTTSModel, t, isSTTModel]); + + const { runAsync: updateModel, loading: updatingModel } = useRequest2( + async (data: SystemModelItemType) => { + return putSystemModel({ + model: data.model, + metadata: data + }).then(onSuccess); + }, + { + onSuccess: () => { + onClose(); + }, + successToast: t('common:common.Success') + } + ); + + const [key, setKey] = useState(0); + const { runAsync: loadDefaultConfig, loading: loadingDefaultConfig } = useRequest2( + getSystemModelDefaultConfig, + { + onSuccess(res) { + reset({ + ...getValues(), + ...res + }); + setTimeout(() => { + setKey((prev) => prev + 1); + }, 0); + } + } + ); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + {priceUnit && feConfigs?.isPlus && ( + <> + + + + + {isLLMModel && ( + <> + + + + + + + + + + )} + + )} + {isLLMModel && ( + <> + + + + + + + + + + + + + + + + + + )} + {isEmbeddingModel && ( + <> + + + + + + + + + + + + + + )} + {isTTSModel && ( + <> + + + + + + )} + + + + + + + + + +
{t('account:model.param_name')}
+ + {t('account:model.model_id')} + + + + {isCustom ? ( + + ) : ( + modelData?.model + )} +
{t('common:model.provider')} + setValue('provider', value)} + list={providerList.current} + {...InputStyles} + /> +
+ + {t('account:model.alias')} + + + + +
+ + {t('account:model.charsPointsPrice')} + + + + + + + {priceUnit} + + +
+ + {t('account:model.input_price')} + + + + + + + {priceUnit} + + +
+ + {t('account:model.output_price')} + + + + + + + {priceUnit} + + +
{t('common:core.ai.Max context')} + + + +
{t('account:model.max_quote')} + + + +
{t('common:core.chat.response.module maxToken')} + + + +
{t('account:model.max_temperature')} + + + +
+ + {t('account:model.default_token')} + + + + + + +
{t('common:core.ai.Max context')} + + + +
+ + {t('account:model.defaultConfig')} + + + + + { + if (!e) { + setValue('defaultConfig', {}); + return; + } + try { + setValue('defaultConfig', JSON.parse(e)); + } catch (error) { + console.error(error); + } + }} + {...InputStyles} + /> + +
+ + {t('account:model.voices')} + + + + + { + try { + setValue('voices', JSON.parse(e)); + } catch (error) { + console.error(error); + } + }} + {...InputStyles} + /> + +
+ + {t('account:model.request_url')} + + + + +
+ + {t('account:model.request_auth')} + + + + +
+
+ {isLLMModel && ( + + + + + + + + + + + + + + + + + + + + + + {feConfigs?.isPlus && ( + + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t('account:model.param_name')}
+ + {t('account:model.tool_choice')} + + + + + + +
+ + {t('account:model.function_call')} + + + + + + +
+ + {t('account:model.vision')} + + + + + + +
+ + {t('account:model.censor')} + + + + + + +
{t('account:model.dataset_process')} + + + +
{t('account:model.used_in_classify')} + + + +
{t('account:model.used_in_extract_fields')} + + + +
{t('account:model.used_in_tool_call')} + + + +
+ + {t('account:model.default_system_chat_prompt')} + + + + +
+ + {t('account:model.custom_cq_prompt')} + + + + +
+ + {t('account:model.custom_extract_prompt')} + + + + +
+ + {t('account:model.default_config')} + + + + { + if (!e) { + setValue('defaultConfig', {}); + return; + } + try { + setValue('defaultConfig', JSON.parse(e)); + } catch (error) { + console.error(error); + } + }} + {...InputStyles} + /> +
+
+ )} +
+
+ + {!modelData.isCustom && ( + + )} + + + +
+ ); +}; + +const JsonConfigModal = ({ + onClose, + onSuccess +}: { + onClose: () => void; + onSuccess: () => void; +}) => { + const { t } = useTranslation(); + + const [data, setData] = useState(''); + const { loading } = useRequest2(getModelConfigJson, { + manual: false, + onSuccess(res) { + setData(res); + } + }); + + const { openConfirm, ConfirmModal } = useConfirm({ + content: t('account:model.json_config_confirm') + }); + const { runAsync } = useRequest2(putUpdateWithJson, { + onSuccess: () => { + onSuccess(); + onClose(); + } + }); + + return ( + + + + {t('account:model.json_config_tip')} + + + + + + + + + + + + + ); +}; + +const labelStyles = { + fontSize: 'sm', + color: 'myGray.900', + mb: 0.5 +}; +const DefaultModelModal = ({ + onSuccess, + onClose +}: { + onSuccess: () => void; + onClose: () => void; +}) => { + const { t } = useTranslation(); + const { + defaultModels, + llmModelList, + embeddingModelList, + ttsModelList, + sttModelList, + reRankModelList + } = useSystemStore(); + + // Create a copy of defaultModels for local state management + const [defaultData, setDefaultData] = useState(defaultModels); + + const { runAsync, loading } = useRequest2(putUpdateDefaultModels, { + onSuccess: () => { + onSuccess(); + onClose(); + }, + successToast: t('common:common.Update Success') + }); + + return ( + + + + {t('common:model.type.chat')} + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + llm: llmModelList.find((item) => item.model === e) + })); + }} + /> + + + + {t('common:model.type.embedding')} + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + embedding: embeddingModelList.find((item) => item.model === e) + })); + }} + /> + + + + {t('common:model.type.tts')} + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + tts: ttsModelList.find((item) => item.model === e) + })); + }} + /> + + + + {t('common:model.type.stt')} + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + stt: sttModelList.find((item) => item.model === e) + })); + }} + /> + + + + {t('common:model.type.reRank')} + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + rerank: reRankModelList.find((item) => item.model === e) + })); + }} + /> + + + + + + + + + ); +}; + +export default ModelTable; diff --git a/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx b/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx index 95528e7ec800..847e28d5efb4 100644 --- a/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx +++ b/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx @@ -14,7 +14,7 @@ import Avatar from '@fastgpt/web/components/common/Avatar'; import Tag from '@fastgpt/web/components/common/Tag'; import { useTranslation } from 'next-i18next'; -import React, { useMemo, useState } from 'react'; +import React, { useMemo, useRef, useState } from 'react'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useContextSelector } from 'use-context-selector'; import { TeamContext } from '../context'; @@ -50,6 +50,8 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro const refetchMembers = useContextSelector(TeamContext, (v) => v.refetchMembers); const MemberScrollData = useContextSelector(TeamContext, (v) => v.MemberScrollData); const [hoveredMemberId, setHoveredMemberId] = useState(); + + const selectedMembersRef = useRef(null); const [members, setMembers] = useState(group?.members || []); const [searchKey, setSearchKey] = useState(''); @@ -155,7 +157,7 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro setSearchKey(e.target.value); }} /> - + {filtered.map((member) => { return ( void; editGro
{t('common:chosen') + ': ' + members.length} - + {members.map((member) => { return ( - - + + @@ -246,9 +246,9 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) { ))}
-
- -
+ + +
diff --git a/projects/app/src/pageComponents/account/team/OrgManage/OrgMemberManageModal.tsx b/projects/app/src/pageComponents/account/team/OrgManage/OrgMemberManageModal.tsx index fd5a990aeead..8ecd21739460 100644 --- a/projects/app/src/pageComponents/account/team/OrgManage/OrgMemberManageModal.tsx +++ b/projects/app/src/pageComponents/account/team/OrgManage/OrgMemberManageModal.tsx @@ -121,36 +121,34 @@ function OrgMemberManageModal({ setSearchKey(e.target.value); }} /> - - - {filterMembers.map((member) => { - return ( - handleToggleSelect(member.tmbId)} - > - } - pointerEvents="none" - /> - - {member.memberName} - - ); - })} - - + + {filterMembers.map((member) => { + return ( + handleToggleSelect(member.tmbId)} + > + } + pointerEvents="none" + /> + + {member.memberName} + + ); + })} +
{`${t('common:chosen')}:${selectedMembers.length}`} diff --git a/projects/app/src/pages/account/thirdParty/components/OpenAIAccountModal.tsx b/projects/app/src/pageComponents/account/thirdParty/OpenAIAccountModal.tsx similarity index 100% rename from projects/app/src/pages/account/thirdParty/components/OpenAIAccountModal.tsx rename to projects/app/src/pageComponents/account/thirdParty/OpenAIAccountModal.tsx diff --git a/projects/app/src/pages/account/thirdParty/components/WorkflowVariableModal.tsx b/projects/app/src/pageComponents/account/thirdParty/WorkflowVariableModal.tsx similarity index 96% rename from projects/app/src/pages/account/thirdParty/components/WorkflowVariableModal.tsx rename to projects/app/src/pageComponents/account/thirdParty/WorkflowVariableModal.tsx index dc9719fec310..6bd4ee383c45 100644 --- a/projects/app/src/pages/account/thirdParty/components/WorkflowVariableModal.tsx +++ b/projects/app/src/pageComponents/account/thirdParty/WorkflowVariableModal.tsx @@ -1,7 +1,7 @@ import { Box, Button, Flex, Input, ModalBody, ModalFooter } from '@chakra-ui/react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import React from 'react'; -import { ThirdPartyAccountType } from '../index'; +import { ThirdPartyAccountType } from '../../../pages/account/thirdParty/index'; import { useTranslation } from 'next-i18next'; import { useForm } from 'react-hook-form'; import { useUserStore } from '@/web/support/user/useUserStore'; diff --git a/projects/app/src/pageComponents/account/usage/Dashboard.tsx b/projects/app/src/pageComponents/account/usage/Dashboard.tsx new file mode 100644 index 000000000000..fa4a55a32bcc --- /dev/null +++ b/projects/app/src/pageComponents/account/usage/Dashboard.tsx @@ -0,0 +1,142 @@ +import { getDashboardData } from '@/web/support/wallet/usage/api'; +import { Box, Flex } from '@chakra-ui/react'; +import { formatNumber } from '@fastgpt/global/common/math/tools'; +import MyBox from '@fastgpt/web/components/common/MyBox'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; +import { addDays } from 'date-fns'; +import { useTranslation } from 'next-i18next'; +import React, { useMemo } from 'react'; +import { + ResponsiveContainer, + LineChart, + Line, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + TooltipProps +} from 'recharts'; +import { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent'; +import { UnitType, UsageFilterParams } from './type'; +import dayjs from 'dayjs'; + +export type usageFormType = { + date: string; + totalPoints: number; +}; + +const CustomTooltip = ({ active, payload }: TooltipProps) => { + const data = payload?.[0]?.payload as usageFormType; + const { t } = useTranslation(); + if (active && data) { + return ( + + + {data.date} + + + {`${formatNumber(data.totalPoints)} ${t('account_usage:points')}`} + + + ); + } + return null; +}; + +const UsageDashboard = ({ + filterParams, + Tabs, + Selectors +}: { + filterParams: UsageFilterParams; + Tabs: React.ReactNode; + Selectors: React.ReactNode; +}) => { + const { t } = useTranslation(); + + const { dateRange, selectTmbIds, usageSources, unit, isSelectAllSource, isSelectAllTmb } = + filterParams; + + const { data: totalPoints = [], loading: totalPointsLoading } = useRequest2( + () => + getDashboardData({ + dateStart: dateRange.from + ? new Date(dateRange.from.setHours(0, 0, 0, 0)) + : new Date(new Date().setHours(0, 0, 0, 0)), + dateEnd: dateRange.to + ? new Date(addDays(dateRange.to, 1).setHours(0, 0, 0, 0)) + : new Date(addDays(new Date(), 1).setHours(0, 0, 0, 0)), + sources: isSelectAllSource ? undefined : usageSources, + teamMemberIds: isSelectAllTmb ? undefined : selectTmbIds, + unit + }).then((res) => + res.map((item) => ({ + ...item, + date: dayjs(item.date).format('YYYY-MM-DD') + })) + ), + { + manual: false, + refreshDeps: [filterParams] + } + ); + + const totalUsage = useMemo(() => { + return totalPoints.reduce((acc, curr) => acc + curr.totalPoints, 0); + }, [totalPoints]); + + return ( + <> + {Tabs} + {Selectors} + + + {`${t('account_usage:total_usage')}:`} + + {`${formatNumber(totalUsage)} ${t('account_usage:points')}`} + + + + {t('account_usage:points')} + + + + + + + } /> + + + + + + ); +}; + +export default React.memo(UsageDashboard); diff --git a/projects/app/src/pages/account/usage/UsageDetail.tsx b/projects/app/src/pageComponents/account/usage/UsageDetail.tsx similarity index 100% rename from projects/app/src/pages/account/usage/UsageDetail.tsx rename to projects/app/src/pageComponents/account/usage/UsageDetail.tsx diff --git a/projects/app/src/pageComponents/account/usage/UsageTable.tsx b/projects/app/src/pageComponents/account/usage/UsageTable.tsx new file mode 100644 index 000000000000..ccb4bf0b900a --- /dev/null +++ b/projects/app/src/pageComponents/account/usage/UsageTable.tsx @@ -0,0 +1,180 @@ +import { + Box, + Button, + Flex, + Table, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr +} from '@chakra-ui/react'; +import { formatNumber } from '@fastgpt/global/common/math/tools'; +import { UsageSourceMap } from '@fastgpt/global/support/wallet/usage/constants'; +import { UsageItemType } from '@fastgpt/global/support/wallet/usage/type'; +import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; +import MyBox from '@fastgpt/web/components/common/MyBox'; +import dayjs from 'dayjs'; +import { useTranslation } from 'next-i18next'; +import React, { useMemo, useState } from 'react'; +import Avatar from '@fastgpt/web/components/common/Avatar'; +import { usePagination } from '@fastgpt/web/hooks/usePagination'; +import { getUserUsages } from '@/web/support/wallet/usage/api'; +import { addDays } from 'date-fns'; +import dynamic from 'next/dynamic'; +import { UsageFilterParams } from './type'; +import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; +import { downloadFetch } from '@/web/common/system/utils'; + +const UsageDetail = dynamic(() => import('./UsageDetail')); + +const UsageTableList = ({ + filterParams, + Tabs, + Selectors +}: { + Tabs: React.ReactNode; + Selectors: React.ReactNode; + filterParams: UsageFilterParams; +}) => { + const { t } = useTranslation(); + + const { dateRange, selectTmbIds, isSelectAllTmb, usageSources, isSelectAllSource, projectName } = + filterParams; + const requestParams = useMemo(() => { + return { + dateStart: dateRange.from || new Date(), + dateEnd: addDays(dateRange.to || new Date(), 1), + sources: isSelectAllSource ? undefined : usageSources, + teamMemberIds: isSelectAllTmb ? undefined : selectTmbIds, + projectName + }; + }, [ + dateRange.from, + dateRange.to, + isSelectAllSource, + isSelectAllTmb, + projectName, + selectTmbIds, + usageSources + ]); + + const { + data: usages, + isLoading, + Pagination, + total + } = usePagination(getUserUsages, { + pageSize: 20, + params: requestParams, + refreshDeps: [requestParams] + }); + + const [usageDetail, setUsageDetail] = useState(); + + const { runAsync: exportUsage } = useRequest2( + async () => { + await downloadFetch({ + url: `/api/proApi/support/wallet/usage/exportUsage`, + filename: `usage.csv`, + body: { + ...requestParams, + appNameMap: { + ['core.app.Question Guide']: t('common:core.app.Question Guide'), + ['common:support.wallet.usage.Audio Speech']: t( + 'common:support.wallet.usage.Audio Speech' + ), + ['support.wallet.usage.Whisper']: t('common:support.wallet.usage.Whisper'), + ['support.wallet.moduleName.index']: t('common:support.wallet.moduleName.index'), + ['support.wallet.moduleName.qa']: t('common:support.wallet.moduleName.qa'), + ['core.dataset.training.Auto mode']: t('common:core.dataset.training.Auto mode'), + ['common:core.module.template.ai_chat']: t('common:core.module.template.ai_chat') + }, + sourcesMap: Object.fromEntries( + Object.entries(UsageSourceMap).map(([key, config]) => [ + key, + { + label: t(config.label as any) + } + ]) + ), + title: t('account_usage:export_title') + } + }); + }, + { + refreshDeps: [requestParams] + } + ); + + return ( + <> + {Tabs} + + {Selectors} + + {t('common:Export')}} + showCancel + content={t('account_usage:export_confirm_tip', { total })} + onConfirm={exportUsage} + /> + + + + + + + + + + + + + + + + {usages.map((item) => ( + + + + + + + + + ))} + +
{t('common:user.Time')}{t('account_usage:member')}{t('account_usage:user_type')}{t('account_usage:project_name')}{t('account_usage:total_points')}
{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')} + + + {item.sourceMember.name} + + {t(UsageSourceMap[item.source]?.label as any) || '-'}{t(item.appName as any) || '-'}{formatNumber(item.totalPoints) || 0} + +
+ {!isLoading && usages.length === 0 && ( + + )} +
+
+ + + + + {!!usageDetail && ( + setUsageDetail(undefined)} /> + )} + + ); +}; + +export default React.memo(UsageTableList); diff --git a/projects/app/src/pageComponents/account/usage/type.d.ts b/projects/app/src/pageComponents/account/usage/type.d.ts new file mode 100644 index 000000000000..21b3a8c0d08f --- /dev/null +++ b/projects/app/src/pageComponents/account/usage/type.d.ts @@ -0,0 +1,13 @@ +import { DateRangeType } from '@fastgpt/web/components/common/DateRangePicker'; + +export type UnitType = 'day' | 'month'; + +export type UsageFilterParams = { + dateRange: DateRangeType; + selectTmbIds: string[]; + isSelectAllTmb: boolean; + usageSources: UsageSourceEnum[]; + isSelectAllSource: boolean; + projectName: string; + unit: UnitType; +}; diff --git a/projects/app/src/pageComponents/app/detail/ExportConfigPopover.tsx b/projects/app/src/pageComponents/app/detail/ExportConfigPopover.tsx index 776b97d111d0..7e141b172a95 100644 --- a/projects/app/src/pageComponents/app/detail/ExportConfigPopover.tsx +++ b/projects/app/src/pageComponents/app/detail/ExportConfigPopover.tsx @@ -3,7 +3,7 @@ import { Box, Flex } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { filterSensitiveNodesData } from '@/web/core/workflow/utils'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import MyPopover from '@fastgpt/web/components/common/MyPopover'; import { fileDownload } from '@/web/common/file/utils'; import { AppChatConfigType, AppSimpleEditFormType } from '@fastgpt/global/core/app/type'; diff --git a/projects/app/src/pages/app/detail/components/InfoModal.tsx b/projects/app/src/pageComponents/app/detail/InfoModal.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/InfoModal.tsx rename to projects/app/src/pageComponents/app/detail/InfoModal.tsx index f82b1e931e21..3d0c1beb4a88 100644 --- a/projects/app/src/pages/app/detail/components/InfoModal.tsx +++ b/projects/app/src/pageComponents/app/detail/InfoModal.tsx @@ -1,6 +1,6 @@ import CollaboratorContextProvider from '@/components/support/permission/MemberManager/context'; import ResumeInherit from '@/components/support/permission/ResumeInheritText'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from './context'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { useI18n } from '@/web/context/I18n'; import { resumeInheritPer } from '@/web/core/app/api'; diff --git a/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx b/projects/app/src/pageComponents/app/detail/Logs/DetailLogsModal.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx rename to projects/app/src/pageComponents/app/detail/Logs/DetailLogsModal.tsx index 0098e8cec3b0..4a20b9d87270 100644 --- a/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx +++ b/projects/app/src/pageComponents/app/detail/Logs/DetailLogsModal.tsx @@ -11,7 +11,7 @@ import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs'; import { PluginRunBoxTabEnum } from '@/components/core/chat/ChatContainer/PluginRunBox/constants'; import CloseIcon from '@fastgpt/web/components/common/Icon/close'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; -import { PcHeader } from '@/pages/chat/components/ChatHeader'; +import { PcHeader } from '@/pageComponents/chat/ChatHeader'; import { GetChatTypeEnum } from '@/global/core/chat/constants'; import ChatItemContextProvider, { ChatItemContext } from '@/web/core/chat/context/chatItemContext'; import ChatRecordContextProvider, { diff --git a/projects/app/src/pages/app/detail/components/Logs/index.tsx b/projects/app/src/pageComponents/app/detail/Logs/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Logs/index.tsx rename to projects/app/src/pageComponents/app/detail/Logs/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Plugin/Header.tsx b/projects/app/src/pageComponents/app/detail/Plugin/Header.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Plugin/Header.tsx rename to projects/app/src/pageComponents/app/detail/Plugin/Header.tsx diff --git a/projects/app/src/pages/app/detail/components/Plugin/index.tsx b/projects/app/src/pageComponents/app/detail/Plugin/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Plugin/index.tsx rename to projects/app/src/pageComponents/app/detail/Plugin/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/API/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/API/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/API/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/API/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/DingTalk/DingTalkEditModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/DingTalk/DingTalkEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/DingTalk/DingTalkEditModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/DingTalk/DingTalkEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/DingTalk/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/DingTalk/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/DingTalk/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/DingTalk/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/FeiShu/FeiShuEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/FeiShu/FeiShuEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/FeiShu/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/FeiShu/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/FeiShu/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/FeiShu/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/Link/SelectUsingWayModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/Link/SelectUsingWayModal.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/Publish/Link/SelectUsingWayModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/Link/SelectUsingWayModal.tsx index 1fad9055f4d6..2844f43c8be9 100644 --- a/projects/app/src/pages/app/detail/components/Publish/Link/SelectUsingWayModal.tsx +++ b/projects/app/src/pageComponents/app/detail/Publish/Link/SelectUsingWayModal.tsx @@ -6,7 +6,7 @@ import { Box, Flex, FlexProps, Grid, ModalBody, Switch, useTheme } from '@chakra import MyRadio from '@/components/common/MyRadio'; import { useForm } from 'react-hook-form'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { fileToBase64 } from '@/web/common/file/utils'; import { useSystemStore } from '@/web/common/system/useSystemStore'; diff --git a/projects/app/src/pages/app/detail/components/Publish/Link/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/Link/index.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/Publish/Link/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/Link/index.tsx index 27cd2813552e..61f86b6b0ddb 100644 --- a/projects/app/src/pages/app/detail/components/Publish/Link/index.tsx +++ b/projects/app/src/pageComponents/app/detail/Publish/Link/index.tsx @@ -28,7 +28,7 @@ import { putShareChat } from '@/web/support/outLink/api'; import { formatTimeToChatTime } from '@fastgpt/global/common/string/time'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useForm } from 'react-hook-form'; import { defaultOutLinkForm } from '@/web/core/app/constants'; import type { OutLinkEditType, OutLinkSchema } from '@fastgpt/global/support/outLink/type.d'; @@ -233,7 +233,7 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => { onEdit={() => { toast({ status: 'success', - title: t('common:common.Update Successful') + title: t('common:common.Update Success') }); refetchShareChatList(); setEditLinkData(undefined); diff --git a/projects/app/src/pages/app/detail/components/Publish/OffiAccount/OffiAccountEditModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/OffiAccount/OffiAccountEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/OffiAccount/OffiAccountEditModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/OffiAccount/OffiAccountEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/OffiAccount/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/OffiAccount/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/OffiAccount/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/OffiAccount/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/Wecom/WecomEditModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/Wecom/WecomEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/Wecom/WecomEditModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/Wecom/WecomEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/Wecom/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/Wecom/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/Wecom/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/Wecom/index.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/components/BasicInfo.tsx b/projects/app/src/pageComponents/app/detail/Publish/components/BasicInfo.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/components/BasicInfo.tsx rename to projects/app/src/pageComponents/app/detail/Publish/components/BasicInfo.tsx diff --git a/projects/app/src/pages/app/detail/components/Publish/components/showShareLinkModal.tsx b/projects/app/src/pageComponents/app/detail/Publish/components/showShareLinkModal.tsx similarity index 96% rename from projects/app/src/pages/app/detail/components/Publish/components/showShareLinkModal.tsx rename to projects/app/src/pageComponents/app/detail/Publish/components/showShareLinkModal.tsx index 0b0dfbd3626a..5826cb12d8c4 100644 --- a/projects/app/src/pages/app/detail/components/Publish/components/showShareLinkModal.tsx +++ b/projects/app/src/pageComponents/app/detail/Publish/components/showShareLinkModal.tsx @@ -1,4 +1,4 @@ -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { Box, Image, Flex, ModalBody } from '@chakra-ui/react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import MyIcon from '@fastgpt/web/components/common/Icon'; diff --git a/projects/app/src/pages/app/detail/components/Publish/index.tsx b/projects/app/src/pageComponents/app/detail/Publish/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Publish/index.tsx rename to projects/app/src/pageComponents/app/detail/Publish/index.tsx diff --git a/projects/app/src/pages/app/detail/components/PublishHistoriesSlider.tsx b/projects/app/src/pageComponents/app/detail/PublishHistoriesSlider.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/PublishHistoriesSlider.tsx rename to projects/app/src/pageComponents/app/detail/PublishHistoriesSlider.tsx diff --git a/projects/app/src/pages/app/detail/components/RouteTab.tsx b/projects/app/src/pageComponents/app/detail/RouteTab.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/RouteTab.tsx rename to projects/app/src/pageComponents/app/detail/RouteTab.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/AppCard.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/AppCard.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/SimpleApp/AppCard.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/AppCard.tsx index 59c4543228b5..cef63d3dcc5e 100644 --- a/projects/app/src/pages/app/detail/components/SimpleApp/AppCard.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/AppCard.tsx @@ -16,7 +16,7 @@ import Avatar from '@fastgpt/web/components/common/Avatar'; import MyIcon from '@fastgpt/web/components/common/Icon'; import TagsEditModal from '../TagsEditModal'; import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { useContextSelector } from 'use-context-selector'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import MyModal from '@fastgpt/web/components/common/MyModal'; diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/ChatTest.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/Edit.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/Edit.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/Edit.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/Edit.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/EditForm.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/EditForm.tsx similarity index 96% rename from projects/app/src/pages/app/detail/components/SimpleApp/EditForm.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/EditForm.tsx index eb083263caa4..899e4bce147f 100644 --- a/projects/app/src/pages/app/detail/components/SimpleApp/EditForm.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/EditForm.tsx @@ -27,7 +27,7 @@ import type { SettingAIDataType } from '@fastgpt/global/core/app/type.d'; import { TTSTypeEnum } from '@/web/core/app/constants'; import { workflowSystemVariables } from '@/web/core/app/utils'; import { useContextSelector } from 'use-context-selector'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import VariableTip from '@/components/common/Textarea/MyTextarea/VariableTip'; @@ -138,9 +138,16 @@ const EditForm = ({ model: appForm.aiSettings.model, temperature: appForm.aiSettings.temperature, maxToken: appForm.aiSettings.maxToken, - maxHistories: appForm.aiSettings.maxHistories + maxHistories: appForm.aiSettings.maxHistories, + aiChatReasoning: appForm.aiSettings.aiChatReasoning ?? true }} - onChange={({ model, temperature, maxToken, maxHistories }: SettingAIDataType) => { + onChange={({ + model, + temperature, + maxToken, + maxHistories, + aiChatReasoning = false + }) => { setAppForm((state) => ({ ...state, aiSettings: { @@ -148,7 +155,8 @@ const EditForm = ({ model, temperature, maxToken, - maxHistories: maxHistories ?? 6 + maxHistories: maxHistories ?? 6, + aiChatReasoning } })); }} diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/Header.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/Header.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/components/ConfigToolModal.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/components/ConfigToolModal.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/components/ToolSelect.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelect.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/components/ToolSelect.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelect.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/components/ToolSelectModal.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/components/ToolSelectModal.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/index.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/index.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/index.tsx diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/styles.module.scss b/projects/app/src/pageComponents/app/detail/SimpleApp/styles.module.scss similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/styles.module.scss rename to projects/app/src/pageComponents/app/detail/SimpleApp/styles.module.scss diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/useSnapshots.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/useSnapshots.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/SimpleApp/useSnapshots.tsx rename to projects/app/src/pageComponents/app/detail/SimpleApp/useSnapshots.tsx diff --git a/projects/app/src/pages/app/detail/components/TagsEditModal.tsx b/projects/app/src/pageComponents/app/detail/TagsEditModal.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/TagsEditModal.tsx rename to projects/app/src/pageComponents/app/detail/TagsEditModal.tsx index 20a322864745..db33023decce 100644 --- a/projects/app/src/pages/app/detail/components/TagsEditModal.tsx +++ b/projects/app/src/pageComponents/app/detail/TagsEditModal.tsx @@ -23,7 +23,7 @@ import { useRequest } from '@fastgpt/web/hooks/useRequest'; import { getTeamsTags } from '@/web/support/user/team/api'; import { useQuery } from '@tanstack/react-query'; import { useContextSelector } from 'use-context-selector'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from './context'; const TagsEditModal = ({ onClose }: { onClose: () => void }) => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/app/detail/components/Workflow/Header.tsx b/projects/app/src/pageComponents/app/detail/Workflow/Header.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Workflow/Header.tsx rename to projects/app/src/pageComponents/app/detail/Workflow/Header.tsx diff --git a/projects/app/src/pages/app/detail/components/Workflow/components/SaveButton.tsx b/projects/app/src/pageComponents/app/detail/Workflow/components/SaveButton.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Workflow/components/SaveButton.tsx rename to projects/app/src/pageComponents/app/detail/Workflow/components/SaveButton.tsx diff --git a/projects/app/src/pages/app/detail/components/Workflow/index.tsx b/projects/app/src/pageComponents/app/detail/Workflow/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/Workflow/index.tsx rename to projects/app/src/pageComponents/app/detail/Workflow/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/AppCard.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/AppCard.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx index 4834f09706b1..94c6057a05b9 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx @@ -8,8 +8,8 @@ import { useTranslation } from 'next-i18next'; import { StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge'; import { useContextSelector } from 'use-context-selector'; -import { AppContext } from '@/pages/app/detail/components/context'; -import { useChatTest } from '@/pages/app/detail/components/useChatTest'; +import { AppContext } from '@/pageComponents/app/detail/context'; +import { useChatTest } from '../../useChatTest'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs'; import { PluginRunBoxTabEnum } from '@/components/core/chat/ChatContainer/PluginRunBox/constants'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ImportSettings.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ImportSettings.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/SelectAppModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/SelectAppModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ButtonEdge.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ButtonEdge.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ButtonEdge.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ButtonEdge.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/Container.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/Container.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/Container.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/Container.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ContextMenu.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ContextMenu.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ContextMenu.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ContextMenu.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/Divider.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/Divider.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/Divider.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/Divider.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/FlowController.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/FlowController.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/HelperLines.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/HelperLines.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/IOTitle.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/IOTitle.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/SaveAndPublish.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/SaveAndPublish.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/SaveAndPublish.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/SaveAndPublish.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/index.module.scss b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/index.module.scss similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/index.module.scss rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/index.module.scss diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useDebug.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useDebug.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useDebug.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useDebug.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useKeyboard.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useKeyboard.tsx index 8400c4274f39..92df705ff9d8 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useKeyboard.tsx @@ -1,6 +1,6 @@ import { useCallback } from 'react'; import { getNanoid } from '@fastgpt/global/common/string/tools'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { useTranslation } from 'next-i18next'; import { Node, useKeyPress } from 'reactflow'; import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useUtils.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useUtils.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopEnd.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoopEnd.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopEnd.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoopEnd.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeAnswer.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeAnswer.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeAnswer.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeAnswer.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeCQNode.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeCQNode.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCode.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeCode.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCode.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeCode.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeComment.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeComment.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeComment.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeComment.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeEmpty.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeEmpty.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeEmpty.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeEmpty.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeExtract/ExtractFieldModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeExtract/ExtractFieldModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeExtract/ExtractFieldModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeExtract/ExtractFieldModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeExtract/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeExtract/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeExtract/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeExtract/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeFormInput/InputFormEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/InputFormEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeFormInput/InputFormEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/InputFormEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeHttp/CurlImportModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeHttp/CurlImportModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeHttp/CurlImportModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeHttp/CurlImportModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx index e19f2af13bbd..9a0a5bcc0f93 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeHttp/index.tsx @@ -44,7 +44,7 @@ import IOTitle from '../../components/IOTitle'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../../../context'; import { useCreation, useMemoizedFn } from 'ahooks'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { getEditorVariables } from '../../../utils'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx index e1017d740bdd..0a0de9788f2d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx @@ -30,7 +30,7 @@ import { SourceHandle } from '../render/Handle'; import { Position, useReactFlow } from 'reactflow'; import { getRefData } from '@/web/core/workflow/utils'; import DragIcon from '@fastgpt/web/components/common/DndDrag/DragIcon'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { useI18n } from '@/web/context/I18n'; const ListItem = ({ diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeLaf.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeLaf.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx index 9d5894778442..b969230e3aa7 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx @@ -18,7 +18,9 @@ import { FlowValueTypeMap } from '@fastgpt/global/core/workflow/node/constant'; import MySelect from '@fastgpt/web/components/common/MySelect'; -import MultipleSelect from '@fastgpt/web/components/common/MySelect/MultipleSelect'; +import MultipleSelect, { + useMultipleSelect +} from '@fastgpt/web/components/common/MySelect/MultipleSelect'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import JsonEditor from '@fastgpt/web/components/common/Textarea/JsonEditor'; import React, { useMemo } from 'react'; @@ -79,10 +81,13 @@ const InputTypeConfig = ({ const maxLength = watch('maxLength'); const max = watch('max'); const min = watch('min'); - const selectValueTypeList = watch('customInputConfig.selectValueTypeList'); const defaultValue = watch('defaultValue'); const valueType = watch('valueType'); + const selectValueTypeList = watch('customInputConfig.selectValueTypeList'); + const { isSelectAll: isSelectAllValueType, setIsSelectAll: setIsSelectAllValueType } = + useMultipleSelect(selectValueTypeList, false); + const toolDescription = watch('toolDescription'); const isToolInput = !!toolDescription; @@ -359,10 +364,14 @@ const InputTypeConfig = ({ list={valueTypeSelectList} bg={'myGray.50'} + minH={'40px'} + py={2} value={selectValueTypeList || []} onSelect={(e) => { setValue('customInputConfig.selectValueTypeList', e); }} + isSelectAll={isSelectAllValueType} + setIsSelectAll={setIsSelectAllValueType} /> diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/NodePluginConfig.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/NodePluginConfig.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/NodePluginConfig.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/NodePluginConfig.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginInput.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginInput.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginInput.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginInput.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutput.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutput.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutput.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutput.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutputEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutputEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutputEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/PluginOutputEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/VariableTable.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/VariableTable.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodePluginIO/VariableTable.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/VariableTable.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeSimple.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeSimple.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx index d7c20432ef07..8f9660224656 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSystemConfig.tsx @@ -21,7 +21,7 @@ import { } from '@fastgpt/global/core/app/type'; import { useMemoizedFn } from 'ahooks'; import VariableEdit from '@/components/core/app/VariableEdit'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import WelcomeTextConfig from '@/components/core/app/WelcomeTextConfig'; import FileSelect from '@/components/core/app/FileSelect'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeToolParams/ToolParamsEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolParams/ToolParamsEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeToolParams/ToolParamsEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolParams/ToolParamsEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeToolParams/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolParams/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeToolParams/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolParams/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeTools.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeTools.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx index 4be1f4dc4461..0e5689678644 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx @@ -29,7 +29,7 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { ReferenceItemValueType, ReferenceValueType } from '@fastgpt/global/core/workflow/type/io'; import { ReferSelector, useReference } from './render/RenderInput/templates/Reference'; import { getRefData } from '@/web/core/workflow/utils'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor'; import { useCreation, useMemoizedFn } from 'ahooks'; import { getEditorVariables } from '../../utils'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx index 41ee01117ada..d61d90a3935a 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeWorkflowStart.tsx @@ -12,7 +12,7 @@ import { useCreation } from 'ahooks'; import { FlowNodeOutputItemType } from '@fastgpt/global/core/workflow/type/io'; import { FlowNodeOutputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { workflowSystemVariables } from '@/web/core/app/utils'; import { formatEditorVariablePickerIcon, diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx index 428dea606ea1..e7bc2f7d9238 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'next-i18next'; import { Connection, Handle, Position } from 'reactflow'; import { useCallback, useMemo } from 'react'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { WorkflowNodeEdgeContext } from '../../../../context/workflowInitContext'; const handleSize = '16px'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/style.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/style.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/style.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/style.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/FieldEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/FieldEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/FieldEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/FieldEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx similarity index 96% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx index b372f2655186..9a53ce94da69 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/Label.tsx @@ -7,7 +7,7 @@ import NodeInputSelect from '@fastgpt/web/components/core/workflow/NodeInputSele import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import ValueTypeLabel from '../ValueTypeLabel'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx index 36ab6454d684..30799758ea3e 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx @@ -7,7 +7,7 @@ import dynamic from 'next/dynamic'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import { FlowNodeInputItemType, ReferenceValueType } from '@fastgpt/global/core/workflow/type/io'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { defaultInput } from '../../FieldEditModal'; import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils'; import { ReferSelector, useReference } from '../Reference'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx similarity index 92% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx index 4636e74b6c21..786d6504c262 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/JsonEditor.tsx @@ -3,11 +3,11 @@ import type { RenderInputProps } from '../type'; import JSONEditor from '@fastgpt/web/components/common/Textarea/JsonEditor'; import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/workflow/utils'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils'; import { useCreation } from 'ahooks'; import { useTranslation } from 'next-i18next'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; const JsonEditor = ({ inputs = [], item, nodeId }: RenderInputProps) => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx similarity index 90% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx index 2a7b8416c9d5..35db09e7b36b 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; import type { RenderInputProps } from '../type'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; const NumberInputRender = ({ item, nodeId }: RenderInputProps) => { diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx index 6df07b6f1ba9..9c5775da5c5f 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Reference.tsx @@ -18,9 +18,9 @@ import type { } from '@fastgpt/global/core/workflow/type/io'; import dynamic from 'next/dynamic'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { WorkflowNodeEdgeContext } from '../../../../../context/workflowInitContext'; const MultipleRowSelect = dynamic(() => diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx similarity index 90% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx index 7a4aa5093bb1..10be856252f4 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Select.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; import type { RenderInputProps } from '../type'; import MySelect from '@fastgpt/web/components/common/MySelect'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { useContextSelector } from 'use-context-selector'; const SelectRender = ({ item, nodeId }: RenderInputProps) => { diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx similarity index 96% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx index a7a9145998cd..6bcf640d6a14 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectApp.tsx @@ -6,7 +6,7 @@ import Avatar from '@fastgpt/web/components/common/Avatar'; import SelectAppModal from '../../../../SelectAppModal'; import { useTranslation } from 'next-i18next'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { getAppDetailById } from '@/web/core/app/api'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx index b4bdb70e8888..89d2aa6778f4 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx @@ -11,7 +11,7 @@ import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants'; import dynamic from 'next/dynamic'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx similarity index 94% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx index e3834f6df02a..38918d81695a 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx @@ -10,7 +10,7 @@ import DatasetParamsModal, { DatasetParamsProps } from '@/components/core/app/Da import { useSystemStore } from '@/web/common/system/useSystemStore'; import SearchParamsTip from '@/components/core/dataset/SearchParamsTip'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { getWebLLMModel } from '@/web/common/system/utils'; import { defaultDatasetMaxTokens } from '@fastgpt/global/core/app/constants'; @@ -19,7 +19,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => { const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); const { t } = useTranslation(); - const { llmModelList } = useSystemStore(); + const { defaultModels } = useSystemStore(); const [data, setData] = useState({ searchMode: DatasetSearchModeEnum.embedding, @@ -27,7 +27,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => { similarity: 0.5, usingReRank: false, datasetSearchUsingExtensionQuery: true, - datasetSearchExtensionModel: llmModelList[0]?.model, + datasetSearchExtensionModel: defaultModels.llm?.model, datasetSearchExtensionBg: '' }); @@ -45,7 +45,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => { }); return maxTokens; - }, [nodeList, llmModelList]); + }, [nodeList]); const { isOpen, onOpen, onClose } = useDisclosure(); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx similarity index 78% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx index b4c3dfca98d3..470b71faa839 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectLLMModel.tsx @@ -4,7 +4,8 @@ import { useSystemStore } from '@/web/common/system/useSystemStore'; import { llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants'; import AIModelSelector from '@/components/Select/AIModelSelector'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; +import { getWebDefaultModel } from '@/web/common/system/utils'; const SelectAiModelRender = ({ item, nodeId }: RenderInputProps) => { const { llmModelList } = useSystemStore(); @@ -21,6 +22,9 @@ const SelectAiModelRender = ({ item, nodeId }: RenderInputProps) => { }), [llmModelList, item.llmModelType] ); + const defaultModel = useMemo(() => { + return getWebDefaultModel(modelList).model; + }, [modelList]); const onChangeModel = useCallback( (e: string) => { @@ -38,10 +42,10 @@ const SelectAiModelRender = ({ item, nodeId }: RenderInputProps) => { ); useEffect(() => { - if (!item.value && modelList.length > 0) { - onChangeModel(modelList[0].model); + if (!modelList.find((model) => model.model === item.value) && !!defaultModel) { + onChangeModel(defaultModel); } - }, []); + }, [defaultModel, item.value, modelList, onChangeModel]); const Render = useMemo(() => { return ( diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx similarity index 89% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx index 13038c26da35..5e4e2c557c95 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingLLMModel.tsx @@ -4,7 +4,7 @@ import type { SettingAIDataType } from '@fastgpt/global/core/app/type.d'; import SettingLLMModel from '@/components/core/ai/SettingLLMModel'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; const SelectAiModelRender = ({ item, inputs = [], nodeId }: RenderInputProps) => { const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode); @@ -38,7 +38,9 @@ const SelectAiModelRender = ({ item, inputs = [], nodeId }: RenderInputProps) => (input) => input.key === NodeInputKeyEnum.aiChatIsResponseText )?.value, aiChatVision: - inputs.find((input) => input.key === NodeInputKeyEnum.aiChatVision)?.value ?? true + inputs.find((input) => input.key === NodeInputKeyEnum.aiChatVision)?.value ?? true, + aiChatReasoning: + inputs.find((input) => input.key === NodeInputKeyEnum.aiChatReasoning)?.value ?? true }), [inputs] ); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx index 29a8476037dc..1d8296aa8e59 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx @@ -19,10 +19,10 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import Reference from './Reference'; import ValueTypeLabel from '../../ValueTypeLabel'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils'; import { useCreation } from 'ahooks'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import { datasetQuoteValueDesc } from '@fastgpt/global/core/workflow/node/constant'; @@ -79,6 +79,16 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo }>(); const quoteTemplateVariables = useMemo( () => [ + { + key: 'id', + label: 'id', + icon: 'core/app/simpleMode/variable' + }, + { + key: 'source', + label: t('common:core.dataset.search.Source name'), + icon: 'core/app/simpleMode/variable' + }, { key: 'q', label: 'q', @@ -90,13 +100,8 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo icon: 'core/app/simpleMode/variable' }, { - key: 'source', - label: t('common:core.dataset.search.Source name'), - icon: 'core/app/simpleMode/variable' - }, - { - key: 'sourceId', - label: t('common:core.dataset.search.Source id'), + key: 'updateTime', + label: t('app:source_updateTime'), icon: 'core/app/simpleMode/variable' }, { diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx similarity index 92% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx index bcbbcd6202fa..451c612395b7 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Slider.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'next-i18next'; import { Box } from '@chakra-ui/react'; import MySlider from '@/components/Slider'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; const SliderRender = ({ item, nodeId }: RenderInputProps) => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx similarity index 89% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx index 5520d91af4ea..e5ddc80029a6 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Switch.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import type { RenderInputProps } from '../type'; import { Switch } from '@chakra-ui/react'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; const SwitchRender = ({ item, nodeId }: RenderInputProps) => { const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx similarity index 92% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx index a7c82f363a20..d2895497faf7 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/TextInput.tsx @@ -3,9 +3,9 @@ import type { RenderInputProps } from '../type'; import { useTranslation } from 'next-i18next'; import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { useCreation } from 'ahooks'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { getEditorVariables } from '../../../../../utils'; import { WorkflowNodeEdgeContext } from '../../../../../context/workflowInitContext'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx similarity index 94% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx index d190e6fb2839..3c18d23f242f 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/Textarea.tsx @@ -3,9 +3,9 @@ import type { RenderInputProps } from '../type'; import { useTranslation } from 'next-i18next'; import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { useCreation } from 'ahooks'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import { getEditorVariables } from '../../../../../utils'; import { WorkflowNodeEdgeContext } from '../../../../../context/workflowInitContext'; import { useSystemStore } from '@/web/common/system/useSystemStore'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/type.d.ts b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/type.d.ts similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderInput/type.d.ts rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/type.d.ts diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/FieldEditModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/FieldEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/FieldEditModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/FieldEditModal.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/Label.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/Label.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/Label.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/Label.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx index 35ef4609c783..22f040f85e36 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/index.tsx @@ -9,7 +9,7 @@ import { SmallAddIcon } from '@chakra-ui/icons'; import VariableTable from '../../NodePluginIO/VariableTable'; import { FlowValueTypeMap } from '@fastgpt/global/core/workflow/node/constant'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import dynamic from 'next/dynamic'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/type.d.ts b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/type.d.ts similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderOutput/type.d.ts rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderOutput/type.d.ts diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx similarity index 98% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx index dfadba769e7e..a1a87f63062d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx @@ -18,7 +18,7 @@ import { useRequest } from '@fastgpt/web/hooks/useRequest'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io.d'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants'; import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx similarity index 97% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx index cf6513739593..fb7e478ca572 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx @@ -18,7 +18,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import dynamic from 'next/dynamic'; import { defaultEditFormData } from './EditFieldModal'; import { useContextSelector } from 'use-context-selector'; -import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context'; +import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import IOTitle from '../../../components/IOTitle'; import { SmallAddIcon } from '@chakra-ui/icons'; import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/type.d.ts b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/type.d.ts similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/type.d.ts rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderToolInput/type.d.ts diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/constants.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/constants.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/constants.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/constants.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx similarity index 99% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx index f2fe96350c64..5b8ff1f50b5d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx @@ -23,7 +23,7 @@ import { defaultRunningStatus } from '../constants'; import { checkNodeRunStatus } from '@fastgpt/global/core/workflow/runtime/utils'; import { getHandleId } from '@fastgpt/global/core/workflow/utils'; import { AppChatConfigType } from '@fastgpt/global/core/app/type'; -import { AppContext } from '@/pages/app/detail/components/context'; +import { AppContext } from '@/pageComponents/app/detail/context'; import ChatTest from '../Flow/ChatTest'; import { useDisclosure } from '@chakra-ui/react'; import { uiWorkflow2StoreWorkflow } from '../utils'; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowEventContext.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowEventContext.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowEventContext.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowEventContext.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowInitContext.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowInitContext.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowInitContext.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowInitContext.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowStatusContext.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowStatusContext.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/context/workflowStatusContext.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowStatusContext.tsx diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx rename to projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx diff --git a/projects/app/src/pages/app/detail/components/constants.tsx b/projects/app/src/pageComponents/app/detail/constants.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/constants.tsx rename to projects/app/src/pageComponents/app/detail/constants.tsx diff --git a/projects/app/src/pages/app/detail/components/context.tsx b/projects/app/src/pageComponents/app/detail/context.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/context.tsx rename to projects/app/src/pageComponents/app/detail/context.tsx diff --git a/projects/app/src/pages/app/detail/components/useChatTest.tsx b/projects/app/src/pageComponents/app/detail/useChatTest.tsx similarity index 100% rename from projects/app/src/pages/app/detail/components/useChatTest.tsx rename to projects/app/src/pageComponents/app/detail/useChatTest.tsx diff --git a/projects/app/src/pages/app/list/components/CreateModal.tsx b/projects/app/src/pageComponents/app/list/CreateModal.tsx similarity index 100% rename from projects/app/src/pages/app/list/components/CreateModal.tsx rename to projects/app/src/pageComponents/app/list/CreateModal.tsx diff --git a/projects/app/src/pages/app/list/components/HttpPluginEditModal.tsx b/projects/app/src/pageComponents/app/list/HttpPluginEditModal.tsx similarity index 100% rename from projects/app/src/pages/app/list/components/HttpPluginEditModal.tsx rename to projects/app/src/pageComponents/app/list/HttpPluginEditModal.tsx diff --git a/projects/app/src/pages/app/list/components/JsonImportModal.tsx b/projects/app/src/pageComponents/app/list/JsonImportModal.tsx similarity index 100% rename from projects/app/src/pages/app/list/components/JsonImportModal.tsx rename to projects/app/src/pageComponents/app/list/JsonImportModal.tsx diff --git a/projects/app/src/pages/app/list/components/List.tsx b/projects/app/src/pageComponents/app/list/List.tsx similarity index 99% rename from projects/app/src/pages/app/list/components/List.tsx rename to projects/app/src/pageComponents/app/list/List.tsx index 66af89fbe16a..234ba48b2737 100644 --- a/projects/app/src/pages/app/list/components/List.tsx +++ b/projects/app/src/pageComponents/app/list/List.tsx @@ -24,7 +24,7 @@ import { postUpdateAppCollaborators } from '@/web/core/app/api/collaborator'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; -import AppTypeTag from '@/pages/app/list/components/TypeTag'; +import AppTypeTag from './TypeTag'; const EditResourceModal = dynamic(() => import('@/components/common/Modal/EditResourceModal')); const ConfigPerModal = dynamic(() => import('@/components/support/permission/ConfigPerModal')); diff --git a/projects/app/src/pages/app/list/components/TemplateMarketModal.tsx b/projects/app/src/pageComponents/app/list/TemplateMarketModal.tsx similarity index 100% rename from projects/app/src/pages/app/list/components/TemplateMarketModal.tsx rename to projects/app/src/pageComponents/app/list/TemplateMarketModal.tsx diff --git a/projects/app/src/pages/app/list/components/TypeTag.tsx b/projects/app/src/pageComponents/app/list/TypeTag.tsx similarity index 95% rename from projects/app/src/pages/app/list/components/TypeTag.tsx rename to projects/app/src/pageComponents/app/list/TypeTag.tsx index 63111dfff253..9fa4d3e6efb6 100644 --- a/projects/app/src/pages/app/list/components/TypeTag.tsx +++ b/projects/app/src/pageComponents/app/list/TypeTag.tsx @@ -1,6 +1,5 @@ import React, { useRef } from 'react'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; -import MyTag from '@fastgpt/web/components/common/Tag/index'; import { useI18n } from '@/web/context/I18n'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { Box, Flex } from '@chakra-ui/react'; diff --git a/projects/app/src/pages/app/list/components/context.tsx b/projects/app/src/pageComponents/app/list/context.tsx similarity index 100% rename from projects/app/src/pages/app/list/components/context.tsx rename to projects/app/src/pageComponents/app/list/context.tsx diff --git a/projects/app/src/pages/chat/components/ChatHeader.tsx b/projects/app/src/pageComponents/chat/ChatHeader.tsx similarity index 100% rename from projects/app/src/pages/chat/components/ChatHeader.tsx rename to projects/app/src/pageComponents/chat/ChatHeader.tsx diff --git a/projects/app/src/pages/chat/components/ChatHistorySlider.tsx b/projects/app/src/pageComponents/chat/ChatHistorySlider.tsx similarity index 100% rename from projects/app/src/pages/chat/components/ChatHistorySlider.tsx rename to projects/app/src/pageComponents/chat/ChatHistorySlider.tsx diff --git a/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx b/projects/app/src/pageComponents/chat/CustomPluginRunBox.tsx similarity index 100% rename from projects/app/src/pages/chat/components/CustomPluginRunBox.tsx rename to projects/app/src/pageComponents/chat/CustomPluginRunBox.tsx diff --git a/projects/app/src/pages/chat/components/Empty.tsx b/projects/app/src/pageComponents/chat/Empty.tsx similarity index 100% rename from projects/app/src/pages/chat/components/Empty.tsx rename to projects/app/src/pageComponents/chat/Empty.tsx diff --git a/projects/app/src/pages/chat/components/SliderApps.tsx b/projects/app/src/pageComponents/chat/SliderApps.tsx similarity index 100% rename from projects/app/src/pages/chat/components/SliderApps.tsx rename to projects/app/src/pageComponents/chat/SliderApps.tsx diff --git a/projects/app/src/pages/chat/components/ToolMenu.tsx b/projects/app/src/pageComponents/chat/ToolMenu.tsx similarity index 100% rename from projects/app/src/pages/chat/components/ToolMenu.tsx rename to projects/app/src/pageComponents/chat/ToolMenu.tsx diff --git a/projects/app/src/pages/dataset/component/ApiDatasetForm.tsx b/projects/app/src/pageComponents/dataset/ApiDatasetForm.tsx similarity index 100% rename from projects/app/src/pages/dataset/component/ApiDatasetForm.tsx rename to projects/app/src/pageComponents/dataset/ApiDatasetForm.tsx diff --git a/projects/app/src/pages/dataset/component/EditFolderModal.tsx b/projects/app/src/pageComponents/dataset/EditFolderModal.tsx similarity index 100% rename from projects/app/src/pages/dataset/component/EditFolderModal.tsx rename to projects/app/src/pageComponents/dataset/EditFolderModal.tsx diff --git a/projects/app/src/pages/dataset/component/MemberManager.tsx b/projects/app/src/pageComponents/dataset/MemberManager.tsx similarity index 100% rename from projects/app/src/pages/dataset/component/MemberManager.tsx rename to projects/app/src/pageComponents/dataset/MemberManager.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/Context.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/Context.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/Context.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/Context.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/EmptyCollectionTip.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/EmptyCollectionTip.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/EmptyCollectionTip.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/EmptyCollectionTip.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/Header.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/Header.tsx similarity index 99% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/Header.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/Header.tsx index 45ecf4ed6b45..1462ab563a09 100644 --- a/projects/app/src/pages/dataset/detail/components/CollectionCard/Header.tsx +++ b/projects/app/src/pageComponents/dataset/detail/CollectionCard/Header.tsx @@ -30,8 +30,8 @@ import { DatasetTypeMap, DatasetStatusEnum } from '@fastgpt/global/core/dataset/constants'; -import EditFolderModal, { useEditFolder } from '../../../component/EditFolderModal'; -import { TabEnum } from '../../index'; +import EditFolderModal, { useEditFolder } from '../../EditFolderModal'; +import { TabEnum } from '../../../../pages/dataset/detail/index'; import ParentPath from '@/components/common/ParentPaths'; import dynamic from 'next/dynamic'; diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/HeaderTagPopOver.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/HeaderTagPopOver.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/HeaderTagPopOver.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/HeaderTagPopOver.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/TagManageModal.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/TagManageModal.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/TagManageModal.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/TagManageModal.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/TagsPopOver.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/TagsPopOver.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/TagsPopOver.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/TagsPopOver.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/WebsiteConfig.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/WebsiteConfig.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/WebsiteConfig.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/WebsiteConfig.tsx diff --git a/projects/app/src/pages/dataset/detail/components/CollectionCard/index.tsx b/projects/app/src/pageComponents/dataset/detail/CollectionCard/index.tsx similarity index 99% rename from projects/app/src/pages/dataset/detail/components/CollectionCard/index.tsx rename to projects/app/src/pageComponents/dataset/detail/CollectionCard/index.tsx index 26cb172437f2..d298da150aef 100644 --- a/projects/app/src/pages/dataset/detail/components/CollectionCard/index.tsx +++ b/projects/app/src/pageComponents/dataset/detail/CollectionCard/index.tsx @@ -32,7 +32,7 @@ import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { getCollectionIcon } from '@fastgpt/global/core/dataset/utils'; -import { TabEnum } from '../../index'; +import { TabEnum } from '../../../../pages/dataset/detail/index'; import dynamic from 'next/dynamic'; import SelectCollections from '@/web/core/dataset/components/SelectCollections'; import { useToast } from '@fastgpt/web/hooks/useToast'; diff --git a/projects/app/src/pages/dataset/detail/components/DataCard.tsx b/projects/app/src/pageComponents/dataset/detail/DataCard.tsx similarity index 99% rename from projects/app/src/pages/dataset/detail/components/DataCard.tsx rename to projects/app/src/pageComponents/dataset/detail/DataCard.tsx index 4b2f5f4fcc9a..99b3ff701642 100644 --- a/projects/app/src/pages/dataset/detail/components/DataCard.tsx +++ b/projects/app/src/pageComponents/dataset/detail/DataCard.tsx @@ -13,7 +13,7 @@ import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import MyIcon from '@fastgpt/web/components/common/Icon'; import MyInput from '@/components/MyInput'; -import InputDataModal from '../components/InputDataModal'; +import InputDataModal from './InputDataModal'; import RawSourceBox from '@/components/core/dataset/RawSourceBox'; import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; diff --git a/projects/app/src/pages/dataset/detail/components/Import/Context.tsx b/projects/app/src/pageComponents/dataset/detail/Import/Context.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/Context.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/Context.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/commonProgress/DataProcess.tsx b/projects/app/src/pageComponents/dataset/detail/Import/commonProgress/DataProcess.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/commonProgress/DataProcess.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/commonProgress/DataProcess.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/commonProgress/PreviewData.tsx b/projects/app/src/pageComponents/dataset/detail/Import/commonProgress/PreviewData.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/commonProgress/PreviewData.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/commonProgress/PreviewData.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/commonProgress/Upload.tsx b/projects/app/src/pageComponents/dataset/detail/Import/commonProgress/Upload.tsx similarity index 99% rename from projects/app/src/pages/dataset/detail/components/Import/commonProgress/Upload.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/commonProgress/Upload.tsx index b51c53dad07d..e811a52540dd 100644 --- a/projects/app/src/pages/dataset/detail/components/Import/commonProgress/Upload.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Import/commonProgress/Upload.tsx @@ -20,7 +20,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { useRouter } from 'next/router'; -import { TabEnum } from '../../../index'; +import { TabEnum } from '../../../../../pages/dataset/detail/index'; import { postCreateDatasetApiDatasetCollection, postCreateDatasetCsvTableCollection, diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/FileSelector.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/FileSelector.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/FileSourceSelector.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/FileSourceSelector.tsx similarity index 96% rename from projects/app/src/pages/dataset/detail/components/Import/components/FileSourceSelector.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/FileSourceSelector.tsx index 604f2a9de6d1..293bf24375b1 100644 --- a/projects/app/src/pages/dataset/detail/components/Import/components/FileSourceSelector.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Import/components/FileSourceSelector.tsx @@ -4,7 +4,7 @@ import { ModalBody, ModalFooter, Button } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import LeftRadio from '@fastgpt/web/components/common/Radio/LeftRadio'; import { useRouter } from 'next/router'; -import { TabEnum } from '../../..'; +import { TabEnum } from '../../../../../pages/dataset/detail'; import { ImportDataSourceEnum } from '@fastgpt/global/core/dataset/constants'; const FileModeSelector = ({ onClose }: { onClose: () => void }) => { diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/Preview.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/Preview.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/components/Preview.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/Preview.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/PreviewChunks.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/PreviewChunks.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/components/PreviewChunks.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/PreviewChunks.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/PreviewRawText.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/PreviewRawText.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/components/PreviewRawText.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/PreviewRawText.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/RenderFiles.tsx b/projects/app/src/pageComponents/dataset/detail/Import/components/RenderFiles.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/components/RenderFiles.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/components/RenderFiles.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/APIDataset.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/APIDataset.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/ExternalFile.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/ExternalFile.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/FileCustomText.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/FileCustomText.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/FileLink.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/FileLink.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/FileLocal.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/FileLocal.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/ReTraining.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/ReTraining.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/diffSource/TableLocal.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/TableLocal.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/diffSource/TableLocal.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/diffSource/TableLocal.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/index.tsx b/projects/app/src/pageComponents/dataset/detail/Import/index.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/index.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/index.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Import/type.d.ts b/projects/app/src/pageComponents/dataset/detail/Import/type.d.ts similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/type.d.ts rename to projects/app/src/pageComponents/dataset/detail/Import/type.d.ts diff --git a/projects/app/src/pages/dataset/detail/components/Import/utils.tsx b/projects/app/src/pageComponents/dataset/detail/Import/utils.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/Import/utils.tsx rename to projects/app/src/pageComponents/dataset/detail/Import/utils.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Info/components/EditApiServiceModal.tsx b/projects/app/src/pageComponents/dataset/detail/Info/components/EditApiServiceModal.tsx similarity index 97% rename from projects/app/src/pages/dataset/detail/components/Info/components/EditApiServiceModal.tsx rename to projects/app/src/pageComponents/dataset/detail/Info/components/EditApiServiceModal.tsx index d46a6ee81f72..57fee7f5953d 100644 --- a/projects/app/src/pages/dataset/detail/components/Info/components/EditApiServiceModal.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Info/components/EditApiServiceModal.tsx @@ -6,7 +6,7 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useForm } from 'react-hook-form'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { APIFileServer, FeishuServer, YuqueServer } from '@fastgpt/global/core/dataset/apiDataset'; -import ApiDatasetForm from '@/pages/dataset/component/ApiDatasetForm'; +import ApiDatasetForm from '@/pageComponents/dataset/ApiDatasetForm'; import { useContextSelector } from 'use-context-selector'; import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext'; import { datasetTypeCourseMap } from '@/web/core/dataset/constants'; diff --git a/projects/app/src/pages/dataset/detail/components/Info/index.tsx b/projects/app/src/pageComponents/dataset/detail/Info/index.tsx similarity index 97% rename from projects/app/src/pages/dataset/detail/components/Info/index.tsx rename to projects/app/src/pageComponents/dataset/detail/Info/index.tsx index e3269664aa73..c35a0515b358 100644 --- a/projects/app/src/pages/dataset/detail/components/Info/index.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Info/index.tsx @@ -9,7 +9,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import AIModelSelector from '@/components/Select/AIModelSelector'; import { postRebuildEmbedding } from '@/web/core/dataset/api'; -import type { VectorModelItemType } from '@fastgpt/global/core/ai/model.d'; +import type { EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d'; import { useContextSelector } from 'use-context-selector'; import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext'; import MyDivider from '@fastgpt/web/components/common/MyDivider/index'; @@ -18,7 +18,7 @@ import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant'; -import MemberManager from '../../../component/MemberManager'; +import MemberManager from '../../MemberManager'; import { getCollaboratorList, postUpdateDatasetCollaborators, @@ -50,7 +50,7 @@ const Info = ({ datasetId }: { datasetId: string }) => { const vectorModel = watch('vectorModel'); const agentModel = watch('agentModel'); - const { feConfigs, datasetModelList, vectorModelList } = useSystemStore(); + const { feConfigs, datasetModelList, embeddingModelList } = useSystemStore(); const { ConfirmModal: ConfirmDelModal } = useConfirm({ content: t('common:core.dataset.Delete Confirm'), type: 'delete' @@ -80,7 +80,7 @@ const Info = ({ datasetId }: { datasetId: string }) => { ); const { runAsync: onRebuilding } = useRequest2( - (vectorModel: VectorModelItemType) => { + (vectorModel: EmbeddingModelItemType) => { return postRebuildEmbedding({ datasetId, vectorModel: vectorModel.model @@ -186,12 +186,12 @@ const Info = ({ datasetId }: { datasetId: string }) => { ) : undefined } - list={vectorModelList.map((item) => ({ + list={embeddingModelList.map((item) => ({ label: item.name, value: item.model }))} onchange={(e) => { - const vectorModel = vectorModelList.find((item) => item.model === e); + const vectorModel = embeddingModelList.find((item) => item.model === e); if (!vectorModel) return; return onOpenConfirmRebuild(async () => { await onRebuilding(vectorModel); diff --git a/projects/app/src/pages/dataset/detail/components/InputDataModal.tsx b/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx similarity index 98% rename from projects/app/src/pages/dataset/detail/components/InputDataModal.tsx rename to projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx index a3a40d6f137e..e39373e6f101 100644 --- a/projects/app/src/pages/dataset/detail/components/InputDataModal.tsx +++ b/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx @@ -67,7 +67,7 @@ const InputDataModal = ({ const theme = useTheme(); const { toast } = useToast(); const [currentTab, setCurrentTab] = useState(TabEnum.content); - const { vectorModelList } = useSystemStore(); + const { embeddingModelList, defaultModels } = useSystemStore(); const { isPc } = useSystem(); const { register, handleSubmit, reset, control } = useForm(); const { @@ -158,11 +158,11 @@ const InputDataModal = ({ const maxToken = useMemo(() => { const vectorModel = - vectorModelList.find((item) => item.model === collection.dataset.vectorModel) || - vectorModelList[0]; + embeddingModelList.find((item) => item.model === collection.dataset.vectorModel) || + defaultModels.embedding; return vectorModel?.maxToken || 3000; - }, [collection.dataset.vectorModel, vectorModelList]); + }, [collection.dataset.vectorModel, defaultModels.embedding, embeddingModelList]); // import new data const { mutate: sureImportData, isLoading: isImporting } = useRequest({ diff --git a/projects/app/src/pages/dataset/detail/components/MetaDataCard.tsx b/projects/app/src/pageComponents/dataset/detail/MetaDataCard.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/MetaDataCard.tsx rename to projects/app/src/pageComponents/dataset/detail/MetaDataCard.tsx diff --git a/projects/app/src/pages/dataset/detail/components/NavBar.tsx b/projects/app/src/pageComponents/dataset/detail/NavBar.tsx similarity index 100% rename from projects/app/src/pages/dataset/detail/components/NavBar.tsx rename to projects/app/src/pageComponents/dataset/detail/NavBar.tsx diff --git a/projects/app/src/pages/dataset/detail/components/Test.tsx b/projects/app/src/pageComponents/dataset/detail/Test.tsx similarity index 98% rename from projects/app/src/pages/dataset/detail/components/Test.tsx rename to projects/app/src/pageComponents/dataset/detail/Test.tsx index 1e65f5d78889..8a119afcd77f 100644 --- a/projects/app/src/pages/dataset/detail/components/Test.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Test.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Box, Textarea, Button, Flex, useTheme, useDisclosure } from '@chakra-ui/react'; -import { useDatasetStore } from '@/web/core/dataset/store/dataset'; import { useSearchTestStore, SearchTestStoreItemType } from '@/web/core/dataset/store/searchTest'; import { postSearchText } from '@/web/core/dataset/api'; import MyIcon from '@fastgpt/web/components/common/Icon'; @@ -49,7 +48,7 @@ type FormType = { const Test = ({ datasetId }: { datasetId: string }) => { const { t } = useTranslation(); const { toast } = useToast(); - const { llmModelList } = useSystemStore(); + const { defaultModels } = useSystemStore(); const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail); const { pushDatasetTestItem } = useSearchTestStore(); const [inputType, setInputType] = useState<'text' | 'file'>('text'); @@ -70,8 +69,8 @@ const Test = ({ datasetId }: { datasetId: string }) => { usingReRank: false, limit: 5000, similarity: 0, - datasetSearchUsingExtensionQuery: true, - datasetSearchExtensionModel: llmModelList[0].model, + datasetSearchUsingExtensionQuery: false, + datasetSearchExtensionModel: defaultModels.llm?.model, datasetSearchExtensionBg: '' } } diff --git a/projects/app/src/pages/dataset/detail/components/styles.module.scss b/projects/app/src/pageComponents/dataset/detail/styles.module.scss similarity index 100% rename from projects/app/src/pages/dataset/detail/components/styles.module.scss rename to projects/app/src/pageComponents/dataset/detail/styles.module.scss diff --git a/projects/app/src/pages/dataset/list/component/CreateModal.tsx b/projects/app/src/pageComponents/dataset/list/CreateModal.tsx similarity index 71% rename from projects/app/src/pages/dataset/list/component/CreateModal.tsx rename to projects/app/src/pageComponents/dataset/list/CreateModal.tsx index f6ae59ea9d89..debf45fd5c57 100644 --- a/projects/app/src/pages/dataset/list/component/CreateModal.tsx +++ b/projects/app/src/pageComponents/dataset/list/CreateModal.tsx @@ -20,7 +20,8 @@ import ComplianceTip from '@/components/common/ComplianceTip/index'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { getDocPath } from '@/web/common/system/doc'; import { datasetTypeCourseMap } from '@/web/core/dataset/constants'; -import ApiDatasetForm from '../../component/ApiDatasetForm'; +import ApiDatasetForm from '../ApiDatasetForm'; +import { getWebDefaultModel } from '@/web/common/system/utils'; export type CreateDatasetType = | DatasetTypeEnum.dataset @@ -41,7 +42,7 @@ const CreateModal = ({ const { t } = useTranslation(); const { toast } = useToast(); const router = useRouter(); - const { vectorModelList, datasetModelList } = useSystemStore(); + const { defaultModels, embeddingModelList, datasetModelList } = useSystemStore(); const { isPc } = useSystem(); const datasetTypeMap = useMemo(() => { @@ -69,7 +70,7 @@ const CreateModal = ({ }; }, [t]); - const filterNotHiddenVectorModelList = vectorModelList.filter((item) => !item.hidden); + const filterNotHiddenVectorModelList = embeddingModelList.filter((item) => !item.hidden); const form = useForm({ defaultValues: { @@ -78,8 +79,8 @@ const CreateModal = ({ avatar: datasetTypeMap[type].icon, name: '', intro: '', - vectorModel: filterNotHiddenVectorModelList[0].model, - agentModel: datasetModelList[0].model + vectorModel: defaultModels.embedding?.model, + agentModel: getWebDefaultModel(datasetModelList)?.model } }); const { register, setValue, handleSubmit, watch } = form; @@ -172,73 +173,69 @@ const CreateModal = ({ />
- {filterNotHiddenVectorModelList.length > 1 && ( - + - - {t('common:core.ai.model.Vector Model')} - - - - ({ - label: item.name, - value: item.model - }))} - onchange={(e) => { - setValue('vectorModel' as const, e); - }} - /> - - - )} - {datasetModelList.length > 1 && ( - {t('common:core.ai.model.Vector Model')} + + + + ({ + label: item.name, + value: item.model + }))} + onchange={(e) => { + setValue('vectorModel' as const, e); + }} + /> + + + + - - {t('common:core.ai.model.Dataset Agent Model')} - - - - ({ - label: item.name, - value: item.model - }))} - onchange={(e) => { - setValue('agentModel' as const, e); - }} - /> - - - )} + {t('common:core.ai.model.Dataset Agent Model')} + + + + ({ + label: item.name, + value: item.model + }))} + onchange={(e) => { + setValue('agentModel' as const, e); + }} + /> + + {/* @ts-ignore */} diff --git a/projects/app/src/pages/dataset/list/component/List.tsx b/projects/app/src/pageComponents/dataset/list/List.tsx similarity index 99% rename from projects/app/src/pages/dataset/list/component/List.tsx rename to projects/app/src/pageComponents/dataset/list/List.tsx index db711e176b87..19c5c77a2ca0 100644 --- a/projects/app/src/pages/dataset/list/component/List.tsx +++ b/projects/app/src/pageComponents/dataset/list/List.tsx @@ -16,7 +16,7 @@ import { downloadFetch } from '@/web/common/system/utils'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import dynamic from 'next/dynamic'; import { useContextSelector } from 'use-context-selector'; -import { DatasetsContext } from '../context'; +import { DatasetsContext } from '../../../pages/dataset/list/context'; import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant'; import ConfigPerModal from '@/components/support/permission/ConfigPerModal'; import { diff --git a/projects/app/src/pages/dataset/list/component/SideTag.tsx b/projects/app/src/pageComponents/dataset/list/SideTag.tsx similarity index 100% rename from projects/app/src/pages/dataset/list/component/SideTag.tsx rename to projects/app/src/pageComponents/dataset/list/SideTag.tsx diff --git a/projects/app/src/pages/login/components/ForgetPasswordForm.tsx b/projects/app/src/pageComponents/login/ForgetPasswordForm.tsx similarity index 100% rename from projects/app/src/pages/login/components/ForgetPasswordForm.tsx rename to projects/app/src/pageComponents/login/ForgetPasswordForm.tsx diff --git a/projects/app/src/pages/login/components/LoginForm/components/FormLayout.tsx b/projects/app/src/pageComponents/login/LoginForm/FormLayout.tsx similarity index 97% rename from projects/app/src/pages/login/components/LoginForm/components/FormLayout.tsx rename to projects/app/src/pageComponents/login/LoginForm/FormLayout.tsx index 5a5a5cb338d3..912df8ffd606 100644 --- a/projects/app/src/pages/login/components/LoginForm/components/FormLayout.tsx +++ b/projects/app/src/pageComponents/login/LoginForm/FormLayout.tsx @@ -31,6 +31,7 @@ type OAuthItem = { const FormLayout = ({ children, setPageType, pageType }: Props) => { const { t } = useTranslation(); const router = useRouter(); + const rootLogin = router.query.rootLogin === '1'; const { setLoginStore, feConfigs } = useSystemStore(); const { isPc } = useSystem(); @@ -147,7 +148,9 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => { [lastRoute, router, setLoginStore, setPageType] ); + // Auto login useEffect(() => { + if (rootLogin) return; const sso = oAuthList.find((item) => item.provider === OAuthEnum.sso); const wecom = oAuthList.find((item) => item.provider === OAuthEnum.wecom); if (feConfigs?.sso?.autoLogin && sso) { @@ -157,7 +160,7 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => { // Auto wecom login onClickOauth(wecom); } - }, [feConfigs?.sso?.autoLogin, isWecomWorkTerminal, onClickOauth]); + }, [rootLogin, feConfigs?.sso?.autoLogin, isWecomWorkTerminal, onClickOauth]); return ( diff --git a/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx b/projects/app/src/pageComponents/login/LoginForm/LoginForm.tsx similarity index 99% rename from projects/app/src/pages/login/components/LoginForm/LoginForm.tsx rename to projects/app/src/pageComponents/login/LoginForm/LoginForm.tsx index ad365e4b2b26..4fad6e61c8e3 100644 --- a/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx +++ b/projects/app/src/pageComponents/login/LoginForm/LoginForm.tsx @@ -8,7 +8,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { getDocPath } from '@/web/common/system/doc'; import { useTranslation } from 'next-i18next'; -import FormLayout from './components/FormLayout'; +import FormLayout from './FormLayout'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; interface Props { diff --git a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx b/projects/app/src/pageComponents/login/LoginForm/WechatForm.tsx similarity index 97% rename from projects/app/src/pages/login/components/LoginForm/WechatForm.tsx rename to projects/app/src/pageComponents/login/LoginForm/WechatForm.tsx index 4d08509f9c04..d1d8c2c2c77e 100644 --- a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx +++ b/projects/app/src/pageComponents/login/LoginForm/WechatForm.tsx @@ -6,7 +6,7 @@ import { useQuery } from '@tanstack/react-query'; import { getWXLoginQR, getWXLoginResult } from '@/web/support/user/api'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { useToast } from '@fastgpt/web/hooks/useToast'; -import FormLayout from './components/FormLayout'; +import FormLayout from './FormLayout'; import { useTranslation } from 'next-i18next'; import Loading from '@fastgpt/web/components/common/MyLoading'; import MyImage from '@fastgpt/web/components/common/Image/MyImage'; diff --git a/projects/app/src/pages/login/components/RegisterForm.tsx b/projects/app/src/pageComponents/login/RegisterForm.tsx similarity index 100% rename from projects/app/src/pages/login/components/RegisterForm.tsx rename to projects/app/src/pageComponents/login/RegisterForm.tsx diff --git a/projects/app/src/pages/price/components/ExtraPlan.tsx b/projects/app/src/pageComponents/price/ExtraPlan.tsx similarity index 100% rename from projects/app/src/pages/price/components/ExtraPlan.tsx rename to projects/app/src/pageComponents/price/ExtraPlan.tsx diff --git a/projects/app/src/pages/price/components/FAQ.tsx b/projects/app/src/pageComponents/price/FAQ.tsx similarity index 100% rename from projects/app/src/pages/price/components/FAQ.tsx rename to projects/app/src/pageComponents/price/FAQ.tsx diff --git a/projects/app/src/pages/price/components/Points.tsx b/projects/app/src/pageComponents/price/Points.tsx similarity index 88% rename from projects/app/src/pages/price/components/Points.tsx rename to projects/app/src/pageComponents/price/Points.tsx index 72aa872784f1..6f74189d6167 100644 --- a/projects/app/src/pages/price/components/Points.tsx +++ b/projects/app/src/pageComponents/price/Points.tsx @@ -31,7 +31,7 @@ export default React.memo(Points); export const AiPointsTable = () => { const { t } = useTranslation(); - const { llmModelList, audioSpeechModelList, vectorModelList, whisperModel } = useSystemStore(); + const { llmModelList, ttsModelList, embeddingModelList, sttModelList } = useSystemStore(); return ( @@ -85,7 +85,7 @@ export const AiPointsTable = () => { - {vectorModelList?.map((item, i) => ( + {embeddingModelList?.map((item, i) => ( {item.name} @@ -111,7 +111,7 @@ export const AiPointsTable = () => { - {audioSpeechModelList?.map((item, i) => ( + {ttsModelList?.map((item, i) => ( {item.name} @@ -138,15 +138,17 @@ export const AiPointsTable = () => { - - {whisperModel?.name} - - {whisperModel?.charsPointsPrice + - t('common:support.wallet.subscription.point') + - ' / 60' + - t('common:unit.seconds')} - - + {sttModelList.map((item) => ( + + {item.name} + + {item.charsPointsPrice + + t('common:support.wallet.subscription.point') + + ' / 60' + + t('common:unit.seconds')} + + + ))} diff --git a/projects/app/src/pages/price/components/Standard.tsx b/projects/app/src/pageComponents/price/Standard.tsx similarity index 100% rename from projects/app/src/pages/price/components/Standard.tsx rename to projects/app/src/pageComponents/price/Standard.tsx diff --git a/projects/app/src/pages/toolkit/components/PluginCard.tsx b/projects/app/src/pageComponents/toolkit/PluginCard.tsx similarity index 100% rename from projects/app/src/pages/toolkit/components/PluginCard.tsx rename to projects/app/src/pageComponents/toolkit/PluginCard.tsx diff --git a/projects/app/src/pages/account/apikey.tsx b/projects/app/src/pages/account/apikey.tsx index eef200b5123a..0294a00947a6 100644 --- a/projects/app/src/pages/account/apikey.tsx +++ b/projects/app/src/pages/account/apikey.tsx @@ -2,7 +2,7 @@ import React from 'react'; import ApiKeyTable from '@/components/support/apikey/Table'; import { useTranslation } from 'next-i18next'; import { Box } from '@chakra-ui/react'; -import AccountContainer, { TabEnum } from './components/AccountContainer'; +import AccountContainer, { TabEnum } from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const ApiKey = () => { diff --git a/projects/app/src/pages/account/bill/index.tsx b/projects/app/src/pages/account/bill/index.tsx index 477baa082696..5bda548de4a9 100644 --- a/projects/app/src/pages/account/bill/index.tsx +++ b/projects/app/src/pages/account/bill/index.tsx @@ -3,9 +3,9 @@ import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; import dynamic from 'next/dynamic'; import { useState } from 'react'; import { useTranslation } from 'next-i18next'; -import ApplyInvoiceModal from './components/ApplyInvoiceModal'; +import ApplyInvoiceModal from '@/pageComponents/account/bill/ApplyInvoiceModal'; import { useRouter } from 'next/router'; -import AccountContainer, { TabEnum } from '../components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; export enum InvoiceTabEnum { @@ -14,9 +14,9 @@ export enum InvoiceTabEnum { invoiceHeader = 'invoiceHeader' } -const BillTable = dynamic(() => import('./components/BillTable')); -const InvoiceHeaderForm = dynamic(() => import('./components/InvoiceHeaderForm')); -const InvoiceTable = dynamic(() => import('./components/InvoiceTable')); +const BillTable = dynamic(() => import('@/pageComponents/account/bill/BillTable')); +const InvoiceHeaderForm = dynamic(() => import('@/pageComponents/account/bill/InvoiceHeaderForm')); +const InvoiceTable = dynamic(() => import('@/pageComponents/account/bill/InvoiceTable')); const BillAndInvoice = () => { const { t } = useTranslation(); const router = useRouter(); diff --git a/projects/app/src/pages/account/info/index.tsx b/projects/app/src/pages/account/info/index.tsx index 1adbff2167d6..8d516f971dde 100644 --- a/projects/app/src/pages/account/info/index.tsx +++ b/projects/app/src/pages/account/info/index.tsx @@ -38,14 +38,17 @@ import StandardPlanContentList from '@/components/support/wallet/StandardPlanCon import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { getWebReqUrl } from '@fastgpt/web/common/system/utils'; -import AccountContainer from '../components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useRouter } from 'next/router'; -import TeamSelector from '../components/TeamSelector'; +import TeamSelector from '@/pageComponents/account/TeamSelector'; -const StandDetailModal = dynamic(() => import('./components/standardDetailModal'), { ssr: false }); -const ConversionModal = dynamic(() => import('./components/ConversionModal')); -const UpdatePswModal = dynamic(() => import('./components/UpdatePswModal')); +const StandDetailModal = dynamic( + () => import('@/pageComponents/account/info/standardDetailModal'), + { ssr: false } +); +const ConversionModal = dynamic(() => import('@/pageComponents/account/info/ConversionModal')); +const UpdatePswModal = dynamic(() => import('@/pageComponents/account/info/UpdatePswModal')); const UpdateNotification = dynamic( () => import('@/components/support/user/inform/UpdateNotificationModal') ); diff --git a/projects/app/src/pages/account/inform.tsx b/projects/app/src/pages/account/inform.tsx index d0612c3385f7..e2fa08c1bc02 100644 --- a/projects/app/src/pages/account/inform.tsx +++ b/projects/app/src/pages/account/inform.tsx @@ -6,7 +6,7 @@ import { usePagination } from '@fastgpt/web/hooks/usePagination'; import { useLoading } from '@fastgpt/web/hooks/useLoading'; import { useTranslation } from 'next-i18next'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; -import AccountContainer from './components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const InformTable = () => { diff --git a/projects/app/src/pages/account/model/components/DefaultModal.tsx b/projects/app/src/pages/account/model/components/DefaultModal.tsx deleted file mode 100644 index 2568c9500468..000000000000 --- a/projects/app/src/pages/account/model/components/DefaultModal.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useMemo, useState } from 'react'; -import MyModal from '@fastgpt/web/components/common/MyModal'; -import { useTranslation } from 'next-i18next'; -import { Box, Flex, ModalBody } from '@chakra-ui/react'; -import { MultipleRowArraySelect } from '@fastgpt/web/components/common/MySelect/MultipleRowSelect'; -import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { ModelProviderList } from '@fastgpt/global/core/ai/provider'; -import Avatar from '@fastgpt/web/components/common/Avatar'; -import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants'; -import { getModelFromList } from '@fastgpt/global/core/ai/model'; - -const DefaultModal = ({ onClose }: { onClose: () => void }) => { - const { t } = useTranslation(); - const { llmModelList, vectorModelList, whisperModel, audioSpeechModelList, reRankModelList } = - useSystemStore(); - const [value, setValue] = useState([]); - - const modelList = useMemo(() => { - return [ - ...llmModelList, - ...vectorModelList, - ...audioSpeechModelList, - ...reRankModelList, - whisperModel - ].map((item) => ({ - provider: item.provider, - name: item.name, - model: item.model - })); - }, [llmModelList, vectorModelList, whisperModel, audioSpeechModelList, reRankModelList]); - - const selectorList = useMemo(() => { - const renderList = ModelProviderList.map<{ - label: React.JSX.Element; - value: string; - children: { label: string | React.ReactNode; value: string }[]; - }>((provider) => ({ - label: ( - - - {t(provider.name as any)} - - ), - value: provider.id, - children: [] - })); - - for (const item of modelList) { - const modelData = getModelFromList(modelList, item.model); - const provider = - renderList.find((item) => item.value === (modelData?.provider || 'Other')) ?? - renderList[renderList.length - 1]; - - provider.children.push({ - label: modelData.name, - value: modelData.model - }); - } - - return renderList.filter((item) => item.children.length > 0); - }, [modelList, t]); - - console.log(selectorList); - - return ( - - 11 - - ); -}; - -export default DefaultModal; diff --git a/projects/app/src/pages/account/model/index.tsx b/projects/app/src/pages/account/model/index.tsx index c0c1b5f50d48..4c796bb0024d 100644 --- a/projects/app/src/pages/account/model/index.tsx +++ b/projects/app/src/pages/account/model/index.tsx @@ -1,72 +1,43 @@ import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; -import React, { useState } from 'react'; -import AccountContainer from '../components/AccountContainer'; -import { Box, Button, Flex, useDisclosure } from '@chakra-ui/react'; +import React, { useMemo, useState } from 'react'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; +import { Box, Flex } from '@chakra-ui/react'; import ModelTable from '@/components/core/ai/ModelTable'; import { useUserStore } from '@/web/support/user/useUserStore'; import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; import { useTranslation } from 'next-i18next'; -import MyMenu from '@fastgpt/web/components/common/MyMenu'; import dynamic from 'next/dynamic'; -const DefaultModal = dynamic(() => import('./components/DefaultModal'), { - ssr: false -}); +const ModelConfigTable = dynamic(() => import('@/pageComponents/account/model/ModelConfigTable')); + +type TabType = 'model' | 'config' | 'channel'; const ModelProvider = () => { const { t } = useTranslation(); - const { userInfo } = useUserStore(); - const isRoot = userInfo?.username === 'root'; - const [tab, setTab] = useState<'model' | 'channel'>('model'); + const [tab, setTab] = useState('model'); - const { isOpen: isOpenDefault, onOpen: onOpenDefault, onClose: onCloseDefault } = useDisclosure(); + const Tab = useMemo(() => { + return ( + + list={[ + { label: t('account:active_model'), value: 'model' }, + { label: t('account:config_model'), value: 'config' } + // { label: t('account:channel'), value: 'channel' } + ]} + value={tab} + py={1} + onChange={setTab} + /> + ); + }, [t, tab]); return ( - {/* Header */} - {/* - - list={[ - { label: t('account:active_model'), value: 'model' }, - { label: t('account:channel'), value: 'channel' } - ]} - value={tab} - px={8} - py={1} - onChange={setTab} - /> - - {tab === 'model' && ( - {t('account:create_model')}} - menuList={[ - { - children: [ - { - label: t('account:default_model'), - onClick: onOpenDefault - }, - { - label: t('account:custom_model') - } - ] - } - ]} - /> - )} - {tab === 'channel' && } - */} - - {tab === 'model' && } - {/* {tab === 'channel' && } */} - + {tab === 'model' && } + {tab === 'config' && } - - {isOpenDefault && } ); }; @@ -80,3 +51,16 @@ export async function getServerSideProps(content: any) { } export default ModelProvider; + +const ValidModelTable = ({ Tab }: { Tab: React.ReactNode }) => { + const { userInfo } = useUserStore(); + const isRoot = userInfo?.username === 'root'; + return ( + <> + {isRoot && {Tab}} + + + + + ); +}; diff --git a/projects/app/src/pages/account/promotion.tsx b/projects/app/src/pages/account/promotion.tsx index 5da3e0b48815..5933737d74af 100644 --- a/projects/app/src/pages/account/promotion.tsx +++ b/projects/app/src/pages/account/promotion.tsx @@ -19,13 +19,13 @@ import { useQuery } from '@tanstack/react-query'; import { getPromotionInitData, getPromotionRecords } from '@/web/support/activity/promotion/api'; import { useUserStore } from '@/web/support/user/useUserStore'; -import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import dayjs from 'dayjs'; import { usePagination } from '@fastgpt/web/hooks/usePagination'; import { useLoading } from '@fastgpt/web/hooks/useLoading'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; -import AccountContainer from './components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const Promotion = () => { diff --git a/projects/app/src/pages/account/setting.tsx b/projects/app/src/pages/account/setting.tsx index b276ada5a900..2660fd5c3c5e 100644 --- a/projects/app/src/pages/account/setting.tsx +++ b/projects/app/src/pages/account/setting.tsx @@ -9,7 +9,7 @@ import { useForm } from 'react-hook-form'; import { UserUpdateParams } from '@/types/user'; import TimezoneSelect from '@fastgpt/web/components/common/MySelect/TimezoneSelect'; import I18nLngSelector from '@/components/Select/I18nLngSelector'; -import AccountContainer from './components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const Individuation = () => { diff --git a/projects/app/src/pages/account/team/index.tsx b/projects/app/src/pages/account/team/index.tsx index f8e41ef21425..9d70cea81924 100644 --- a/projects/app/src/pages/account/team/index.tsx +++ b/projects/app/src/pages/account/team/index.tsx @@ -1,9 +1,9 @@ import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; -import AccountContainer from '../components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { Box, Flex } from '@chakra-ui/react'; import Icon from '@fastgpt/web/components/common/Icon'; import { useTranslation } from 'next-i18next'; -import TeamSelector from '../components/TeamSelector'; +import TeamSelector from '@/pageComponents/account/TeamSelector'; import { useUserStore } from '@/web/support/user/useUserStore'; import React, { useMemo } from 'react'; import { useContextSelector } from 'use-context-selector'; diff --git a/projects/app/src/pages/account/thirdParty/index.tsx b/projects/app/src/pages/account/thirdParty/index.tsx index eb73ce2d5bc7..392af56c1fb4 100644 --- a/projects/app/src/pages/account/thirdParty/index.tsx +++ b/projects/app/src/pages/account/thirdParty/index.tsx @@ -1,4 +1,4 @@ -import AccountContainer from '../components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { Box, Flex, Grid, Progress, useDisclosure } from '@chakra-ui/react'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useTranslation } from 'next-i18next'; @@ -7,7 +7,7 @@ import { useUserStore } from '@/web/support/user/useUserStore'; import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant'; import dynamic from 'next/dynamic'; import { useState, useMemo } from 'react'; -import WorkflowVariableModal from './components/WorkflowVariableModal'; +import WorkflowVariableModal from '@/pageComponents/account/thirdParty/WorkflowVariableModal'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; @@ -16,7 +16,9 @@ import type { checkUsageResponse } from '@/pages/api/support/user/team/thirtdPar import MyBox from '@fastgpt/web/components/common/MyBox'; const LafAccountModal = dynamic(() => import('@/components/support/laf/LafAccountModal')); -const OpenAIAccountModal = dynamic(() => import('./components/OpenAIAccountModal')); +const OpenAIAccountModal = dynamic( + () => import('@/pageComponents/account/thirdParty/OpenAIAccountModal') +); export type ThirdPartyAccountType = { name: string; diff --git a/projects/app/src/pages/account/usage/index.tsx b/projects/app/src/pages/account/usage/index.tsx index 8db661730fea..c09c32fa3038 100644 --- a/projects/app/src/pages/account/usage/index.tsx +++ b/projects/app/src/pages/account/usage/index.tsx @@ -1,78 +1,64 @@ import React, { useEffect, useMemo, useState } from 'react'; -import { - Table, - Thead, - Tbody, - Tr, - Th, - Td, - TableContainer, - Flex, - Box, - Button -} from '@chakra-ui/react'; +import { Flex, Box, HStack } from '@chakra-ui/react'; import { UsageSourceEnum, UsageSourceMap } from '@fastgpt/global/support/wallet/usage/constants'; -import { getUserUsages } from '@/web/support/wallet/usage/api'; -import type { UsageItemType } from '@fastgpt/global/support/wallet/usage/type'; -import { usePagination } from '@fastgpt/web/hooks/usePagination'; -import { useLoading } from '@fastgpt/web/hooks/useLoading'; -import dayjs from 'dayjs'; import DateRangePicker, { type DateRangeType } from '@fastgpt/web/components/common/DateRangePicker'; -import { addDays } from 'date-fns'; -import dynamic from 'next/dynamic'; +import { addDays, startOfMonth, startOfWeek } from 'date-fns'; import { useTranslation } from 'next-i18next'; import { useUserStore } from '@/web/support/user/useUserStore'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import MySelect from '@fastgpt/web/components/common/MySelect'; -import { formatNumber } from '@fastgpt/global/common/math/tools'; -import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; -import { useSystem } from '@fastgpt/web/hooks/useSystem'; -import AccountContainer from '../components/AccountContainer'; +import AccountContainer from '@/pageComponents/account/AccountContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination'; import { getTeamMembers } from '@/web/support/user/team/api'; +import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; +import MultipleSelect, { + useMultipleSelect +} from '@fastgpt/web/components/common/MySelect/MultipleSelect'; +import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; +import MySelect from '@fastgpt/web/components/common/MySelect'; +import { useRouter } from 'next/router'; +import dynamic from 'next/dynamic'; + +import UsageTableList from '@/pageComponents/account/usage/UsageTable'; +import { UnitType } from '@/pageComponents/account/usage/type'; +import { useSystem } from '@fastgpt/web/hooks/useSystem'; +const UsageDashboard = dynamic(() => import('@/pageComponents/account/usage/Dashboard')); -const UsageDetail = dynamic(() => import('./UsageDetail')); +export enum UsageTabEnum { + detail = 'detail', + dashboard = 'dashboard' +} const UsageTable = () => { const { t } = useTranslation(); - const { Loading } = useLoading(); + const { userInfo } = useUserStore(); + const { isPc } = useSystem(); + const router = useRouter(); + const { usageTab = UsageTabEnum.detail } = router.query as { usageTab: `${UsageTabEnum}` }; + + const [unit, setUnit] = useState('day'); const [dateRange, setDateRange] = useState({ from: addDays(new Date(), -7), to: new Date() }); - const [usageSource, setUsageSource] = useState(''); - const { isPc } = useSystem(); - const { userInfo } = useUserStore(); - const [usageDetail, setUsageDetail] = useState(); - const sourceList = useMemo( - () => - [ - { label: t('account_usage:all'), value: '' }, - ...Object.entries(UsageSourceMap).map(([key, value]) => ({ - label: t(value.label as any), - value: key - })) - ] as { - label: never; - value: UsageSourceEnum | ''; - }[], - [t] - ); - - const [selectTmbId, setSelectTmbId] = useState(userInfo?.team?.tmbId); - const { data: members, ScrollData } = useScrollPagination(getTeamMembers, {}); + const { data: members, ScrollData, total: memberTotal } = useScrollPagination(getTeamMembers, {}); + const { + value: selectTmbIds, + setValue: setSelectTmbIds, + isSelectAll: isSelectAllTmb, + setIsSelectAll: setIsSelectAllTmb + } = useMultipleSelect([], true); const tmbList = useMemo( () => members.map((item) => ({ label: ( - - - {item.memberName} - + + + {item.memberName} + ), value: item.tmbId })), @@ -80,121 +66,195 @@ const UsageTable = () => { ); const { - data: usages, - isLoading, - Pagination, - getData - } = usePagination(getUserUsages, { - pageSize: isPc ? 20 : 10, - params: { - dateStart: dateRange.from || new Date(), - dateEnd: addDays(dateRange.to || new Date(), 1), - source: usageSource as UsageSourceEnum, - teamMemberId: selectTmbId ?? '' - }, - defaultRequest: false - }); + value: usageSources, + setValue: setUsageSources, + isSelectAll: isSelectAllSource, + setIsSelectAll: setIsSelectAllSource + } = useMultipleSelect(Object.values(UsageSourceEnum), true); + const sourceList = useMemo( + () => + Object.entries(UsageSourceMap).map(([key, value]) => ({ + label: t(value.label as any), + value: key as UsageSourceEnum + })), + [t] + ); - useEffect(() => { - getData(1); - }, [usageSource, selectTmbId]); + const [projectName, setProjectName] = useState(''); + const [inputValue, setInputValue] = useState(''); - return ( - - - - {tmbList.length > 1 && userInfo?.team?.permission.hasManagePer && ( - - - {t('account_usage:member')} - - ( + { + router.replace({ + query: { + ...router.query, + usageTab: e + } + }); + }} + /> + ), + [router, t, usageTab] + ); + + const Selectors = useMemo( + () => ( + + + + {t('common:user.Time')} + + + {/* {usageTab === UsageTabEnum.dashboard && ( + + bg={'myGray.50'} + minH={'32px'} + height={'32px'} + fontSize={'mini'} + ml={1} + list={[ + { label: t('account_usage:every_day'), value: 'day' }, + { label: t('account_usage:every_month'), value: 'month' } + ]} + value={unit} + onchange={setUnit} + /> + )} */} + + {userInfo?.team?.permission.hasManagePer && ( + + + {t('account_usage:member')} + + + list={tmbList} - value={selectTmbId} - onchange={setSelectTmbId} + value={selectTmbIds} + onSelect={(val) => { + setSelectTmbIds(val as string[]); + }} + itemWrap={false} + height={'32px'} + bg={'myGray.50'} + w={'160px'} + ScrollData={ScrollData} + isSelectAll={isSelectAllTmb} + setIsSelectAll={setIsSelectAllTmb} /> - - )} - - - getData(1)} - /> - + + )} + + + {t('account_usage:source')} + + + + list={sourceList} + value={usageSources} + onSelect={setUsageSources} + isSelectAll={isSelectAllSource} + setIsSelectAll={setIsSelectAllSource} + itemWrap={false} + height={'32px'} + bg={'myGray.50'} + w={'160px'} + /> + - - - - - {/* */} - - - - - - - - - {usages.map((item) => ( - - {/* */} - - - - - - - ))} - -
{t('account_usage:user.team.Member Name')}{t('account_usage:user_type')} - - list={sourceList} - value={usageSource} - size={'sm'} - onchange={(e) => { - setUsageSource(e); - }} - w={'130px'} - > - {t('account_usage:project_name')}{t('account_usage:total_points')}
{item.memberName}{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')}{t(UsageSourceMap[item.source]?.label as any) || '-'}{t(item.appName as any) || '-'}{formatNumber(item.totalPoints) || 0} - -
- {!isLoading && usages.length === 0 && ( - - )} -
+ {/* {usageTab === UsageTabEnum.detail && ( + + + {t('common:user.Application Name')} + + setInputValue(e.target.value)} + /> + + )} */} +
+ ), + [ + t, + dateRange, + usageTab, + unit, + userInfo?.team?.permission.hasManagePer, + tmbList, + selectTmbIds, + ScrollData, + isSelectAllTmb, + setIsSelectAllTmb, + sourceList, + usageSources, + setUsageSources, + isSelectAllSource, + setIsSelectAllSource, + setSelectTmbIds + ] + ); + + useEffect(() => { + const timer = setTimeout(() => { + setProjectName(inputValue); + }, 300); + + return () => clearTimeout(timer); + }, [inputValue]); - - {!!usageDetail && ( - setUsageDetail(undefined)} /> + const filterParams = useMemo( + () => ({ + dateRange, + selectTmbIds, + projectName, + isSelectAllTmb, + usageSources, + isSelectAllSource, + unit + }), + [dateRange, isSelectAllSource, unit, isSelectAllTmb, projectName, selectTmbIds, usageSources] + ); + + return ( + + + {usageTab === UsageTabEnum.detail && ( + )} -
+ {usageTab === UsageTabEnum.dashboard && ( + + )} +
); }; diff --git a/projects/app/src/pages/api/admin/initv4820.ts b/projects/app/src/pages/api/admin/initv4820.ts new file mode 100644 index 000000000000..c7d8b6dac1b3 --- /dev/null +++ b/projects/app/src/pages/api/admin/initv4820.ts @@ -0,0 +1,77 @@ +import { readConfigData } from '@/service/common/system'; +import { NextAPI } from '@/service/middleware/entry'; +import { + getFastGPTConfigFromDB, + updateFastGPTConfigBuffer +} from '@fastgpt/service/common/system/config/controller'; +import { authCert } from '@fastgpt/service/support/permission/auth/common'; +import { NextApiRequest, NextApiResponse } from 'next'; +import json5 from 'json5'; +import { FastGPTConfigFileType } from '@fastgpt/global/common/system/types'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; +import { loadSystemModels } from '@fastgpt/service/core/ai/config/utils'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; + +/* + 简单版迁移:直接升级到最新镜像,会去除 MongoDatasetData 里的索引。直接执行这个脚本。 + 无缝迁移: + 1. 移动 User 表中的 avatar 字段到 TeamMember 表中。 +*/ +async function handler(req: NextApiRequest, res: NextApiResponse) { + await authCert({ req, authRoot: true }); + + // load config + const [{ config: dbConfig }, fileConfig] = await Promise.all([ + getFastGPTConfigFromDB(), + readConfigData('config.json') + ]); + const fileRes = json5.parse(fileConfig) as FastGPTConfigFileType; + + const llmModels = dbConfig.llmModels || fileRes.llmModels || []; + const vectorModels = dbConfig.vectorModels || fileRes.vectorModels || []; + const reRankModels = dbConfig.reRankModels || fileRes.reRankModels || []; + const audioSpeechModels = dbConfig.audioSpeechModels || fileRes.audioSpeechModels || []; + const whisperModel = dbConfig.whisperModel || fileRes.whisperModel; + + const list = [ + ...llmModels.map((item) => ({ + ...item, + type: ModelTypeEnum.llm + })), + ...vectorModels.map((item) => ({ + ...item, + type: ModelTypeEnum.embedding + })), + ...reRankModels.map((item) => ({ + ...item, + type: ModelTypeEnum.rerank + })), + ...audioSpeechModels.map((item) => ({ + ...item, + type: ModelTypeEnum.tts + })), + { + ...whisperModel, + type: ModelTypeEnum.stt + } + ]; + + for await (const item of list) { + try { + await MongoSystemModel.updateOne( + { model: item.model }, + { $set: { model: item.model, metadata: { ...item, isActive: true } } }, + { upsert: true } + ); + } catch (error) { + console.log(error); + } + } + + await loadSystemModels(true); + await updateFastGPTConfigBuffer(); + + return { success: true }; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/common/system/getInitData.ts b/projects/app/src/pages/api/common/system/getInitData.ts index 85d6413c11e3..4ce77b3a8891 100644 --- a/projects/app/src/pages/api/common/system/getInitData.ts +++ b/projects/app/src/pages/api/common/system/getInitData.ts @@ -1,10 +1,29 @@ import type { NextApiResponse } from 'next'; import { ApiRequestProps } from '@fastgpt/service/type/next'; import { NextAPI } from '@/service/middleware/entry'; +import { InitDateResponse } from '@/global/common/api/systemRes'; +import { SystemModelItemType } from '@fastgpt/service/core/ai/type'; -async function handler(req: ApiRequestProps<{}, { bufferId?: string }>, res: NextApiResponse) { +async function handler( + req: ApiRequestProps<{}, { bufferId?: string }>, + res: NextApiResponse +): Promise { const { bufferId } = req.query; + const activeModelList = global.systemActiveModelList.map((model) => ({ + ...model, + customCQPrompt: undefined, + customExtractPrompt: undefined, + defaultSystemChatPrompt: undefined, + fieldMap: undefined, + defaultConfig: undefined, + weight: undefined, + dbConfig: undefined, + queryConfig: undefined, + requestUrl: undefined, + requestAuth: undefined + })) as SystemModelItemType[]; + // If bufferId is the same as the current bufferId, return directly if (bufferId && global.systemInitBufferId && global.systemInitBufferId === bufferId) { return { @@ -17,22 +36,9 @@ async function handler(req: ApiRequestProps<{}, { bufferId?: string }>, res: Nex bufferId: global.systemInitBufferId, feConfigs: global.feConfigs, subPlans: global.subPlans, - llmModels: global.llmModels.map((model) => ({ - ...model, - customCQPrompt: '', - customExtractPrompt: '', - defaultSystemChatPrompt: '' - })), - vectorModels: global.vectorModels, - reRankModels: - global.reRankModels?.map((item) => ({ - ...item, - requestUrl: '', - requestAuth: '' - })) || [], - whisperModel: global.whisperModel, - audioSpeechModels: global.audioSpeechModels, - systemVersion: global.systemVersion || '0.0.0' + systemVersion: global.systemVersion || '0.0.0', + activeModelList, + defaultModels: global.systemDefaultModel }; } diff --git a/projects/app/src/pages/api/common/tracks/push.ts b/projects/app/src/pages/api/common/tracks/push.ts index 8298c2f1fdb1..b64d8c0036f8 100644 --- a/projects/app/src/pages/api/common/tracks/push.ts +++ b/projects/app/src/pages/api/common/tracks/push.ts @@ -4,7 +4,7 @@ import { addLog } from '@fastgpt/service/common/system/log'; import { TrackEnum } from '@fastgpt/global/common/middle/tracks/constants'; import { TrackModel } from '@fastgpt/service/common/middle/tracks/schema'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; -import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; +import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; export type pushQuery = {}; @@ -38,7 +38,7 @@ async function handler( return TrackModel.create(data); } -export default NextAPI(useReqFrequencyLimit(1, 5), handler); +export default NextAPI(useIPFrequencyLimit({ id: 'push-tracks', seconds: 1, limit: 5 }), handler); export const config = { api: { diff --git a/projects/app/src/pages/api/core/ai/agent/createQuestionGuide.ts b/projects/app/src/pages/api/core/ai/agent/createQuestionGuide.ts index a16b32931948..625b990098dc 100644 --- a/projects/app/src/pages/api/core/ai/agent/createQuestionGuide.ts +++ b/projects/app/src/pages/api/core/ai/agent/createQuestionGuide.ts @@ -16,6 +16,7 @@ import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSc import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant'; import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; +import { getDefaultLLMModel } from '@fastgpt/service/core/ai/model'; async function handler( req: ApiRequestProps< @@ -35,7 +36,7 @@ async function handler( authApiKey: true }); - const qgModel = global.llmModels[0]; + const qgModel = getDefaultLLMModel(); const { result, inputTokens, outputTokens } = await createQuestionGuide({ messages, @@ -47,6 +48,7 @@ async function handler( }); pushQuestionGuideUsage({ + model: qgModel.model, inputTokens, outputTokens, teamId, diff --git a/projects/app/src/pages/api/core/ai/agent/v2/createQuestionGuide.ts b/projects/app/src/pages/api/core/ai/agent/v2/createQuestionGuide.ts index b2ca7bb8d13d..241369eae60c 100644 --- a/projects/app/src/pages/api/core/ai/agent/v2/createQuestionGuide.ts +++ b/projects/app/src/pages/api/core/ai/agent/v2/createQuestionGuide.ts @@ -9,6 +9,7 @@ import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { getChatItems } from '@fastgpt/service/core/chat/controller'; import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controller'; +import { getDefaultLLMModel } from '@fastgpt/service/core/ai/model'; export type CreateQuestionGuideParams = OutLinkChatAuthProps & { appId: string; @@ -50,7 +51,7 @@ async function handler(req: ApiRequestProps, res: Nex }); const messages = chats2GPTMessages({ messages: histories, reserveId: false }); - const qgModel = questionGuide?.model || global.llmModels[0].model; + const qgModel = questionGuide?.model || getDefaultLLMModel().model; const { result, inputTokens, outputTokens } = await createQuestionGuide({ messages, @@ -59,6 +60,7 @@ async function handler(req: ApiRequestProps, res: Nex }); pushQuestionGuideUsage({ + model: qgModel, inputTokens, outputTokens, teamId, diff --git a/projects/app/src/pages/api/core/ai/model/delete.ts b/projects/app/src/pages/api/core/ai/model/delete.ts new file mode 100644 index 000000000000..4f0c344dbb6a --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/delete.ts @@ -0,0 +1,42 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { findModelFromAlldata } from '@fastgpt/service/core/ai/model'; +import { updateFastGPTConfigBuffer } from '@fastgpt/service/common/system/config/controller'; +import { loadSystemModels, updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils'; + +export type deleteQuery = { + model: string; +}; + +export type deleteBody = {}; + +export type deleteResponse = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const { model } = req.query; + + const modelData = findModelFromAlldata(model); + + if (!modelData) { + return Promise.reject('Model not found'); + } + + if (!modelData.isCustom) { + return Promise.reject('System model cannot be deleted'); + } + + await MongoSystemModel.deleteOne({ model }); + + await updatedReloadSystemModel(); + + return {}; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/detail.ts b/projects/app/src/pages/api/core/ai/model/detail.ts new file mode 100644 index 000000000000..bbc261303369 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/detail.ts @@ -0,0 +1,29 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { SystemModelItemType } from '@fastgpt/service/core/ai/type'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { findModelFromAlldata } from '@fastgpt/service/core/ai/model'; + +export type detailQuery = { + model: string; +}; + +export type detailBody = {}; + +export type detailResponse = SystemModelItemType; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const { model } = req.query; + const modelItem = findModelFromAlldata(model); + if (!modelItem) { + return Promise.reject('Model not found'); + } + return modelItem; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/getConfigJson.ts b/projects/app/src/pages/api/core/ai/model/getConfigJson.ts new file mode 100644 index 000000000000..411b744aa91d --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/getConfigJson.ts @@ -0,0 +1,29 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; + +export type getConfigJsonQuery = {}; + +export type getConfigJsonBody = {}; + +export type getConfigJsonResponse = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + const data = await MongoSystemModel.find({}).lean(); + + return JSON.stringify( + data.map((item) => ({ + model: item.model, + metadata: item.metadata + })), + null, + 2 + ); +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/getDefaultConfig.ts b/projects/app/src/pages/api/core/ai/model/getDefaultConfig.ts new file mode 100644 index 000000000000..5d24830afd22 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/getDefaultConfig.ts @@ -0,0 +1,22 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { getSystemModelConfig } from '@fastgpt/service/core/ai/config/utils'; +import { SystemModelItemType } from '@fastgpt/service/core/ai/type'; + +export type getDefaultQuery = { model: string }; + +export type getDefaultBody = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const model = req.query.model; + + return getSystemModelConfig(model); +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/list.ts b/projects/app/src/pages/api/core/ai/model/list.ts new file mode 100644 index 000000000000..e19622be9698 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/list.ts @@ -0,0 +1,57 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { ModelProviderIdType } from '@fastgpt/global/core/ai/provider'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; + +export type listQuery = {}; + +export type listBody = {}; + +export type listResponse = { + type: `${ModelTypeEnum}`; + name: string; + avatar: string | undefined; + provider: ModelProviderIdType; + model: string; + charsPointsPrice?: number; + inputPrice?: number; + outputPrice?: number; + + isActive: boolean; + isCustom: boolean; + + // Tag + contextToken?: number; + vision?: boolean; + toolChoice?: boolean; +}[]; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + // Read db + return global.systemModelList.map((model) => ({ + type: model.type, + provider: model.provider, + model: model.model, + name: model.name, + avatar: model.avatar, + charsPointsPrice: model.charsPointsPrice, + inputPrice: model.inputPrice, + outputPrice: model.outputPrice, + isActive: model.isActive ?? false, + isCustom: model.isCustom ?? false, + + // Tag + contextToken: + 'maxContext' in model ? model.maxContext : 'maxToken' in model ? model.maxToken : undefined, + vision: 'vision' in model ? model.vision : undefined, + toolChoice: 'toolChoice' in model ? model.toolChoice : undefined + })); +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/test.ts b/projects/app/src/pages/api/core/ai/model/test.ts new file mode 100644 index 000000000000..3900dcd2c664 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/test.ts @@ -0,0 +1,127 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { findModelFromAlldata, getReRankModel } from '@fastgpt/service/core/ai/model'; +import { + EmbeddingModelItemType, + LLMModelItemType, + ReRankModelItemType, + STTModelType, + TTSModelType +} from '@fastgpt/global/core/ai/model.d'; +import { getAIApi } from '@fastgpt/service/core/ai/config'; +import { addLog } from '@fastgpt/service/common/system/log'; +import { getVectorsByText } from '@fastgpt/service/core/ai/embedding'; +import { reRankRecall } from '@fastgpt/service/core/ai/rerank'; +import { aiTranscriptions } from '@fastgpt/service/core/ai/audio/transcriptions'; +import { isProduction } from '@fastgpt/global/common/system/constants'; +import * as fs from 'fs'; + +export type testQuery = { model: string }; + +export type testBody = {}; + +export type testResponse = any; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const { model } = req.query; + const modelData = findModelFromAlldata(model); + + if (!modelData) return Promise.reject('Model not found'); + + if (modelData.type === 'llm') { + return testLLMModel(modelData); + } + if (modelData.type === 'embedding') { + return testEmbeddingModel(modelData); + } + if (modelData.type === 'tts') { + return testTTSModel(modelData); + } + if (modelData.type === 'stt') { + return testSTTModel(modelData); + } + if (modelData.type === 'rerank') { + return testReRankModel(modelData); + } + + return Promise.reject('Model type not supported'); +} + +export default NextAPI(handler); + +const testLLMModel = async (model: LLMModelItemType) => { + const ai = getAIApi({}); + const response = await ai.chat.completions.create( + { + model: model.model, + messages: [{ role: 'user', content: 'hi' }], + stream: false, + max_tokens: 10 + }, + { + ...(model.requestUrl ? { path: model.requestUrl } : {}), + headers: { + ...(model.requestAuth ? { Authorization: `Bearer ${model.requestAuth}` } : {}) + } + } + ); + + const responseText = response.choices?.[0]?.message?.content; + + if (!responseText) { + return Promise.reject('Model response empty'); + } + + addLog.info(`Model test response: ${responseText}`); +}; + +const testEmbeddingModel = async (model: EmbeddingModelItemType) => { + return getVectorsByText({ + input: 'Hi', + model + }); +}; + +const testTTSModel = async (model: TTSModelType) => { + const ai = getAIApi(); + await ai.audio.speech.create( + { + model: model.model, + voice: model.voices[0]?.value as any, + input: 'Hi', + response_format: 'mp3', + speed: 1 + }, + model.requestUrl && model.requestAuth + ? { + path: model.requestUrl, + headers: { + Authorization: `Bearer ${model.requestAuth}` + } + } + : {} + ); +}; + +const testSTTModel = async (model: STTModelType) => { + const path = isProduction ? '/app/data/test.mp3' : 'data/test.mp3'; + const { text } = await aiTranscriptions({ + model: model.model, + fileStream: fs.createReadStream(path) + }); + addLog.info(`STT result: ${text}`); +}; + +const testReRankModel = async (model: ReRankModelItemType) => { + await reRankRecall({ + model, + query: 'Hi', + documents: [{ id: '1', text: 'Hi' }] + }); +}; diff --git a/projects/app/src/pages/api/core/ai/model/update.ts b/projects/app/src/pages/api/core/ai/model/update.ts new file mode 100644 index 000000000000..2ccd60403a79 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/update.ts @@ -0,0 +1,64 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; +import { findModelFromAlldata } from '@fastgpt/service/core/ai/model'; +import { updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils'; + +export type updateQuery = {}; + +export type updateBody = { + model: string; + metadata?: Record; +}; + +export type updateResponse = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + let { model, metadata } = req.body; + if (!model) return Promise.reject(new Error('model is required')); + model = model.trim(); + + const dbModel = await MongoSystemModel.findOne({ model }).lean(); + const modelData = findModelFromAlldata(model); + + const metadataConcat: Record = { + ...modelData, // system config + ...dbModel?.metadata, // db config + ...metadata // user config + }; + delete metadataConcat.avatar; + delete metadataConcat.isCustom; + + // 强制赋值 model,避免脏的 metadata 覆盖真实 model + metadataConcat.model = model; + metadataConcat.name = metadataConcat?.name?.trim(); + // Delete null value + Object.keys(metadataConcat).forEach((key) => { + if (metadataConcat[key] === null || metadataConcat[key] === undefined) { + delete metadataConcat[key]; + } + }); + + await MongoSystemModel.updateOne( + { model }, + { + model, + metadata: metadataConcat + }, + { + upsert: true + } + ); + + await updatedReloadSystemModel(); + + return {}; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/updateDefault.ts b/projects/app/src/pages/api/core/ai/model/updateDefault.ts new file mode 100644 index 000000000000..3c9c856894d7 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/updateDefault.ts @@ -0,0 +1,75 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; +import { loadSystemModels, updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils'; +import { updateFastGPTConfigBuffer } from '@fastgpt/service/common/system/config/controller'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; + +export type updateDefaultQuery = {}; + +export type updateDefaultBody = { + [ModelTypeEnum.llm]?: string; + [ModelTypeEnum.embedding]?: string; + [ModelTypeEnum.tts]?: string; + [ModelTypeEnum.stt]?: string; + [ModelTypeEnum.rerank]?: string; +}; + +export type updateDefaultResponse = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const { llm, embedding, tts, stt, rerank } = req.body; + + await mongoSessionRun(async (session) => { + await MongoSystemModel.updateMany({}, { $unset: { 'metadata.isDefault': 1 } }, { session }); + + if (llm) { + await MongoSystemModel.updateOne( + { model: llm }, + { $set: { 'metadata.isDefault': true } }, + { session } + ); + } + if (embedding) { + await MongoSystemModel.updateOne( + { model: embedding }, + { $set: { 'metadata.isDefault': true } }, + { session } + ); + } + if (tts) { + await MongoSystemModel.updateOne( + { model: tts }, + { $set: { 'metadata.isDefault': true } }, + { session } + ); + } + if (stt) { + await MongoSystemModel.updateOne( + { model: stt }, + { $set: { 'metadata.isDefault': true } }, + { session } + ); + } + if (rerank) { + await MongoSystemModel.updateOne( + { model: rerank }, + { $set: { 'metadata.isDefault': true } }, + { session } + ); + } + }); + + await updatedReloadSystemModel(); + + return {}; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/ai/model/updateWithJson.ts b/projects/app/src/pages/api/core/ai/model/updateWithJson.ts new file mode 100644 index 000000000000..d15c060c4142 --- /dev/null +++ b/projects/app/src/pages/api/core/ai/model/updateWithJson.ts @@ -0,0 +1,62 @@ +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; +import { NextAPI } from '@/service/middleware/entry'; +import { SystemModelSchemaType } from '@fastgpt/service/core/ai/type'; +import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; +import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; +import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema'; +import { updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils'; + +export type updateWithJsonQuery = {}; + +export type updateWithJsonBody = { + config: string; +}; + +export type updateWithJsonResponse = {}; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + await authSystemAdmin({ req }); + + const { config } = req.body; + const data = JSON.parse(config) as SystemModelSchemaType[]; + + // Check + for (const item of data) { + if (!item.model || !item.metadata || typeof item.metadata !== 'object') { + return Promise.reject('Invalid model or metadata'); + } + if (!item.metadata.type) { + return Promise.reject(`${item.model} metadata.type is required`); + } + if (!item.metadata.model) { + return Promise.reject(`${item.model} metadata.model is required`); + } + if (!item.metadata.provider) { + return Promise.reject(`${item.model} metadata.provider is required`); + } + item.metadata.model = item.model.trim(); + if (!item.metadata.name) { + item.metadata.name = item.model; + } + } + + await mongoSessionRun(async (session) => { + await MongoSystemModel.deleteMany({}, { session }); + for await (const item of data) { + await MongoSystemModel.updateOne( + { model: item.model }, + { $set: { model: item.model, metadata: item.metadata } }, + { upsert: true, session } + ); + } + }); + + await updatedReloadSystemModel(); + + return {}; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/chat/item/getSpeech.ts b/projects/app/src/pages/api/core/chat/item/getSpeech.ts index fbea617b4693..facfcd7a3733 100644 --- a/projects/app/src/pages/api/core/chat/item/getSpeech.ts +++ b/projects/app/src/pages/api/core/chat/item/getSpeech.ts @@ -6,7 +6,7 @@ import { text2Speech } from '@fastgpt/service/core/ai/audio/speech'; import { pushAudioSpeechUsage } from '@/service/support/wallet/usage/push'; import { authChatCrud } from '@/service/support/permission/auth/chat'; import { authType2UsageSource } from '@/service/support/wallet/usage/utils'; -import { getAudioSpeechModel } from '@fastgpt/service/core/ai/model'; +import { getTTSModel } from '@fastgpt/service/core/ai/model'; import { MongoTTSBuffer } from '@fastgpt/service/common/buffer/tts/schema'; import { ApiRequestProps } from '@fastgpt/service/type/next'; @@ -31,17 +31,19 @@ async function handler(req: ApiRequestProps, res: NextApiRes ...req.body }); - const ttsModel = getAudioSpeechModel(ttsConfig.model); + const ttsModel = getTTSModel(ttsConfig.model); const voiceData = ttsModel.voices?.find((item) => item.value === ttsConfig.voice); if (!voiceData) { throw new Error('voice not found'); } + const bufferId = `${ttsModel.model}-${ttsConfig.voice}`; + /* get audio from buffer */ const ttsBuffer = await MongoTTSBuffer.findOne( { - bufferId: voiceData.bufferId, + bufferId, text: JSON.stringify({ text: input, speed: ttsConfig.speed }) }, 'buffer' @@ -70,11 +72,21 @@ async function handler(req: ApiRequestProps, res: NextApiRes }); /* create buffer */ - await MongoTTSBuffer.create({ - bufferId: voiceData.bufferId, - text: JSON.stringify({ text: input, speed: ttsConfig.speed }), - buffer - }); + await MongoTTSBuffer.create( + { + bufferId, + text: JSON.stringify({ text: input, speed: ttsConfig.speed }), + buffer + }, + ttsModel.requestUrl && ttsModel.requestAuth + ? { + path: ttsModel.requestUrl, + headers: { + Authorization: `Bearer ${ttsModel.requestAuth}` + } + } + : {} + ); } catch (error) {} }, onError: (err) => { diff --git a/projects/app/src/pages/api/core/dataset/allDataset.ts b/projects/app/src/pages/api/core/dataset/allDataset.ts index f963c62aebc1..c1d93f02d910 100644 --- a/projects/app/src/pages/api/core/dataset/allDataset.ts +++ b/projects/app/src/pages/api/core/dataset/allDataset.ts @@ -1,6 +1,6 @@ import type { NextApiRequest } from 'next'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import type { DatasetSimpleItemType } from '@fastgpt/global/core/dataset/type.d'; import { NextAPI } from '@/service/middleware/entry'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; @@ -31,7 +31,7 @@ async function handler(req: NextApiRequest): Promise { _id: item._id, avatar: item.avatar, name: item.name, - vectorModel: getVectorModel(item.vectorModel) + vectorModel: getEmbeddingModel(item.vectorModel) })); } diff --git a/projects/app/src/pages/api/core/dataset/create.ts b/projects/app/src/pages/api/core/dataset/create.ts index aaf41bf294e5..1bf40c2c3ccf 100644 --- a/projects/app/src/pages/api/core/dataset/create.ts +++ b/projects/app/src/pages/api/core/dataset/create.ts @@ -2,7 +2,12 @@ import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import type { CreateDatasetParams } from '@/global/core/dataset/api.d'; import { authUserPer } from '@fastgpt/service/support/permission/user/auth'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; -import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model'; +import { + getLLMModel, + getEmbeddingModel, + getDatasetModel, + getDefaultEmbeddingModel +} from '@fastgpt/service/core/ai/model'; import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { NextAPI } from '@/service/middleware/entry'; @@ -27,7 +32,7 @@ async function handler( intro, type = DatasetTypeEnum.dataset, avatar, - vectorModel = global.vectorModels[0].model, + vectorModel = getDefaultEmbeddingModel().model, agentModel = getDatasetModel().model, apiServer, feishuServer, @@ -56,7 +61,7 @@ async function handler( ]); // check model valid - const vectorModelStore = getVectorModel(vectorModel); + const vectorModelStore = getEmbeddingModel(vectorModel); const agentModelStore = getLLMModel(agentModel); if (!vectorModelStore || !agentModelStore) { return Promise.reject(DatasetErrEnum.invalidVectorModelOrQAModel); diff --git a/projects/app/src/pages/api/core/dataset/data/getQuoteData.ts b/projects/app/src/pages/api/core/dataset/data/getQuoteData.ts new file mode 100644 index 000000000000..d99642979618 --- /dev/null +++ b/projects/app/src/pages/api/core/dataset/data/getQuoteData.ts @@ -0,0 +1,34 @@ +import type { NextApiRequest } from 'next'; +import { NextAPI } from '@/service/middleware/entry'; +import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; +import { authDatasetData } from '@fastgpt/service/support/permission/dataset/auth'; +import { CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type'; + +export type GetQuoteDataResponse = { + collection: CollectionWithDatasetType; + q: string; + a: string; +}; + +async function handler(req: NextApiRequest): Promise { + const { id: dataId } = req.query as { + id: string; + }; + + // 凭证校验 + const { datasetData, collection } = await authDatasetData({ + req, + authToken: true, + authApiKey: true, + dataId, + per: ReadPermissionVal + }); + + return { + collection, + q: datasetData.q, + a: datasetData.a + }; +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/dataset/data/insertData.ts b/projects/app/src/pages/api/core/dataset/data/insertData.ts index 397bedb6f1af..e99e51626bf0 100644 --- a/projects/app/src/pages/api/core/dataset/data/insertData.ts +++ b/projects/app/src/pages/api/core/dataset/data/insertData.ts @@ -4,7 +4,7 @@ */ import type { NextApiRequest } from 'next'; import { countPromptTokens } from '@fastgpt/service/common/string/tiktoken/index'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { hasSameValue } from '@/service/core/dataset/data/utils'; import { insertData2Dataset } from '@/service/core/dataset/data/controller'; import { authDatasetCollection } from '@fastgpt/service/support/permission/dataset/auth'; @@ -59,7 +59,7 @@ async function handler(req: NextApiRequest) { // token check const token = await countPromptTokens(formatQ + formatA, ''); - const vectorModelData = getVectorModel(vectorModel); + const vectorModelData = getEmbeddingModel(vectorModel); if (token > vectorModelData.maxToken) { return Promise.reject('Q Over Tokens'); diff --git a/projects/app/src/pages/api/core/dataset/detail.ts b/projects/app/src/pages/api/core/dataset/detail.ts index 6f4957b69bf4..6f96d7404460 100644 --- a/projects/app/src/pages/api/core/dataset/detail.ts +++ b/projects/app/src/pages/api/core/dataset/detail.ts @@ -1,4 +1,4 @@ -import { getLLMModel, getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getLLMModel, getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { authDataset } from '@fastgpt/service/support/permission/dataset/auth'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { NextAPI } from '@/service/middleware/entry'; @@ -50,7 +50,7 @@ async function handler(req: ApiRequestProps): Promise { } : undefined, permission, - vectorModel: getVectorModel(dataset.vectorModel), + vectorModel: getEmbeddingModel(dataset.vectorModel), agentModel: getLLMModel(dataset.agentModel) }; } diff --git a/projects/app/src/pages/api/core/dataset/list.ts b/projects/app/src/pages/api/core/dataset/list.ts index ad9ffca5a4b0..f5a61459c95f 100644 --- a/projects/app/src/pages/api/core/dataset/list.ts +++ b/projects/app/src/pages/api/core/dataset/list.ts @@ -18,7 +18,7 @@ import { getGroupsByTmbId } from '@fastgpt/service/support/permission/memberGrou import { concatPer } from '@fastgpt/service/support/permission/controller'; import { getOrgIdSetWithParentByTmbId } from '@fastgpt/service/support/permission/org/controllers'; import { addSourceMember } from '@fastgpt/service/support/user/utils'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; export type GetDatasetListBody = { parentId: ParentIdType; @@ -172,7 +172,7 @@ async function handler(req: ApiRequestProps) { name: dataset.name, intro: dataset.intro, type: dataset.type, - vectorModel: getVectorModel(dataset.vectorModel), + vectorModel: getEmbeddingModel(dataset.vectorModel), inheritPermission: dataset.inheritPermission, tmbId: dataset.tmbId, updateTime: dataset.updateTime, diff --git a/projects/app/src/pages/api/core/dataset/searchTest.ts b/projects/app/src/pages/api/core/dataset/searchTest.ts index dff352f78390..d09666de0f3d 100644 --- a/projects/app/src/pages/api/core/dataset/searchTest.ts +++ b/projects/app/src/pages/api/core/dataset/searchTest.ts @@ -14,7 +14,7 @@ import { import { NextAPI } from '@/service/middleware/entry'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; -import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; +import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; async function handler(req: NextApiRequest) { const { @@ -100,4 +100,4 @@ async function handler(req: NextApiRequest) { }; } -export default NextAPI(useReqFrequencyLimit(1, 15), handler); +export default NextAPI(useIPFrequencyLimit({ id: 'search-test', seconds: 1, limit: 15 }), handler); diff --git a/projects/app/src/pages/api/core/dataset/training/rebuildEmbedding.ts b/projects/app/src/pages/api/core/dataset/training/rebuildEmbedding.ts index 9936beb24437..1ea9535957bb 100644 --- a/projects/app/src/pages/api/core/dataset/training/rebuildEmbedding.ts +++ b/projects/app/src/pages/api/core/dataset/training/rebuildEmbedding.ts @@ -6,7 +6,7 @@ import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema'; import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema'; import { createTrainingUsage } from '@fastgpt/service/support/wallet/usage/controller'; import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; -import { getLLMModel, getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getLLMModel, getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constants'; import { ApiRequestProps } from '@fastgpt/service/type/next'; import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant'; @@ -49,7 +49,7 @@ async function handler(req: ApiRequestProps): Promise(`support/outLink/dingtalk/${token}`, req.body, { - headers: req.headers as any + headers: { + timestamp: (req.headers.timestamp as string) ?? '', + sign: (req.headers.sign as string) ?? '' + } }); return result; diff --git a/projects/app/src/pages/api/support/user/account/loginByPassword.ts b/projects/app/src/pages/api/support/user/account/loginByPassword.ts index 6da09119b4cd..8c37ce0d2d74 100644 --- a/projects/app/src/pages/api/support/user/account/loginByPassword.ts +++ b/projects/app/src/pages/api/support/user/account/loginByPassword.ts @@ -5,7 +5,7 @@ import { getUserDetail } from '@fastgpt/service/support/user/controller'; import type { PostLoginProps } from '@fastgpt/global/support/user/api.d'; import { UserStatusEnum } from '@fastgpt/global/support/user/constant'; import { NextAPI } from '@/service/middleware/entry'; -import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; +import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { UserErrEnum } from '@fastgpt/global/common/error/code/user'; @@ -70,4 +70,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { }; } -export default NextAPI(useReqFrequencyLimit(120, 10, true), handler); +export default NextAPI( + useIPFrequencyLimit({ id: 'login-by-password', seconds: 120, limit: 10, force: true }), + handler +); diff --git a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts index 0d0dd7e100d1..41a2d76050de 100644 --- a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts +++ b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts @@ -4,14 +4,16 @@ import { getTeamPlanStatus } from '@fastgpt/service/support/wallet/sub/utils'; import { NextAPI } from '@/service/middleware/entry'; async function handler(req: NextApiRequest, res: NextApiResponse) { - const { teamId } = await authCert({ - req, - authToken: true - }); + try { + const { teamId } = await authCert({ + req, + authToken: true + }); - return getTeamPlanStatus({ - teamId - }); + return getTeamPlanStatus({ + teamId + }); + } catch (error) {} } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/support/wallet/usage/createTrainingUsage.ts b/projects/app/src/pages/api/support/wallet/usage/createTrainingUsage.ts index 1477ac37052d..3b96351a37ca 100644 --- a/projects/app/src/pages/api/support/wallet/usage/createTrainingUsage.ts +++ b/projects/app/src/pages/api/support/wallet/usage/createTrainingUsage.ts @@ -1,7 +1,7 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; import { CreateTrainingUsageProps } from '@fastgpt/global/support/wallet/usage/api.d'; -import { getLLMModel, getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getLLMModel, getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { createTrainingUsage } from '@fastgpt/service/support/wallet/usage/controller'; import { authDataset } from '@fastgpt/service/support/permission/dataset/auth'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; @@ -23,7 +23,7 @@ async function handler(req: NextApiRequest) { tmbId, appName: name, billSource: UsageSourceEnum.training, - vectorModel: getVectorModel(dataset.vectorModel).name, + vectorModel: getEmbeddingModel(dataset.vectorModel).name, agentModel: getLLMModel(dataset.agentModel).name }); diff --git a/projects/app/src/pages/api/v1/audio/transcriptions.ts b/projects/app/src/pages/api/v1/audio/transcriptions.ts index ac51e36e0b13..5f858159533b 100644 --- a/projects/app/src/pages/api/v1/audio/transcriptions.ts +++ b/projects/app/src/pages/api/v1/audio/transcriptions.ts @@ -8,7 +8,8 @@ import { authChatCrud } from '@/service/support/permission/auth/chat'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { NextAPI } from '@/service/middleware/entry'; import { aiTranscriptions } from '@fastgpt/service/core/ai/audio/transcriptions'; -import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; +import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit'; +import { getDefaultSTTModel } from '@fastgpt/service/core/ai/model'; const upload = getUploadModel({ maxSize: 5 @@ -36,7 +37,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { filePaths = [file.path]; - if (!global.whisperModel) { + if (!getDefaultSTTModel()) { throw new Error('whisper model not found'); } @@ -65,7 +66,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { // } const result = await aiTranscriptions({ - model: global.whisperModel.model, + model: getDefaultSTTModel().model, fileStream: fs.createReadStream(file.path) }); @@ -89,7 +90,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { removeFilesByPaths(filePaths); } -export default NextAPI(useReqFrequencyLimit(1, 1), handler); +export default NextAPI( + useIPFrequencyLimit({ id: 'transcriptions', seconds: 1, limit: 1 }), + handler +); export const config = { api: { diff --git a/projects/app/src/pages/api/v1/embeddings.ts b/projects/app/src/pages/api/v1/embeddings.ts index 4b8cb16f57ab..86a3365be621 100644 --- a/projects/app/src/pages/api/v1/embeddings.ts +++ b/projects/app/src/pages/api/v1/embeddings.ts @@ -4,7 +4,7 @@ import { pushGenerateVectorUsage } from '@/service/support/wallet/usage/push'; import { getVectorsByText } from '@fastgpt/service/core/ai/embedding'; import { updateApiKeyUsage } from '@fastgpt/service/support/openapi/tools'; import { getUsageSourceByAuthType } from '@fastgpt/global/support/wallet/usage/tools'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { checkTeamAIPoints } from '@fastgpt/service/support/permission/teamLimit'; import { EmbeddingTypeEnm } from '@fastgpt/global/core/ai/constants'; import { NextAPI } from '@/service/middleware/entry'; @@ -36,7 +36,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { const { tokens, vectors } = await getVectorsByText({ input: query, - model: getVectorModel(model), + model: getEmbeddingModel(model), type }); diff --git a/projects/app/src/pages/app/detail/index.tsx b/projects/app/src/pages/app/detail/index.tsx index 54da870e5f19..9fad08f51f40 100644 --- a/projects/app/src/pages/app/detail/index.tsx +++ b/projects/app/src/pages/app/detail/index.tsx @@ -5,19 +5,19 @@ import Loading from '@fastgpt/web/components/common/MyLoading'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import NextHead from '@/components/common/NextHead'; import { useContextSelector } from 'use-context-selector'; -import AppContextProvider, { AppContext } from './components/context'; +import AppContextProvider, { AppContext } from '@/pageComponents/app/detail/context'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; -const SimpleEdit = dynamic(() => import('./components/SimpleApp'), { +const SimpleEdit = dynamic(() => import('@/pageComponents/app/detail/SimpleApp'), { ssr: false, loading: () => }); -const Workflow = dynamic(() => import('./components/Workflow'), { +const Workflow = dynamic(() => import('@/pageComponents/app/detail/Workflow'), { ssr: false, loading: () => }); -const Plugin = dynamic(() => import('./components/Plugin'), { +const Plugin = dynamic(() => import('@/pageComponents/app/detail/Plugin'), { ssr: false, loading: () => }); diff --git a/projects/app/src/pages/app/list/index.tsx b/projects/app/src/pages/app/list/index.tsx index 118674d884e2..86d7da1ee18b 100644 --- a/projects/app/src/pages/app/list/index.tsx +++ b/projects/app/src/pages/app/list/index.tsx @@ -11,7 +11,7 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { postCreateAppFolder } from '@/web/core/app/api/app'; import type { EditFolderFormType } from '@fastgpt/web/components/common/MyModal/EditFolderModal'; import { useContextSelector } from 'use-context-selector'; -import AppListContextProvider, { AppListContext } from './components/context'; +import AppListContextProvider, { AppListContext } from '@/pageComponents/app/list/context'; import FolderPath from '@/components/common/folder/Path'; import { useRouter } from 'next/router'; import FolderSlideCard from '@/components/common/folder/SlideCard'; @@ -22,22 +22,22 @@ import { getCollaboratorList, postUpdateAppCollaborators } from '@/web/core/app/api/collaborator'; -import type { CreateAppType } from './components/CreateModal'; +import type { CreateAppType } from '@/pageComponents/app/list/CreateModal'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import MyBox from '@fastgpt/web/components/common/MyBox'; import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import MyIcon from '@fastgpt/web/components/common/Icon'; -import TemplateMarketModal from './components/TemplateMarketModal'; +import TemplateMarketModal from '@/pageComponents/app/list/TemplateMarketModal'; import MyImage from '@fastgpt/web/components/common/Image/MyImage'; -import JsonImportModal from './components/JsonImportModal'; +import JsonImportModal from '@/pageComponents/app/list/JsonImportModal'; -const CreateModal = dynamic(() => import('./components/CreateModal')); +const CreateModal = dynamic(() => import('@/pageComponents/app/list/CreateModal')); const EditFolderModal = dynamic( () => import('@fastgpt/web/components/common/MyModal/EditFolderModal') ); -const HttpEditModal = dynamic(() => import('./components/HttpPluginEditModal')); -const List = dynamic(() => import('./components/List')); +const HttpEditModal = dynamic(() => import('@/pageComponents/app/list/HttpPluginEditModal')); +const List = dynamic(() => import('@/pageComponents/app/list/List')); const MyApps = () => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/chat/index.module.scss b/projects/app/src/pages/chat/index.module.scss deleted file mode 100644 index aea66fef6a7a..000000000000 --- a/projects/app/src/pages/chat/index.module.scss +++ /dev/null @@ -1,18 +0,0 @@ -.newChat { - .modelListContainer { - height: 0; - overflow: hidden; - } - .modelList { - border-radius: 6px; - } - &:hover { - .modelListContainer { - height: 60vh; - } - .modelList { - box-shadow: 0 0 5px rgba($color: #000000, $alpha: 0.05); - border: 1px solid #dee0e2; - } - } -} diff --git a/projects/app/src/pages/chat/index.tsx b/projects/app/src/pages/chat/index.tsx index e574d0ff0dab..f9339b1d27de 100644 --- a/projects/app/src/pages/chat/index.tsx +++ b/projects/app/src/pages/chat/index.tsx @@ -11,9 +11,9 @@ import { useTranslation } from 'next-i18next'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; import PageContainer from '@/components/PageContainer'; import SideBar from '@/components/SideBar'; -import ChatHistorySlider from './components/ChatHistorySlider'; -import SliderApps from './components/SliderApps'; -import ChatHeader from './components/ChatHeader'; +import ChatHistorySlider from '@/pageComponents/chat/ChatHistorySlider'; +import SliderApps from '@/pageComponents/chat/SliderApps'; +import ChatHeader from '@/pageComponents/chat/ChatHeader'; import { useUserStore } from '@/web/support/user/useUserStore'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils'; @@ -37,7 +37,7 @@ import ChatRecordContextProvider, { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext'; -const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox')); +const CustomPluginRunBox = dynamic(() => import('@/pageComponents/chat/CustomPluginRunBox')); const Chat = ({ myApps }: { myApps: AppListItemType[] }) => { const router = useRouter(); diff --git a/projects/app/src/pages/chat/share.tsx b/projects/app/src/pages/chat/share.tsx index 2dd85c879525..7f010f3e65d3 100644 --- a/projects/app/src/pages/chat/share.tsx +++ b/projects/app/src/pages/chat/share.tsx @@ -9,8 +9,8 @@ import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; import PageContainer from '@/components/PageContainer'; -import ChatHeader from './components/ChatHeader'; -import ChatHistorySlider from './components/ChatHistorySlider'; +import ChatHeader from '@/pageComponents/chat/ChatHeader'; +import ChatHistorySlider from '@/pageComponents/chat/ChatHistorySlider'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import { getInitOutLinkChatInfo } from '@/web/core/chat/api'; @@ -38,7 +38,7 @@ import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants'; import { useI18nLng } from '@fastgpt/web/hooks/useI18n'; import { AppSchema } from '@fastgpt/global/core/app/type'; -const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox')); +const CustomPluginRunBox = dynamic(() => import('@/pageComponents/chat/CustomPluginRunBox')); type Props = { appId: string; diff --git a/projects/app/src/pages/chat/team.tsx b/projects/app/src/pages/chat/team.tsx index db0c5af31b1b..cc0b9409791c 100644 --- a/projects/app/src/pages/chat/team.tsx +++ b/projects/app/src/pages/chat/team.tsx @@ -6,15 +6,15 @@ import { Box, Flex, Drawer, DrawerOverlay, DrawerContent, useTheme } from '@chak import SideBar from '@/components/SideBar'; import PageContainer from '@/components/PageContainer'; import { getMyTokensApps } from '@/web/core/chat/api'; -import ChatHistorySlider from './components/ChatHistorySlider'; -import ChatHeader from './components/ChatHeader'; +import ChatHistorySlider from '@/pageComponents/chat/ChatHistorySlider'; +import ChatHeader from '@/pageComponents/chat/ChatHeader'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; import { streamFetch } from '@/web/common/api/fetch'; import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils'; -import SliderApps from './components/SliderApps'; +import SliderApps from '@/pageComponents/chat/SliderApps'; import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext'; @@ -33,7 +33,7 @@ import ChatRecordContextProvider, { import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { useMount } from 'ahooks'; import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants'; -const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox')); +const CustomPluginRunBox = dynamic(() => import('@/pageComponents/chat/CustomPluginRunBox')); type Props = { appId: string; chatId: string; teamId: string; teamToken: string }; diff --git a/projects/app/src/pages/dataset/detail/index.tsx b/projects/app/src/pages/dataset/detail/index.tsx index 809ac15dd306..50bf043a780f 100644 --- a/projects/app/src/pages/dataset/detail/index.tsx +++ b/projects/app/src/pages/dataset/detail/index.tsx @@ -7,24 +7,26 @@ import dynamic from 'next/dynamic'; import PageContainer from '@/components/PageContainer'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; -import MetaDataCard from './components/MetaDataCard'; -import NavBar from './components/NavBar'; +import MetaDataCard from '@/pageComponents/dataset/detail/MetaDataCard'; +import NavBar from '@/pageComponents/dataset/detail/NavBar'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { DatasetPageContext, DatasetPageContextProvider } from '@/web/core/dataset/context/datasetPageContext'; -import CollectionPageContextProvider from './components/CollectionCard/Context'; +import CollectionPageContextProvider from '@/pageComponents/dataset/detail/CollectionCard/Context'; import { useContextSelector } from 'use-context-selector'; import NextHead from '@/components/common/NextHead'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; -const CollectionCard = dynamic(() => import('./components/CollectionCard/index')); -const DataCard = dynamic(() => import('./components/DataCard')); -const Test = dynamic(() => import('./components/Test')); -const Info = dynamic(() => import('./components/Info/index')); -const Import = dynamic(() => import('./components/Import')); +const CollectionCard = dynamic( + () => import('@/pageComponents/dataset/detail/CollectionCard/index') +); +const DataCard = dynamic(() => import('@/pageComponents/dataset/detail/DataCard')); +const Test = dynamic(() => import('@/pageComponents/dataset/detail/Test')); +const Info = dynamic(() => import('@/pageComponents/dataset/detail/Info/index')); +const Import = dynamic(() => import('@/pageComponents/dataset/detail/Import')); export enum TabEnum { dataCard = 'dataCard', diff --git a/projects/app/src/pages/dataset/list/index.tsx b/projects/app/src/pages/dataset/list/index.tsx index a1f96c350fbc..f50cd52ba99c 100644 --- a/projects/app/src/pages/dataset/list/index.tsx +++ b/projects/app/src/pages/dataset/list/index.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import ParentPaths from '@/components/common/folder/Path'; -import List from './component/List'; +import List from '@/pageComponents/dataset/list/List'; import { DatasetsContext } from './context'; import DatasetContextProvider from './context'; import { useContextSelector } from 'use-context-selector'; @@ -24,7 +24,7 @@ import { getCollaboratorList } from '@/web/core/dataset/api/collaborator'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; -import { CreateDatasetType } from './component/CreateModal'; +import { CreateDatasetType } from '@/pageComponents/dataset/list/CreateModal'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { useToast } from '@fastgpt/web/hooks/useToast'; import MyBox from '@fastgpt/web/components/common/MyBox'; @@ -34,7 +34,7 @@ const EditFolderModal = dynamic( () => import('@fastgpt/web/components/common/MyModal/EditFolderModal') ); -const CreateModal = dynamic(() => import('./component/CreateModal')); +const CreateModal = dynamic(() => import('@/pageComponents/dataset/list/CreateModal')); const Dataset = () => { const { isPc } = useSystem(); diff --git a/projects/app/src/pages/login/index.tsx b/projects/app/src/pages/login/index.tsx index fd12521db56a..44cd6c73c88a 100644 --- a/projects/app/src/pages/login/index.tsx +++ b/projects/app/src/pages/login/index.tsx @@ -28,11 +28,11 @@ import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { GET } from '@/web/common/api/request'; import { getDocPath } from '@/web/common/system/doc'; import { getWebReqUrl } from '@fastgpt/web/common/system/utils'; -import LoginForm from './components/LoginForm/LoginForm'; +import LoginForm from '@/pageComponents/login/LoginForm/LoginForm'; -const RegisterForm = dynamic(() => import('./components/RegisterForm')); -const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm')); -const WechatForm = dynamic(() => import('./components/LoginForm/WechatForm')); +const RegisterForm = dynamic(() => import('@/pageComponents/login/RegisterForm')); +const ForgetPasswordForm = dynamic(() => import('@/pageComponents/login/ForgetPasswordForm')); +const WechatForm = dynamic(() => import('@/pageComponents/login/LoginForm/WechatForm')); const CommunityModal = dynamic(() => import('@/components/CommunityModal')); const ipDetectURL = 'https://qifu-api.baidubce.com/ip/local/geo/v1/district'; diff --git a/projects/app/src/pages/price/index.tsx b/projects/app/src/pages/price/index.tsx index 33d6fd987469..53f9965b561e 100644 --- a/projects/app/src/pages/price/index.tsx +++ b/projects/app/src/pages/price/index.tsx @@ -3,16 +3,16 @@ import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { Box, Flex, HStack, VStack } from '@chakra-ui/react'; import { useUserStore } from '@/web/support/user/useUserStore'; import { getTeamPlanStatus } from '@/web/support/user/team/api'; -import { useQuery } from '@tanstack/react-query'; -import StandardPlan from './components/Standard'; -import ExtraPlan from './components/ExtraPlan'; -import PointsCard from './components/Points'; -import FAQ from './components/FAQ'; +import StandardPlan from '@/pageComponents/price/Standard'; +import ExtraPlan from '@/pageComponents/price/ExtraPlan'; +import PointsCard from '@/pageComponents/price/Points'; +import FAQ from '@/pageComponents/price/FAQ'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useRouter } from 'next/router'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; const PriceBox = () => { const { userInfo } = useUserStore(); @@ -20,8 +20,9 @@ const PriceBox = () => { const { feConfigs } = useSystemStore(); const router = useRouter(); - const { data: teamSubPlan } = useQuery(['getTeamPlanStatus'], getTeamPlanStatus, { - enabled: !!userInfo + const { data: teamSubPlan } = useRequest2(getTeamPlanStatus, { + manual: false, + refreshDeps: [userInfo] }); const onPaySuccess = () => { diff --git a/projects/app/src/pages/toolkit/index.tsx b/projects/app/src/pages/toolkit/index.tsx index 3b15815f770a..9dcea82a3b97 100644 --- a/projects/app/src/pages/toolkit/index.tsx +++ b/projects/app/src/pages/toolkit/index.tsx @@ -4,7 +4,7 @@ import { Box, Flex, Grid, useDisclosure } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useMemo, useState } from 'react'; -import PluginCard from './components/PluginCard'; +import PluginCard from '@/pageComponents/toolkit/PluginCard'; import { i18nT } from '@fastgpt/web/i18n/utils'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; diff --git a/projects/app/src/service/common/system/index.ts b/projects/app/src/service/common/system/index.ts index 2583dc5ac396..83337c470a1c 100644 --- a/projects/app/src/service/common/system/index.ts +++ b/projects/app/src/service/common/system/index.ts @@ -1,17 +1,16 @@ import { initHttpAgent } from '@fastgpt/service/common/middle/httpAgent'; -import fs, { existsSync, readdirSync } from 'fs'; +import fs, { existsSync } from 'fs'; import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d'; import type { FastGPTConfigFileType } from '@fastgpt/global/common/system/types/index.d'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; import { getFastGPTConfigFromDB } from '@fastgpt/service/common/system/config/controller'; import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; import { isProduction } from '@fastgpt/global/common/system/constants'; import { initFastGPTConfig } from '@fastgpt/service/common/system/tools'; import json5 from 'json5'; -import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; import { defaultGroup, defaultTemplateTypes } from '@fastgpt/web/core/workflow/constants'; import { MongoPluginGroups } from '@fastgpt/service/core/app/plugin/pluginGroupSchema'; import { MongoTemplateTypes } from '@fastgpt/service/core/app/templates/templateTypeSchema'; +import { loadSystemModels } from '@fastgpt/service/core/ai/config/utils'; export const readConfigData = async (name: string) => { const splitName = name.split('.'); @@ -47,13 +46,7 @@ export function initGlobalVariables() { /* Init system data(Need to connected db). It only needs to run once */ export async function getInitConfig() { - return Promise.all([ - initSystemConfig(), - getSystemVersion(), - - // abandon - getSystemPlugin() - ]); + return Promise.all([initSystemConfig(), getSystemVersion(), loadSystemModels()]); } const defaultFeConfigs: FastGPTFeConfigsType = { @@ -78,7 +71,7 @@ const defaultFeConfigs: FastGPTFeConfigsType = { export async function initSystemConfig() { // load config - const [{ config: dbConfig, configId }, fileConfig] = await Promise.all([ + const [{ config: dbConfig }, fileConfig] = await Promise.all([ getFastGPTConfigFromDB(), readConfigData('config.json') ]); @@ -96,27 +89,16 @@ export async function initSystemConfig() { ...fileRes.systemEnv, ...(dbConfig.systemEnv || {}) }, - subPlans: dbConfig.subPlans || fileRes.subPlans, - llmModels: dbConfig.llmModels || fileRes.llmModels || [], - vectorModels: dbConfig.vectorModels || fileRes.vectorModels || [], - reRankModels: dbConfig.reRankModels || fileRes.reRankModels || [], - audioSpeechModels: dbConfig.audioSpeechModels || fileRes.audioSpeechModels || [], - whisperModel: dbConfig.whisperModel || fileRes.whisperModel + subPlans: dbConfig.subPlans || fileRes.subPlans }; // set config - global.systemInitBufferId = configId; initFastGPTConfig(config); console.log({ feConfigs: global.feConfigs, systemEnv: global.systemEnv, - subPlans: global.subPlans, - llmModels: global.llmModels, - vectorModels: global.vectorModels, - reRankModels: global.reRankModels, - audioSpeechModels: global.audioSpeechModels, - whisperModel: global.whisperModel + subPlans: global.subPlans }); } @@ -138,34 +120,6 @@ async function getSystemVersion() { } } -async function getSystemPlugin() { - if (global.communityPlugins && global.communityPlugins.length > 0) return; - - const basePath = - process.env.NODE_ENV === 'development' ? 'data/pluginTemplates' : '/app/data/pluginTemplates'; - // read data/pluginTemplates directory, get all json file - const files = readdirSync(basePath); - // filter json file - const filterFiles = files.filter((item) => item.endsWith('.json')); - - // read json file - const fileTemplates = await Promise.all( - filterFiles.map>(async (filename) => { - const content = await fs.promises.readFile(`${basePath}/${filename}`, 'utf-8'); - return { - ...json5.parse(content), - originCost: 0, - currentCost: 0, - id: `${PluginSourceEnum.community}-${filename.replace('.json', '')}` - }; - }) - ); - - fileTemplates.sort((a, b) => (b.weight || 0) - (a.weight || 0)); - - global.communityPlugins = fileTemplates; -} - export async function initSystemPluginGroups() { try { const { groupOrder, ...restDefaultGroup } = defaultGroup; diff --git a/projects/app/src/service/common/system/volumnMongoWatch.ts b/projects/app/src/service/common/system/volumnMongoWatch.ts index b466d787b004..0d29a2ef6371 100644 --- a/projects/app/src/service/common/system/volumnMongoWatch.ts +++ b/projects/app/src/service/common/system/volumnMongoWatch.ts @@ -6,12 +6,14 @@ import { MongoSystemPlugin } from '@fastgpt/service/core/app/plugin/systemPlugin import { debounce } from 'lodash'; import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema'; import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register'; +import { watchSystemModelUpdate } from '@fastgpt/service/core/ai/config/utils'; export const startMongoWatch = async () => { reloadConfigWatch(); refetchSystemPlugins(); createDatasetTrainingMongoWatch(); refetchAppTemplates(); + watchSystemModelUpdate(); }; const reloadConfigWatch = () => { diff --git a/projects/app/src/service/core/app/workflow.ts b/projects/app/src/service/core/app/workflow.ts index 1940605240df..686b52552cfa 100644 --- a/projects/app/src/service/core/app/workflow.ts +++ b/projects/app/src/service/core/app/workflow.ts @@ -1,13 +1,15 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node.d'; +import { getLLMModel } from '@fastgpt/service/core/ai/model'; export const getChatModelNameListByModules = (nodes: StoreNodeItemType[]): string[] => { const modelList = nodes .map((item) => { const model = item.inputs.find((input) => input.key === NodeInputKeyEnum.aiModel)?.value; - return global.llmModels.find((item) => item.model === model)?.name || ''; + return model ? getLLMModel(model)?.name : ''; }) .filter(Boolean); - + console.log(JSON.stringify(nodes, null, 2), '---='); + console.log(modelList, '---='); return Array.from(new Set(modelList)); }; diff --git a/projects/app/src/service/core/dataset/data/controller.ts b/projects/app/src/service/core/dataset/data/controller.ts index d07753da6b0c..aec06b2e71e6 100644 --- a/projects/app/src/service/core/dataset/data/controller.ts +++ b/projects/app/src/service/core/dataset/data/controller.ts @@ -9,7 +9,7 @@ import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils'; import { jiebaSplit } from '@fastgpt/service/common/string/jieba'; import { deleteDatasetDataVector } from '@fastgpt/service/common/vectorStore/controller'; import { DatasetDataItemType } from '@fastgpt/global/core/dataset/type'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { ClientSession } from '@fastgpt/service/common/mongo'; import { MongoDatasetDataText } from '@fastgpt/service/core/dataset/data/dataTextSchema'; @@ -71,7 +71,7 @@ export async function insertData2Dataset({ indexes.map((item) => insertDatasetDataVector({ query: item.text, - model: getVectorModel(model), + model: getEmbeddingModel(model), teamId, datasetId, collectionId @@ -219,7 +219,7 @@ export async function updateData2Dataset({ if (item.type === 'create' || item.type === 'update') { const result = await insertDatasetDataVector({ query: item.index.text, - model: getVectorModel(model), + model: getEmbeddingModel(model), teamId: mongoData.teamId, datasetId: mongoData.datasetId, collectionId: mongoData.collectionId diff --git a/projects/app/src/service/events/generateQA.ts b/projects/app/src/service/events/generateQA.ts index 0824e317e974..fc213f83f815 100644 --- a/projects/app/src/service/events/generateQA.ts +++ b/projects/app/src/service/events/generateQA.ts @@ -18,7 +18,7 @@ import { } from '@fastgpt/service/common/string/tiktoken/index'; import { pushDataListToTrainingQueueByCollectionId } from '@fastgpt/service/core/dataset/training/controller'; import { loadRequestMessages } from '@fastgpt/service/core/chat/utils'; -import { llmCompletionsBodyFormat } from '@fastgpt/service/core/ai/utils'; +import { llmCompletionsBodyFormat, llmStreamResponseToText } from '@fastgpt/service/core/ai/utils'; const reduceQueue = () => { global.qaQueueLen = global.qaQueueLen > 0 ? global.qaQueueLen - 1 : 0; @@ -44,7 +44,7 @@ export async function generateQA(): Promise { { mode: TrainingModeEnum.qa, retryCount: { $gte: 0 }, - lockTime: { $lte: addMinutes(new Date(), -6) } + lockTime: { $lte: addMinutes(new Date(), -10) } }, { lockTime: new Date(), @@ -120,12 +120,12 @@ ${replaceVariable(Prompt_AgentQA.fixedText, { text })}`; model: modelData.model, temperature: 0.3, messages: await loadRequestMessages({ messages, useVision: false }), - stream: false + stream: true }, modelData ) }); - const answer = chatResponse.choices?.[0].message?.content || ''; + const answer = await llmStreamResponseToText(chatResponse); const qaArr = formatSplitText(answer, text); // 格式化后的QA对 diff --git a/projects/app/src/service/events/generateVector.ts b/projects/app/src/service/events/generateVector.ts index a84d80479abd..92ea0451c82f 100644 --- a/projects/app/src/service/events/generateVector.ts +++ b/projects/app/src/service/events/generateVector.ts @@ -11,7 +11,7 @@ import { deleteDatasetDataVector, insertDatasetDataVector } from '@fastgpt/service/common/vectorStore/controller'; -import { getVectorModel } from '@fastgpt/service/core/ai/model'; +import { getEmbeddingModel } from '@fastgpt/service/core/ai/model'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { DatasetTrainingSchemaType } from '@fastgpt/global/core/dataset/type'; import { Document } from '@fastgpt/service/common/mongo'; @@ -40,7 +40,7 @@ export async function generateVector(): Promise { { mode: TrainingModeEnum.chunk, retryCount: { $gte: 0 }, - lockTime: { $lte: addMinutes(new Date(), -6) } + lockTime: { $lte: addMinutes(new Date(), -3) } }, { lockTime: new Date(), @@ -207,7 +207,7 @@ const rebuildData = async ({ mongoData.indexes.map(async (index, i) => { const result = await insertDatasetDataVector({ query: index.text, - model: getVectorModel(trainingData.model), + model: getEmbeddingModel(trainingData.model), teamId: mongoData.teamId, datasetId: mongoData.datasetId, collectionId: mongoData.collectionId diff --git a/projects/app/src/service/support/wallet/usage/push.ts b/projects/app/src/service/support/wallet/usage/push.ts index 677c920f5086..407e5aace635 100644 --- a/projects/app/src/service/support/wallet/usage/push.ts +++ b/projects/app/src/service/support/wallet/usage/push.ts @@ -1,10 +1,11 @@ import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; -import { ModelTypeEnum } from '@fastgpt/service/core/ai/model'; import { addLog } from '@fastgpt/service/common/system/log'; import { createUsage, concatUsage } from './controller'; import { formatModelChars2Points } from '@fastgpt/service/support/wallet/usage/utils'; import { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type'; import { i18nT } from '@fastgpt/web/i18n/utils'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; +import { getDefaultTTSModel } from '@fastgpt/service/core/ai/model'; export const pushChatUsage = ({ appName, @@ -108,7 +109,7 @@ export const pushGenerateVectorUsage = ({ extensionOutputTokens?: number; }) => { const { totalPoints: totalVector, modelName: vectorModelName } = formatModelChars2Points({ - modelType: ModelTypeEnum.vector, + modelType: ModelTypeEnum.embedding, model, inputTokens }); @@ -175,21 +176,22 @@ export const pushGenerateVectorUsage = ({ }; export const pushQuestionGuideUsage = ({ + model, inputTokens, outputTokens, teamId, tmbId }: { + model: string; inputTokens: number; outputTokens: number; teamId: string; tmbId: string; }) => { - const qgModel = global.llmModels[0]; const { totalPoints, modelName } = formatModelChars2Points({ inputTokens, outputTokens, - model: qgModel.model, + model, modelType: ModelTypeEnum.llm }); @@ -229,7 +231,7 @@ export function pushAudioSpeechUsage({ const { totalPoints, modelName } = formatModelChars2Points({ model, inputTokens: charsLength, - modelType: ModelTypeEnum.audioSpeech + modelType: ModelTypeEnum.tts }); createUsage({ @@ -258,14 +260,14 @@ export function pushWhisperUsage({ tmbId: string; duration: number; }) { - const whisperModel = global.whisperModel; + const whisperModel = getDefaultTTSModel(); if (!whisperModel) return; const { totalPoints, modelName } = formatModelChars2Points({ model: whisperModel.model, inputTokens: duration, - modelType: ModelTypeEnum.whisper, + modelType: ModelTypeEnum.stt, multiple: 60 }); diff --git a/projects/app/src/types/index.d.ts b/projects/app/src/types/index.d.ts index 84dfaf634d23..6550db0ad403 100644 --- a/projects/app/src/types/index.d.ts +++ b/projects/app/src/types/index.d.ts @@ -1,10 +1,10 @@ import { - AudioSpeechModelType, + TTSModelType, ChatModelItemType, FunctionModelItemType, LLMModelItemType, ReRankModelItemType, - VectorModelItemType, + EmbeddingModelItemType, STTModelType } from '@fastgpt/global/core/ai/model.d'; import { TrackEventName } from '@/web/common/system/constants'; diff --git a/projects/app/src/web/common/api/fetch.ts b/projects/app/src/web/common/api/fetch.ts index ba82ed797532..960a049e90f0 100644 --- a/projects/app/src/web/common/api/fetch.ts +++ b/projects/app/src/web/common/api/fetch.ts @@ -186,6 +186,12 @@ export const streamFetch = ({ text: item }); } + + const reasoningText = parseJson.choices?.[0]?.delta?.reasoning_content || ''; + onMessage({ + event, + reasoningText + }); } else if (event === SseResponseEventEnum.fastAnswer) { const text = parseJson.choices?.[0]?.delta?.content || ''; pushDataToQueue({ diff --git a/projects/app/src/web/common/api/request.ts b/projects/app/src/web/common/api/request.ts index 009dd5c45066..20bbe2010fb2 100644 --- a/projects/app/src/web/common/api/request.ts +++ b/projects/app/src/web/common/api/request.ts @@ -101,6 +101,7 @@ function checkRes(data: ResponseDataType) { */ function responseError(err: any) { console.log('error->', '请求错误', err); + const data = err?.response?.data || err; if (!err) { return Promise.reject({ message: '未知错误' }); @@ -108,8 +109,12 @@ function responseError(err: any) { if (typeof err === 'string') { return Promise.reject({ message: err }); } + if (typeof data === 'string') { + return Promise.reject(data); + } + // 有报错响应 - if (err?.code in TOKEN_ERROR_CODE || err?.response?.data?.code in TOKEN_ERROR_CODE) { + if (data?.code in TOKEN_ERROR_CODE) { if (!['/chat/share', '/chat/team', '/login'].includes(window.location.pathname)) { clearToken(); window.location.replace( @@ -120,18 +125,18 @@ function responseError(err: any) { return Promise.reject({ message: i18nT('common:unauth_token') }); } if ( - err?.statusText === TeamErrEnum.aiPointsNotEnough || - err?.statusText === TeamErrEnum.datasetSizeNotEnough || - err?.statusText === TeamErrEnum.datasetAmountNotEnough || - err?.statusText === TeamErrEnum.appAmountNotEnough + data?.statusText === TeamErrEnum.aiPointsNotEnough || + data?.statusText === TeamErrEnum.datasetSizeNotEnough || + data?.statusText === TeamErrEnum.datasetAmountNotEnough || + data?.statusText === TeamErrEnum.appAmountNotEnough || + data?.statusText === TeamErrEnum.pluginAmountNotEnough || + data?.statusText === TeamErrEnum.websiteSyncNotEnough || + data?.statusText === TeamErrEnum.reRankNotEnough ) { - useSystemStore.getState().setNotSufficientModalType(err.statusText); - return Promise.reject(err); - } - if (err?.response?.data) { - return Promise.reject(err?.response?.data); + useSystemStore.getState().setNotSufficientModalType(data.statusText); + return Promise.reject(data); } - return Promise.reject(err); + return Promise.reject(data); } /* 创建请求实例 */ diff --git a/projects/app/src/web/common/system/useSystemStore.ts b/projects/app/src/web/common/system/useSystemStore.ts index 656a762d1c7d..df8f7d883815 100644 --- a/projects/app/src/web/common/system/useSystemStore.ts +++ b/projects/app/src/web/common/system/useSystemStore.ts @@ -4,17 +4,18 @@ import { immer } from 'zustand/middleware/immer'; import axios from 'axios'; import { OAuthEnum } from '@fastgpt/global/support/user/constant'; import type { - AudioSpeechModelType, + TTSModelType, LLMModelItemType, ReRankModelItemType, - VectorModelItemType, + EmbeddingModelItemType, STTModelType } from '@fastgpt/global/core/ai/model.d'; import { InitDateResponse } from '@/global/common/api/systemRes'; import { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types'; import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; -import { defaultWhisperModel } from '@fastgpt/global/core/ai/model'; +import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; +import { SystemDefaultModelType } from '@fastgpt/service/core/ai/type'; type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string }; @@ -49,12 +50,13 @@ type State = { feConfigs: FastGPTFeConfigsType; subPlans?: SubPlanType; systemVersion: string; + defaultModels: SystemDefaultModelType; llmModelList: LLMModelItemType[]; datasetModelList: LLMModelItemType[]; - vectorModelList: VectorModelItemType[]; - audioSpeechModelList: AudioSpeechModelType[]; + embeddingModelList: EmbeddingModelItemType[]; + ttsModelList: TTSModelType[]; reRankModelList: ReRankModelItemType[]; - whisperModel: STTModelType; + sttModelList: STTModelType[]; initStaticData: (e: InitDateResponse) => void; appType?: string; setAppType: (e?: string) => void; @@ -125,12 +127,13 @@ export const useSystemStore = create()( feConfigs: {}, subPlans: undefined, systemVersion: '0.0.0', + defaultModels: {}, llmModelList: [], datasetModelList: [], - vectorModelList: [], - audioSpeechModelList: [], + embeddingModelList: [], + ttsModelList: [], reRankModelList: [], - whisperModel: defaultWhisperModel, + sttModelList: [], initStaticData(res) { set((state) => { state.initDataBufferId = res.bufferId; @@ -139,12 +142,24 @@ export const useSystemStore = create()( state.subPlans = res.subPlans ?? state.subPlans; state.systemVersion = res.systemVersion ?? state.systemVersion; - state.llmModelList = res.llmModels ?? state.llmModelList; + state.llmModelList = + res.activeModelList?.filter((item) => item.type === ModelTypeEnum.llm) ?? + state.llmModelList; state.datasetModelList = state.llmModelList.filter((item) => item.datasetProcess); - state.vectorModelList = res.vectorModels ?? state.vectorModelList; - state.audioSpeechModelList = res.audioSpeechModels ?? state.audioSpeechModelList; - state.reRankModelList = res.reRankModels ?? state.reRankModelList; - state.whisperModel = res.whisperModel ?? state.whisperModel; + state.embeddingModelList = + res.activeModelList?.filter((item) => item.type === ModelTypeEnum.embedding) ?? + state.embeddingModelList; + state.ttsModelList = + res.activeModelList?.filter((item) => item.type === ModelTypeEnum.tts) ?? + state.ttsModelList; + state.reRankModelList = + res.activeModelList?.filter((item) => item.type === ModelTypeEnum.rerank) ?? + state.reRankModelList; + state.sttModelList = + res.activeModelList?.filter((item) => item.type === ModelTypeEnum.stt) ?? + state.sttModelList; + + state.defaultModels = res.defaultModels ?? state.defaultModels; }); } })), @@ -156,12 +171,13 @@ export const useSystemStore = create()( feConfigs: state.feConfigs, subPlans: state.subPlans, systemVersion: state.systemVersion, + defaultModels: state.defaultModels, llmModelList: state.llmModelList, datasetModelList: state.datasetModelList, - vectorModelList: state.vectorModelList, - audioSpeechModelList: state.audioSpeechModelList, + embeddingModelList: state.embeddingModelList, + ttsModelList: state.ttsModelList, reRankModelList: state.reRankModelList, - whisperModel: state.whisperModel + sttModelList: state.sttModelList }) } ) diff --git a/projects/app/src/web/common/system/utils.ts b/projects/app/src/web/common/system/utils.ts index 3d5ea1ef8a9c..2c3f9f156739 100644 --- a/projects/app/src/web/common/system/utils.ts +++ b/projects/app/src/web/common/system/utils.ts @@ -1,15 +1,58 @@ +import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import { useSystemStore } from './useSystemStore'; -export const downloadFetch = async ({ url, filename }: { url: string; filename: string }) => { - const a = document.createElement('a'); - a.href = url; - a.download = filename; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); +export const downloadFetch = async ({ + url, + filename, + body +}: { + url: string; + filename: string; + body?: Record; +}) => { + if (body) { + // fetch data with POST method if body exists + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + const blob = await response.blob(); + const downloadUrl = window.URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + + // clean up the blob URL + window.URL.revokeObjectURL(downloadUrl); + } else { + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + } }; export const getWebLLMModel = (model?: string) => { const list = useSystemStore.getState().llmModelList; - return list.find((item) => item.model === model || item.name === model) ?? list[0]; + const defaultModels = useSystemStore.getState().defaultModels; + + return list.find((item) => item.model === model || item.name === model) ?? defaultModels.llm!; +}; +export const getWebDefaultModel = (llmList: LLMModelItemType[] = []) => { + const list = llmList.length > 0 ? llmList : useSystemStore.getState().llmModelList; + const defaultModels = useSystemStore.getState().defaultModels; + + return defaultModels.llm && list.find((item) => item.model === defaultModels.llm?.model) + ? defaultModels.llm + : list[0]; }; diff --git a/projects/app/src/web/common/utils/voice.ts b/projects/app/src/web/common/utils/voice.ts index 9b06e2bccf55..d912dba87cec 100644 --- a/projects/app/src/web/common/utils/voice.ts +++ b/projects/app/src/web/common/utils/voice.ts @@ -69,10 +69,6 @@ export const useAudioPlay = ( if (!response.body || !response.ok) { const data = await response.json(); - toast({ - status: 'error', - title: getErrText(data, t('common:core.chat.Audio Speech Error')) - }); return Promise.reject(data); } return response.body; diff --git a/projects/app/src/web/context/useInitApp.ts b/projects/app/src/web/context/useInitApp.ts index a705e36459d8..4b32a7c88b16 100644 --- a/projects/app/src/web/context/useInitApp.ts +++ b/projects/app/src/web/context/useInitApp.ts @@ -63,7 +63,7 @@ export const useInitApp = () => { useRequest2(initFetch, { manual: false, - pollingInterval: 300000 + pollingInterval: 300000 // 5 minutes refresh }); useEffect(() => { diff --git a/projects/app/src/web/core/ai/config.ts b/projects/app/src/web/core/ai/config.ts new file mode 100644 index 000000000000..a8d330bd186a --- /dev/null +++ b/projects/app/src/web/core/ai/config.ts @@ -0,0 +1,27 @@ +import { GET, PUT, DELETE, POST } from '@/web/common/api/request'; +import type { listResponse } from '@/pages/api/core/ai/model/list'; +import type { updateBody } from '@/pages/api/core/ai/model/update'; +import type { deleteQuery } from '@/pages/api/core/ai/model/delete'; +import type { SystemModelItemType } from '@fastgpt/service/core/ai/type'; +import type { updateWithJsonBody } from '@/pages/api/core/ai/model/updateWithJson'; +import type { updateDefaultBody } from '@/pages/api/core/ai/model/updateDefault'; + +export const getSystemModelList = () => GET('/core/ai/model/list'); +export const getSystemModelDetail = (model: string) => + GET('/core/ai/model/detail', { model }); + +export const getSystemModelDefaultConfig = (model: string) => + GET('/core/ai/model/getDefaultConfig', { model }); + +export const putSystemModel = (data: updateBody) => PUT('/core/ai/model/update', data); + +export const deleteSystemModel = (data: deleteQuery) => DELETE('/core/ai/model/delete', data); + +export const getModelConfigJson = () => GET('/core/ai/model/getConfigJson'); +export const putUpdateWithJson = (data: updateWithJsonBody) => + PUT('/core/ai/model/updateWithJson', data); + +export const getTestModel = (model: String) => GET('/core/ai/model/test', { model }); + +export const putUpdateDefaultModels = (data: updateDefaultBody) => + PUT('/core/ai/model/updateDefault', data); diff --git a/projects/app/src/web/core/app/templates.ts b/projects/app/src/web/core/app/templates.ts index 1b128e11f8ea..59a05ba8dc7a 100644 --- a/projects/app/src/web/core/app/templates.ts +++ b/projects/app/src/web/core/app/templates.ts @@ -1,7 +1,7 @@ import { parseCurl } from '@fastgpt/global/common/string/http'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppSchema } from '@fastgpt/global/core/app/type'; -import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; +import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, @@ -150,7 +150,7 @@ export const emptyTemplates: Record< key: 'temperature', renderTypeList: [FlowNodeInputTypeEnum.hidden], label: '', - value: 0, + value: undefined, valueType: WorkflowIOValueTypeEnum.number, min: 0, max: 10, @@ -160,7 +160,7 @@ export const emptyTemplates: Record< key: 'maxToken', renderTypeList: [FlowNodeInputTypeEnum.hidden], label: '', - value: 2000, + value: undefined, valueType: WorkflowIOValueTypeEnum.number, min: 100, max: 4000, @@ -221,6 +221,13 @@ export const emptyTemplates: Record< debugLabel: i18nT('common:core.module.Dataset quote.label'), description: '', valueType: WorkflowIOValueTypeEnum.datasetQuote + }, + { + key: NodeInputKeyEnum.aiChatReasoning, + renderTypeList: [FlowNodeInputTypeEnum.hidden], + label: '', + valueType: WorkflowIOValueTypeEnum.boolean, + value: true } ], outputs: [ diff --git a/projects/app/src/web/core/app/utils.ts b/projects/app/src/web/core/app/utils.ts index 5a8546a58b34..4262a4c2a681 100644 --- a/projects/app/src/web/core/app/utils.ts +++ b/projects/app/src/web/core/app/utils.ts @@ -190,6 +190,13 @@ export function form2AppWorkflow( label: '', valueType: WorkflowIOValueTypeEnum.boolean, value: true + }, + { + key: NodeInputKeyEnum.aiChatReasoning, + renderTypeList: [FlowNodeInputTypeEnum.hidden], + label: '', + valueType: WorkflowIOValueTypeEnum.boolean, + value: formData.aiSettings.aiChatReasoning } ], outputs: AiChatModule.outputs diff --git a/projects/app/src/web/core/dataset/api.ts b/projects/app/src/web/core/dataset/api.ts index ac40e1a02ecd..966b3361b383 100644 --- a/projects/app/src/web/core/dataset/api.ts +++ b/projects/app/src/web/core/dataset/api.ts @@ -65,6 +65,7 @@ import type { listExistIdQuery, listExistIdResponse } from '@/pages/api/core/dataset/apiDataset/listExistId'; +import { GetQuoteDataResponse } from '@/pages/api/core/dataset/data/getQuoteData'; /* ======================== dataset ======================= */ export const getDatasets = (data: GetDatasetListBody) => @@ -203,6 +204,10 @@ export const putDatasetDataById = (data: UpdateDatasetDataProps) => export const delOneDatasetDataById = (id: string) => DELETE(`/core/dataset/data/delete`, { id }); +// Get quote data +export const getQuoteData = (id: string) => + GET(`/core/dataset/data/getQuoteData`, { id }); + /* ================ training ==================== */ export const postRebuildEmbedding = (data: rebuildEmbeddingBody) => POST(`/core/dataset/training/rebuildEmbedding`, data); diff --git a/projects/app/src/web/support/wallet/usage/api.ts b/projects/app/src/web/support/wallet/usage/api.ts index c4ce4171ac55..f979898ab96f 100644 --- a/projects/app/src/web/support/wallet/usage/api.ts +++ b/projects/app/src/web/support/wallet/usage/api.ts @@ -1,17 +1,18 @@ import { POST } from '@/web/common/api/request'; -import { CreateTrainingUsageProps } from '@fastgpt/global/support/wallet/usage/api.d'; -import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; +import { + CreateTrainingUsageProps, + GetUsageDashboardProps, + GetUsageDashboardResponseItem, + GetUsageProps +} from '@fastgpt/global/support/wallet/usage/api.d'; import type { UsageItemType } from '@fastgpt/global/support/wallet/usage/type'; import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type'; -export const getUserUsages = ( - data: PaginationProps<{ - dateStart: Date; - dateEnd: Date; - source?: UsageSourceEnum; - teamMemberId: string; - }> -) => POST>(`/proApi/support/wallet/usage/getUsage`, data); +export const getUserUsages = (data: PaginationProps) => + POST>(`/proApi/support/wallet/usage/getUsage`, data); + +export const getDashboardData = (data: GetUsageDashboardProps) => + POST(`/proApi/support/wallet/usage/getDashboardData`, data); export const postCreateTrainingUsage = (data: CreateTrainingUsageProps) => POST(`/support/wallet/usage/createTrainingUsage`, data); diff --git a/projects/app/tsconfig.json b/projects/app/tsconfig.json index 975513eb1b76..7d58a40e28bb 100644 --- a/projects/app/tsconfig.json +++ b/projects/app/tsconfig.json @@ -1,10 +1,10 @@ { - "extends":"../../tsconfig.json", + "extends": "../../tsconfig.json", "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts","../../packages/**/*.d.ts"] + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts", "../../packages/**/*.d.ts"] }