perf: ery extension and fix filter same embedding result (#3833)
* perf: ery extension and fix filter same embedding result * fix: extract node too long * perf: ui * perf: not chatId will auto save * fix: laf * fix: member load * feat: add completions unstream error response * feat: add completions unstream error response * updat emodel provider
This commit is contained in:
parent
8604cbd021
commit
6762723b10
BIN
docSite/assets/imgs/appid.png
Normal file
BIN
docSite/assets/imgs/appid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 332 KiB |
@ -7,6 +7,12 @@ toc: true
|
|||||||
weight: 852
|
weight: 852
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# 如何获取 AppId
|
||||||
|
|
||||||
|
可在应用详情的路径里获取 AppId。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
# 发起对话
|
# 发起对话
|
||||||
|
|
||||||
{{% alert icon="🤖 " context="success" %}}
|
{{% alert icon="🤖 " context="success" %}}
|
||||||
@ -102,8 +108,8 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
|||||||
{{% alert context="info" %}}
|
{{% alert context="info" %}}
|
||||||
- headers.Authorization: Bearer {{apikey}}
|
- headers.Authorization: Bearer {{apikey}}
|
||||||
- chatId: string | undefined 。
|
- chatId: string | undefined 。
|
||||||
- 为 `undefined` 时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。 不会将你的记录存储到数据库中,你也无法在记录汇总中查阅到。
|
- 为 `undefined` 时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。
|
||||||
- 为`非空字符串`时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题。请自行确保 chatId 唯一,长度小于250,通常可以是自己系统的对话框ID。
|
- 为`非空字符串`时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题,其余 message 会被忽略。请自行确保 chatId 唯一,长度小于250,通常可以是自己系统的对话框ID。
|
||||||
- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) chat模式一致。
|
- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) chat模式一致。
|
||||||
- responseChatItemId: string | undefined 。如果传入,则会将该值作为本次对话的响应消息的 ID,FastGPT 会自动将该 ID 存入数据库。请确保,在当前`chatId`下,`responseChatItemId`是唯一的。
|
- responseChatItemId: string | undefined 。如果传入,则会将该值作为本次对话的响应消息的 ID,FastGPT 会自动将该 ID 存入数据库。请确保,在当前`chatId`下,`responseChatItemId`是唯一的。
|
||||||
- detail: 是否返回中间值(模块状态,响应的完整结果等),`stream模式`下会通过`event`进行区分,`非stream模式`结果保存在`responseData`中。
|
- detail: 是否返回中间值(模块状态,响应的完整结果等),`stream模式`下会通过`event`进行区分,`非stream模式`结果保存在`responseData`中。
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: 'Api Key 使用与鉴权'
|
title: 'OpenAPI 介绍'
|
||||||
description: 'FastGPT Api Key 使用与鉴权'
|
description: 'FastGPT OpenAPI 介绍'
|
||||||
icon: 'key'
|
icon: 'key'
|
||||||
draft: false
|
draft: false
|
||||||
toc: true
|
toc: true
|
||||||
@ -27,6 +27,7 @@ FastGPT 的 API Key **有 2 类**,一类是全局通用的 key (无法直接
|
|||||||
| --------------------- | --------------------- |
|
| --------------------- | --------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
|
|
||||||
## 基本配置
|
## 基本配置
|
||||||
|
|
||||||
OpenAPI 中,所有的接口都通过 Header.Authorization 进行鉴权。
|
OpenAPI 中,所有的接口都通过 Header.Authorization 进行鉴权。
|
||||||
@ -17,19 +17,37 @@ weight: 802
|
|||||||
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.22-alpha
|
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.22-alpha
|
||||||
- Sandbox 镜像无需更新
|
- Sandbox 镜像无需更新
|
||||||
|
|
||||||
|
### 3. 运行升级脚本
|
||||||
|
|
||||||
|
仅商业版,并提供 Saas 服务的用户需要运行该升级脚本。
|
||||||
|
|
||||||
|
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成**FastGPT 域名**。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'https://{{host}}/api/admin/initv4822' \
|
||||||
|
--header 'rootkey: {{rootkey}}' \
|
||||||
|
--header 'Content-Type: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
|
会迁移联系方式到对应用户表中。
|
||||||
|
|
||||||
## 🚀 新增内容
|
## 🚀 新增内容
|
||||||
|
|
||||||
1. AI 对话节点解析 `<think></think>` 标签内容作为思考链,便于各类模型进行思考链输出。需主动开启模型输出思考。
|
1. AI 对话节点解析 `<think></think>` 标签内容作为思考链,便于各类模型进行思考链输出。需主动开启模型输出思考。
|
||||||
2. ppio 模型提供商 by @saikidev
|
2. 对话 API 优化,无论是否传递 chatId,都会保存对话日志。未传递 chatId,则随机生成一个 chatId 来进行存储。
|
||||||
|
3. ppio 模型提供商 by
|
||||||
|
|
||||||
## ⚙️ 优化
|
## ⚙️ 优化
|
||||||
|
|
||||||
1. 模型未配置时提示,减少冲突提示。
|
1. 模型未配置时提示,减少冲突提示。
|
||||||
2. 使用记录代码。
|
2. 使用记录代码。
|
||||||
|
3. 内容提取节点,字段描述过长时换行。同时修改其输出名用 key,而不是 description。
|
||||||
|
4. 团队管理交互。
|
||||||
|
5. 对话接口,非流响应,增加报错字段。
|
||||||
|
|
||||||
## 🐛 修复
|
## 🐛 修复
|
||||||
1. 思考内容未进入到输出 Tokens.
|
|
||||||
|
1. 思考内容未进入到输出 Tokens.
|
||||||
2. 思考链流输出时,有时与正文顺序偏差。
|
2. 思考链流输出时,有时与正文顺序偏差。
|
||||||
3. API 调用工作流,如果传递的图片不支持 Head 检测时,图片会被过滤。已增加该类错误检测,避免被错误过滤。
|
3. API 调用工作流,如果传递的图片不支持 Head 检测时,图片会被过滤。已增加该类错误检测,避免被错误过滤。
|
||||||
4. 模板市场部分模板错误。
|
4. 模板市场部分模板错误。
|
||||||
@ -37,4 +55,7 @@ weight: 802
|
|||||||
6. 对话日志导出,未兼容 sub path。
|
6. 对话日志导出,未兼容 sub path。
|
||||||
7. 切换团队时未刷新成员列表
|
7. 切换团队时未刷新成员列表
|
||||||
8. list 接口在联查 member 时,存在空指针可能性。
|
8. list 接口在联查 member 时,存在空指针可能性。
|
||||||
9. 工作流基础节点无法升级。
|
9. 工作流基础节点无法升级。
|
||||||
|
10. 向量检索结果未去重。
|
||||||
|
11. 用户选择节点无法正常连线。
|
||||||
|
12. 对话记录保存时,source 未正常记录。
|
||||||
@ -72,11 +72,6 @@ export const ModelProviderList: ModelProviderType[] = [
|
|||||||
name: 'Groq',
|
name: 'Groq',
|
||||||
avatar: 'model/groq'
|
avatar: 'model/groq'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'AliCloud',
|
|
||||||
name: i18nT('common:model_alicloud'),
|
|
||||||
avatar: 'model/alicloud'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'Qwen',
|
id: 'Qwen',
|
||||||
name: i18nT('common:model_qwen'),
|
name: i18nT('common:model_qwen'),
|
||||||
@ -87,6 +82,11 @@ export const ModelProviderList: ModelProviderType[] = [
|
|||||||
name: i18nT('common:model_doubao'),
|
name: i18nT('common:model_doubao'),
|
||||||
avatar: 'model/doubao'
|
avatar: 'model/doubao'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'DeepSeek',
|
||||||
|
name: 'DeepSeek',
|
||||||
|
avatar: 'model/deepseek'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'ChatGLM',
|
id: 'ChatGLM',
|
||||||
name: i18nT('common:model_chatglm'),
|
name: i18nT('common:model_chatglm'),
|
||||||
@ -97,11 +97,6 @@ export const ModelProviderList: ModelProviderType[] = [
|
|||||||
name: i18nT('common:model_ernie'),
|
name: i18nT('common:model_ernie'),
|
||||||
avatar: 'model/ernie'
|
avatar: 'model/ernie'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'DeepSeek',
|
|
||||||
name: 'DeepSeek',
|
|
||||||
avatar: 'model/deepseek'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'Moonshot',
|
id: 'Moonshot',
|
||||||
name: i18nT('common:model_moonshot'),
|
name: i18nT('common:model_moonshot'),
|
||||||
@ -163,6 +158,11 @@ export const ModelProviderList: ModelProviderType[] = [
|
|||||||
name: i18nT('common:model_moka'),
|
name: i18nT('common:model_moka'),
|
||||||
avatar: 'model/moka'
|
avatar: 'model/moka'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'AliCloud',
|
||||||
|
name: i18nT('common:model_alicloud'),
|
||||||
|
avatar: 'model/alicloud'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'Siliconflow',
|
id: 'Siliconflow',
|
||||||
name: i18nT('common:model_siliconflow'),
|
name: i18nT('common:model_siliconflow'),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { connectionMongo, getMongoModel } from '../../common/mongo';
|
import { connectionMongo, getMongoModel } from '../../common/mongo';
|
||||||
const { Schema } = connectionMongo;
|
const { Schema } = connectionMongo;
|
||||||
import { ChatSchema as ChatType } from '@fastgpt/global/core/chat/type.d';
|
import { ChatSchema as ChatType } from '@fastgpt/global/core/chat/type.d';
|
||||||
import { ChatSourceMap } from '@fastgpt/global/core/chat/constants';
|
import { ChatSourceEnum, ChatSourceMap } from '@fastgpt/global/core/chat/constants';
|
||||||
import {
|
import {
|
||||||
TeamCollectionName,
|
TeamCollectionName,
|
||||||
TeamMemberCollectionName
|
TeamMemberCollectionName
|
||||||
@ -52,11 +52,10 @@ const ChatSchema = new Schema({
|
|||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
enum: Object.values(ChatSourceEnum)
|
||||||
sourceName: {
|
|
||||||
type: String
|
|
||||||
},
|
},
|
||||||
|
sourceName: String,
|
||||||
shareId: {
|
shareId: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type.d';
|
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type.d';
|
||||||
import { MongoApp } from '../app/schema';
|
import { MongoApp } from '../app/schema';
|
||||||
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
import {
|
||||||
|
ChatItemValueTypeEnum,
|
||||||
|
ChatRoleEnum,
|
||||||
|
ChatSourceEnum
|
||||||
|
} from '@fastgpt/global/core/chat/constants';
|
||||||
import { MongoChatItem } from './chatItemSchema';
|
import { MongoChatItem } from './chatItemSchema';
|
||||||
import { MongoChat } from './chatSchema';
|
import { MongoChat } from './chatSchema';
|
||||||
import { addLog } from '../../common/system/log';
|
import { addLog } from '../../common/system/log';
|
||||||
@ -22,8 +26,8 @@ type Props = {
|
|||||||
variables?: Record<string, any>;
|
variables?: Record<string, any>;
|
||||||
isUpdateUseTime: boolean;
|
isUpdateUseTime: boolean;
|
||||||
newTitle: string;
|
newTitle: string;
|
||||||
source: string;
|
source: `${ChatSourceEnum}`;
|
||||||
sourceName: string;
|
sourceName?: string;
|
||||||
shareId?: string;
|
shareId?: string;
|
||||||
outLinkUid?: string;
|
outLinkUid?: string;
|
||||||
content: [UserChatItemType & { dataId?: string }, AIChatItemType & { dataId?: string }];
|
content: [UserChatItemType & { dataId?: string }, AIChatItemType & { dataId?: string }];
|
||||||
|
|||||||
@ -383,6 +383,7 @@ export async function searchDatasetData(
|
|||||||
).lean()
|
).lean()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const set = new Map<string, number>();
|
||||||
const formatResult = results
|
const formatResult = results
|
||||||
.map((item, index) => {
|
.map((item, index) => {
|
||||||
const collection = collections.find((col) => String(col._id) === String(item.collectionId));
|
const collection = collections.find((col) => String(col._id) === String(item.collectionId));
|
||||||
@ -398,8 +399,6 @@ export async function searchDatasetData(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const score = item?.score || 0;
|
|
||||||
|
|
||||||
const result: SearchDataResponseItemType = {
|
const result: SearchDataResponseItemType = {
|
||||||
id: String(data._id),
|
id: String(data._id),
|
||||||
updateTime: data.updateTime,
|
updateTime: data.updateTime,
|
||||||
@ -409,12 +408,24 @@ export async function searchDatasetData(
|
|||||||
datasetId: String(data.datasetId),
|
datasetId: String(data.datasetId),
|
||||||
collectionId: String(data.collectionId),
|
collectionId: String(data.collectionId),
|
||||||
...getCollectionSourceData(collection),
|
...getCollectionSourceData(collection),
|
||||||
score: [{ type: SearchScoreTypeEnum.embedding, value: score, index }]
|
score: [{ type: SearchScoreTypeEnum.embedding, value: item?.score || 0, index }]
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
})
|
})
|
||||||
.filter(Boolean) as SearchDataResponseItemType[];
|
.filter((item) => {
|
||||||
|
if (!item) return false;
|
||||||
|
if (set.has(item.id)) return false;
|
||||||
|
set.set(item.id, 1);
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((item, index) => {
|
||||||
|
if (!item) return;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
score: item.score.map((item) => ({ ...item, index }))
|
||||||
|
};
|
||||||
|
}) as SearchDataResponseItemType[];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
embeddingRecallResults: formatResult,
|
embeddingRecallResults: formatResult,
|
||||||
@ -717,11 +728,12 @@ export const defaultSearchDatasetData = async ({
|
|||||||
? getLLMModel(datasetSearchExtensionModel)
|
? getLLMModel(datasetSearchExtensionModel)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const { concatQueries, rewriteQuery, aiExtensionResult } = await datasetSearchQueryExtension({
|
const { concatQueries, extensionQueries, rewriteQuery, aiExtensionResult } =
|
||||||
query,
|
await datasetSearchQueryExtension({
|
||||||
extensionModel,
|
query,
|
||||||
extensionBg: datasetSearchExtensionBg
|
extensionModel,
|
||||||
});
|
extensionBg: datasetSearchExtensionBg
|
||||||
|
});
|
||||||
|
|
||||||
const result = await searchDatasetData({
|
const result = await searchDatasetData({
|
||||||
...props,
|
...props,
|
||||||
@ -736,7 +748,7 @@ export const defaultSearchDatasetData = async ({
|
|||||||
model: aiExtensionResult.model,
|
model: aiExtensionResult.model,
|
||||||
inputTokens: aiExtensionResult.inputTokens,
|
inputTokens: aiExtensionResult.inputTokens,
|
||||||
outputTokens: aiExtensionResult.outputTokens,
|
outputTokens: aiExtensionResult.outputTokens,
|
||||||
query: concatQueries.join('\n')
|
query: extensionQueries.join('\n')
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
};
|
};
|
||||||
|
|||||||
@ -72,12 +72,15 @@ Human: ${query}
|
|||||||
if (result.extensionQueries?.length === 0) return;
|
if (result.extensionQueries?.length === 0) return;
|
||||||
return result;
|
return result;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const extensionQueries = filterSamQuery(aiExtensionResult?.extensionQueries || []);
|
||||||
if (aiExtensionResult) {
|
if (aiExtensionResult) {
|
||||||
queries = filterSamQuery(queries.concat(aiExtensionResult.extensionQueries));
|
queries = filterSamQuery(queries.concat(extensionQueries));
|
||||||
rewriteQuery = queries.join('\n');
|
rewriteQuery = queries.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
extensionQueries,
|
||||||
concatQueries: queries,
|
concatQueries: queries,
|
||||||
rewriteQuery,
|
rewriteQuery,
|
||||||
aiExtensionResult
|
aiExtensionResult
|
||||||
|
|||||||
@ -1182,7 +1182,6 @@
|
|||||||
"support.wallet.usage.Audio Speech": "Voice Playback",
|
"support.wallet.usage.Audio Speech": "Voice Playback",
|
||||||
"support.wallet.usage.Bill Module": "Billing Module",
|
"support.wallet.usage.Bill Module": "Billing Module",
|
||||||
"support.wallet.usage.Duration": "Duration (seconds)",
|
"support.wallet.usage.Duration": "Duration (seconds)",
|
||||||
"support.wallet.usage.Extension result": "Question Optimization Result",
|
|
||||||
"support.wallet.usage.Module name": "Module Name",
|
"support.wallet.usage.Module name": "Module Name",
|
||||||
"support.wallet.usage.Source": "Source",
|
"support.wallet.usage.Source": "Source",
|
||||||
"support.wallet.usage.Text Length": "Text Length",
|
"support.wallet.usage.Text Length": "Text Length",
|
||||||
|
|||||||
@ -1185,7 +1185,6 @@
|
|||||||
"support.wallet.usage.Audio Speech": "语音播放",
|
"support.wallet.usage.Audio Speech": "语音播放",
|
||||||
"support.wallet.usage.Bill Module": "扣费模块",
|
"support.wallet.usage.Bill Module": "扣费模块",
|
||||||
"support.wallet.usage.Duration": "时长(秒)",
|
"support.wallet.usage.Duration": "时长(秒)",
|
||||||
"support.wallet.usage.Extension result": "问题优化结果",
|
|
||||||
"support.wallet.usage.Module name": "模块名",
|
"support.wallet.usage.Module name": "模块名",
|
||||||
"support.wallet.usage.Source": "来源",
|
"support.wallet.usage.Source": "来源",
|
||||||
"support.wallet.usage.Text Length": "文本长度",
|
"support.wallet.usage.Text Length": "文本长度",
|
||||||
|
|||||||
@ -1181,7 +1181,6 @@
|
|||||||
"support.wallet.usage.Audio Speech": "語音播放",
|
"support.wallet.usage.Audio Speech": "語音播放",
|
||||||
"support.wallet.usage.Bill Module": "計費模組",
|
"support.wallet.usage.Bill Module": "計費模組",
|
||||||
"support.wallet.usage.Duration": "時長(秒)",
|
"support.wallet.usage.Duration": "時長(秒)",
|
||||||
"support.wallet.usage.Extension result": "問題最佳化結果",
|
|
||||||
"support.wallet.usage.Module name": "模組名稱",
|
"support.wallet.usage.Module name": "模組名稱",
|
||||||
"support.wallet.usage.Source": "來源",
|
"support.wallet.usage.Source": "來源",
|
||||||
"support.wallet.usage.Text Length": "文字長度",
|
"support.wallet.usage.Text Length": "文字長度",
|
||||||
|
|||||||
@ -78,7 +78,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
|||||||
isUpdateNotification &&
|
isUpdateNotification &&
|
||||||
feConfigs?.bind_notification_method &&
|
feConfigs?.bind_notification_method &&
|
||||||
feConfigs?.bind_notification_method.length > 0 &&
|
feConfigs?.bind_notification_method.length > 0 &&
|
||||||
!userInfo?.team.notificationAccount &&
|
!userInfo?.contact &&
|
||||||
!!userInfo?.team.permission.isOwner;
|
!!userInfo?.team.permission.isOwner;
|
||||||
|
|
||||||
useMount(() => {
|
useMount(() => {
|
||||||
|
|||||||
@ -250,7 +250,7 @@ export const WholeResponseContent = ({
|
|||||||
value={`${activeModule.queryExtensionResult.inputTokens}/${activeModule.queryExtensionResult.outputTokens}`}
|
value={`${activeModule.queryExtensionResult.inputTokens}/${activeModule.queryExtensionResult.outputTokens}`}
|
||||||
/>
|
/>
|
||||||
<Row
|
<Row
|
||||||
label={t('common:support.wallet.usage.Extension result')}
|
label={t('chat:query_extension_result')}
|
||||||
value={activeModule.queryExtensionResult.query}
|
value={activeModule.queryExtensionResult.query}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@ -259,10 +259,7 @@ export const WholeResponseContent = ({
|
|||||||
label={t('common:core.chat.response.Extension model')}
|
label={t('common:core.chat.response.Extension model')}
|
||||||
value={activeModule?.extensionModel}
|
value={activeModule?.extensionModel}
|
||||||
/>
|
/>
|
||||||
<Row
|
<Row label={t('chat:query_extension_result')} value={`${activeModule?.extensionResult}`} />
|
||||||
label={t('common:support.wallet.usage.Extension result')}
|
|
||||||
value={`${activeModule?.extensionResult}`}
|
|
||||||
/>
|
|
||||||
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
||||||
<Row
|
<Row
|
||||||
label={t('common:core.chat.response.module quoteList')}
|
label={t('common:core.chat.response.module quoteList')}
|
||||||
|
|||||||
@ -130,7 +130,7 @@ const QuoteItem = ({
|
|||||||
<Box>
|
<Box>
|
||||||
{t(SearchScoreTypeMap[score.primaryScore.type]?.label as any)}
|
{t(SearchScoreTypeMap[score.primaryScore.type]?.label as any)}
|
||||||
{SearchScoreTypeMap[score.primaryScore.type]?.showScore
|
{SearchScoreTypeMap[score.primaryScore.type]?.showScore
|
||||||
? ` ${score.primaryScore.value.toFixed(4)}`
|
? ` ${score.primaryScore.value?.toFixed(4)}`
|
||||||
: ''}
|
: ''}
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -43,10 +43,10 @@ function MemberItemCard({
|
|||||||
{isChecked !== undefined && <Checkbox isChecked={isChecked} pointerEvents="none" />}
|
{isChecked !== undefined && <Checkbox isChecked={isChecked} pointerEvents="none" />}
|
||||||
<Avatar src={avatar} w="1.5rem" borderRadius={'50%'} />
|
<Avatar src={avatar} w="1.5rem" borderRadius={'50%'} />
|
||||||
|
|
||||||
<VStack w="full" gap={0}>
|
<Box w="full">
|
||||||
<Box w="full">{name}</Box>
|
<Box fontSize={'sm'}>{name}</Box>
|
||||||
<Box w="full">{orgs && orgs.length > 0 && <OrgTags orgs={orgs} />}</Box>
|
<Box lineHeight={1}>{orgs && orgs.length > 0 && <OrgTags orgs={orgs} />}</Box>
|
||||||
</VStack>
|
</Box>
|
||||||
{permission && <PermissionTags permission={permission} />}
|
{permission && <PermissionTags permission={permission} />}
|
||||||
{onDelete !== undefined && (
|
{onDelete !== undefined && (
|
||||||
<MyIcon
|
<MyIcon
|
||||||
|
|||||||
@ -126,7 +126,7 @@ function MemberModal({
|
|||||||
const [selectedMemberIdList, setSelectedMembers] = useState<string[]>([]);
|
const [selectedMemberIdList, setSelectedMembers] = useState<string[]>([]);
|
||||||
const filterMembers = useMemo(() => {
|
const filterMembers = useMemo(() => {
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
return searchedData?.members;
|
return searchedData?.members || [];
|
||||||
}
|
}
|
||||||
if (!searchText && filterClass !== 'member' && filterClass !== 'org') return [];
|
if (!searchText && filterClass !== 'member' && filterClass !== 'org') return [];
|
||||||
if (currentOrg && filterClass === 'org') {
|
if (currentOrg && filterClass === 'org') {
|
||||||
@ -320,122 +320,124 @@ function MemberModal({
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ScrollData
|
{(filterClass === 'org' || filterClass === 'member') && (
|
||||||
flexDirection={'column'}
|
<ScrollData
|
||||||
gap={1}
|
flexDirection={'column'}
|
||||||
userSelect={'none'}
|
gap={1}
|
||||||
height={'fit-content'}
|
userSelect={'none'}
|
||||||
>
|
height={'fit-content'}
|
||||||
{filterOrgs?.map((org) => {
|
>
|
||||||
const onChange = () => {
|
{filterOrgs?.map((org) => {
|
||||||
setSelectedOrgIdList((state) => {
|
const onChange = () => {
|
||||||
if (state.includes(org._id)) {
|
setSelectedOrgIdList((state) => {
|
||||||
return state.filter((v) => v !== org._id);
|
if (state.includes(org._id)) {
|
||||||
}
|
return state.filter((v) => v !== org._id);
|
||||||
return [...state, org._id];
|
}
|
||||||
});
|
return [...state, org._id];
|
||||||
};
|
});
|
||||||
const collaborator = collaboratorList?.find((v) => v.orgId === org._id);
|
};
|
||||||
return (
|
const collaborator = collaboratorList?.find((v) => v.orgId === org._id);
|
||||||
<HStack
|
return (
|
||||||
justifyContent="space-between"
|
<HStack
|
||||||
key={org._id}
|
justifyContent="space-between"
|
||||||
py="2"
|
key={org._id}
|
||||||
px="3"
|
py="2"
|
||||||
borderRadius="sm"
|
px="3"
|
||||||
alignItems="center"
|
borderRadius="sm"
|
||||||
_hover={HoverBoxStyle}
|
alignItems="center"
|
||||||
onClick={onChange}
|
_hover={HoverBoxStyle}
|
||||||
>
|
onClick={onChange}
|
||||||
<Checkbox
|
>
|
||||||
isChecked={selectedOrgIdList.includes(org._id)}
|
<Checkbox
|
||||||
pointerEvents="none"
|
isChecked={selectedOrgIdList.includes(org._id)}
|
||||||
/>
|
pointerEvents="none"
|
||||||
<MyAvatar src={org.avatar} w="1.5rem" borderRadius={'50%'} />
|
/>
|
||||||
<HStack ml="2" w="full" gap="5px">
|
<MyAvatar src={org.avatar} w="1.5rem" borderRadius={'50%'} />
|
||||||
<Text>{org.name}</Text>
|
<HStack ml="2" w="full" gap="5px">
|
||||||
|
<Text>{org.name}</Text>
|
||||||
|
{org.count && (
|
||||||
|
<>
|
||||||
|
<Tag size="sm" my="auto">
|
||||||
|
{org.count}
|
||||||
|
</Tag>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
<PermissionTags permission={collaborator?.permission.value} />
|
||||||
{org.count && (
|
{org.count && (
|
||||||
<>
|
<MyIcon
|
||||||
<Tag size="sm" my="auto">
|
name="core/chat/chevronRight"
|
||||||
{org.count}
|
w="16px"
|
||||||
</Tag>
|
p="4px"
|
||||||
</>
|
rounded={'6px'}
|
||||||
|
_hover={{
|
||||||
|
bgColor: 'myGray.200'
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
setParentPath(getOrgChildrenPath(org));
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
<PermissionTags permission={collaborator?.permission.value} />
|
);
|
||||||
{org.count && (
|
})}
|
||||||
<MyIcon
|
{filterMembers?.map((member) => {
|
||||||
name="core/chat/chevronRight"
|
const onChange = () => {
|
||||||
w="16px"
|
setSelectedMembers((state) => {
|
||||||
p="4px"
|
if (state.includes(member.tmbId)) {
|
||||||
rounded={'6px'}
|
return state.filter((v) => v !== member.tmbId);
|
||||||
_hover={{
|
}
|
||||||
bgColor: 'myGray.200'
|
return [...state, member.tmbId];
|
||||||
}}
|
});
|
||||||
onClick={(e) => {
|
};
|
||||||
setParentPath(getOrgChildrenPath(org));
|
const collaborator = collaboratorList?.find((v) => v.tmbId === member.tmbId);
|
||||||
e.stopPropagation();
|
const memberOrgs = orgs.filter((org) =>
|
||||||
}}
|
org.members.find((v) => String(v.tmbId) === String(member.tmbId))
|
||||||
/>
|
);
|
||||||
)}
|
const memberPathIds = memberOrgs.map((org) =>
|
||||||
</HStack>
|
(org.path + '/' + org.pathId).split('/').slice(0)
|
||||||
);
|
);
|
||||||
})}
|
const memberOrgNames = memberPathIds.map((pathIds) =>
|
||||||
{filterMembers?.map((member) => {
|
pathIds.map((id) => orgs.find((v) => v.pathId === id)?.name).join('/')
|
||||||
const onChange = () => {
|
);
|
||||||
setSelectedMembers((state) => {
|
return (
|
||||||
if (state.includes(member.tmbId)) {
|
<MemberItemCard
|
||||||
return state.filter((v) => v !== member.tmbId);
|
avatar={member.avatar}
|
||||||
}
|
key={member.tmbId}
|
||||||
return [...state, member.tmbId];
|
name={member.memberName}
|
||||||
});
|
permission={collaborator?.permission.value}
|
||||||
};
|
onChange={onChange}
|
||||||
const collaborator = collaboratorList?.find((v) => v.tmbId === member.tmbId);
|
isChecked={selectedMemberIdList.includes(member.tmbId)}
|
||||||
const memberOrgs = orgs.filter((org) =>
|
orgs={memberOrgNames}
|
||||||
org.members.find((v) => String(v.tmbId) === String(member.tmbId))
|
/>
|
||||||
);
|
);
|
||||||
const memberPathIds = memberOrgs.map((org) =>
|
})}
|
||||||
(org.path + '/' + org.pathId).split('/').slice(0)
|
</ScrollData>
|
||||||
);
|
)}
|
||||||
const memberOrgNames = memberPathIds.map((pathIds) =>
|
{filterGroups?.map((group) => {
|
||||||
pathIds.map((id) => orgs.find((v) => v.pathId === id)?.name).join('/')
|
const onChange = () => {
|
||||||
);
|
setSelectedGroupIdList((state) => {
|
||||||
return (
|
if (state.includes(group._id)) {
|
||||||
<MemberItemCard
|
return state.filter((v) => v !== group._id);
|
||||||
avatar={member.avatar}
|
}
|
||||||
key={member.tmbId}
|
return [...state, group._id];
|
||||||
name={member.memberName}
|
});
|
||||||
permission={collaborator?.permission.value}
|
};
|
||||||
onChange={onChange}
|
const collaborator = collaboratorList?.find((v) => v.groupId === group._id);
|
||||||
isChecked={selectedMemberIdList.includes(member.tmbId)}
|
return (
|
||||||
orgs={memberOrgNames}
|
<MemberItemCard
|
||||||
/>
|
avatar={group.avatar}
|
||||||
);
|
key={group._id}
|
||||||
})}
|
name={
|
||||||
{filterGroups?.map((group) => {
|
group.name === DefaultGroupName ? userInfo?.team.teamName ?? '' : group.name
|
||||||
const onChange = () => {
|
}
|
||||||
setSelectedGroupIdList((state) => {
|
permission={collaborator?.permission.value}
|
||||||
if (state.includes(group._id)) {
|
onChange={onChange}
|
||||||
return state.filter((v) => v !== group._id);
|
isChecked={selectedGroupIdList.includes(group._id)}
|
||||||
}
|
/>
|
||||||
return [...state, group._id];
|
);
|
||||||
});
|
})}
|
||||||
};
|
|
||||||
const collaborator = collaboratorList?.find((v) => v.groupId === group._id);
|
|
||||||
return (
|
|
||||||
<MemberItemCard
|
|
||||||
avatar={group.avatar}
|
|
||||||
key={group._id}
|
|
||||||
name={
|
|
||||||
group.name === DefaultGroupName ? userInfo?.team.teamName ?? '' : group.name
|
|
||||||
}
|
|
||||||
permission={collaborator?.permission.value}
|
|
||||||
onChange={onChange}
|
|
||||||
isChecked={selectedGroupIdList.includes(group._id)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ScrollData>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
|||||||
@ -18,12 +18,18 @@ function OrgTags({ orgs, type = 'simple' }: { orgs: string[]; type?: 'simple' |
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{type === 'simple' ? (
|
{type === 'simple' ? (
|
||||||
<Box fontSize="sm" fontWeight={400} w="full" color="myGray.500" whiteSpace={'nowrap'}>
|
<Box
|
||||||
|
className="textEllipsis"
|
||||||
|
fontSize="xs"
|
||||||
|
fontWeight={400}
|
||||||
|
w="full"
|
||||||
|
color="myGray.400"
|
||||||
|
whiteSpace={'nowrap'}
|
||||||
|
>
|
||||||
{orgs
|
{orgs
|
||||||
.map((org) => org.split('/').pop())
|
.map((org) => org.split('/').pop())
|
||||||
.join(', ')
|
.join(', ')
|
||||||
.slice(0, 30)}
|
.slice(0, 30)}
|
||||||
{orgs.length > 1 && '...'}
|
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Flex direction="row" gap="1" p="2" alignItems={'start'} wrap={'wrap'}>
|
<Flex direction="row" gap="1" p="2" alignItems={'start'} wrap={'wrap'}>
|
||||||
|
|||||||
@ -194,19 +194,7 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
|
|||||||
{t('account_team:user_team_invite_member')}
|
{t('account_team:user_team_invite_member')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{!userInfo?.team.permission.isOwner && (
|
{userInfo?.team.permission.isOwner && isSyncMember && (
|
||||||
<Button
|
|
||||||
variant={'whitePrimary'}
|
|
||||||
size="md"
|
|
||||||
borderRadius={'md'}
|
|
||||||
ml={3}
|
|
||||||
leftIcon={<MyIcon name={'support/account/loginoutLight'} w={'14px'} />}
|
|
||||||
onClick={() => openLeaveConfirm(onLeaveTeam)()}
|
|
||||||
>
|
|
||||||
{t('account_team:user_team_leave_team')}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{userInfo?.team.permission.hasManagePer && (
|
|
||||||
<Button
|
<Button
|
||||||
variant={'whitePrimary'}
|
variant={'whitePrimary'}
|
||||||
size="md"
|
size="md"
|
||||||
@ -223,6 +211,18 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
|
|||||||
{t('account_team:export_members')}
|
{t('account_team:export_members')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{!userInfo?.team.permission.isOwner && (
|
||||||
|
<Button
|
||||||
|
variant={'whitePrimary'}
|
||||||
|
size="md"
|
||||||
|
borderRadius={'md'}
|
||||||
|
ml={3}
|
||||||
|
leftIcon={<MyIcon name={'support/account/loginoutLight'} w={'14px'} />}
|
||||||
|
onClick={() => openLeaveConfirm(onLeaveTeam)()}
|
||||||
|
>
|
||||||
|
{t('account_team:user_team_leave_team')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ function PermissionManage({
|
|||||||
const groupList = collaboratorList.filter(
|
const groupList = collaboratorList.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
Object.keys(item).includes('groupId') &&
|
Object.keys(item).includes('groupId') &&
|
||||||
(!searchKey || searchResult?.groups.find((group) => group.groupId === item.groupId))
|
(!searchKey || searchResult?.groups.find((group) => group._id === item.groupId))
|
||||||
);
|
);
|
||||||
const orgList = collaboratorList.filter(
|
const orgList = collaboratorList.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
|
|||||||
@ -96,6 +96,7 @@ const ExtractFieldModal = ({
|
|||||||
<Input
|
<Input
|
||||||
bg={'myGray.50'}
|
bg={'myGray.50'}
|
||||||
placeholder="name/age/sql"
|
placeholder="name/age/sql"
|
||||||
|
maxLength={20}
|
||||||
{...register('key', { required: true })}
|
{...register('key', { required: true })}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import IOTitle from '../../components/IOTitle';
|
|||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext } from '../../../context';
|
import { WorkflowContext } from '../../../context';
|
||||||
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
|
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
|
||||||
|
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||||
|
|
||||||
const NodeExtract = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
const NodeExtract = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||||
const { inputs, outputs, nodeId } = data;
|
const { inputs, outputs, nodeId } = data;
|
||||||
@ -71,7 +72,7 @@ const NodeExtract = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<TableContainer borderRadius={'md'} overflow={'hidden'} borderWidth={'1px'} mt={2}>
|
<TableContainer borderRadius={'md'} overflow={'auto'} borderWidth={'1px'} mt={2}>
|
||||||
<Table variant={'workflow'}>
|
<Table variant={'workflow'}>
|
||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
@ -85,19 +86,23 @@ const NodeExtract = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
|||||||
{extractKeys.map((item, index) => (
|
{extractKeys.map((item, index) => (
|
||||||
<Tr key={index}>
|
<Tr key={index}>
|
||||||
<Td>
|
<Td>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'} maxW={'300px'} className={'textEllipsis'}>
|
||||||
<MyIcon name={'checkCircle'} w={'14px'} mr={1} color={'myGray.600'} />
|
<MyIcon name={'checkCircle'} w={'14px'} mr={1} color={'myGray.600'} />
|
||||||
{item.key}
|
{item.key}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>{item.desc}</Td>
|
<Td>
|
||||||
|
<Box maxW={'300px'} whiteSpace={'pre-wrap'}>
|
||||||
|
{item.desc}
|
||||||
|
</Box>
|
||||||
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
{item.required ? (
|
{item.required ? (
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'check'} w={'16px'} color={'myGray.900'} mr={2} />
|
<MyIcon name={'check'} w={'16px'} color={'myGray.900'} mr={2} />
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
''
|
'-'
|
||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
@ -197,7 +202,7 @@ const NodeExtract = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
|||||||
const newOutput: FlowNodeOutputItemType = {
|
const newOutput: FlowNodeOutputItemType = {
|
||||||
id: getNanoid(),
|
id: getNanoid(),
|
||||||
key: data.key,
|
key: data.key,
|
||||||
label: `${t('common:extraction_results')}-${data.desc}`,
|
label: `${t('common:extraction_results')}-${data.key}`,
|
||||||
valueType: data.valueType || WorkflowIOValueTypeEnum.string,
|
valueType: data.valueType || WorkflowIOValueTypeEnum.string,
|
||||||
type: FlowNodeOutputTypeEnum.static
|
type: FlowNodeOutputTypeEnum.static
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,9 @@ async function handler(req: NextApiRequest, _res: NextApiResponse) {
|
|||||||
await authCert({ req, authRoot: true });
|
await authCert({ req, authRoot: true });
|
||||||
const users = await MongoUser.find();
|
const users = await MongoUser.find();
|
||||||
const teams = await MongoTeam.find();
|
const teams = await MongoTeam.find();
|
||||||
|
|
||||||
|
console.log('Total users:', users.length);
|
||||||
|
let success = 0;
|
||||||
for await (const user of users) {
|
for await (const user of users) {
|
||||||
try {
|
try {
|
||||||
const team = teams.find((team) => String(team.ownerId) === String(user._id));
|
const team = teams.find((team) => String(team.ownerId) === String(user._id));
|
||||||
@ -18,6 +21,7 @@ async function handler(req: NextApiRequest, _res: NextApiResponse) {
|
|||||||
user.contact = team.notificationAccount;
|
user.contact = team.notificationAccount;
|
||||||
}
|
}
|
||||||
await user.save();
|
await user.save();
|
||||||
|
console.log('Success:', ++success);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,12 +6,12 @@ import { ApiRequestProps } from '@fastgpt/service/type/next';
|
|||||||
import { syncCollection } from '@fastgpt/service/core/dataset/collection/utils';
|
import { syncCollection } from '@fastgpt/service/core/dataset/collection/utils';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collection sync
|
Collection sync
|
||||||
1. Check collection type: link, api dataset collection
|
1. Check collection type: link, api dataset collection
|
||||||
2. Get collection and raw text
|
2. Get collection and raw text
|
||||||
3. Check whether the original text is the same: skip if same
|
3. Check whether the original text is the same: skip if same
|
||||||
4. Create new collection
|
4. Create new collection
|
||||||
5. Delete old collection
|
5. Delete old collection
|
||||||
*/
|
*/
|
||||||
export type CollectionSyncBody = {
|
export type CollectionSyncBody = {
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
@ -27,6 +27,7 @@ async function handler(req: ApiRequestProps<CollectionSyncBody>) {
|
|||||||
const { collection } = await authDatasetCollection({
|
const { collection } = await authDatasetCollection({
|
||||||
req,
|
req,
|
||||||
authToken: true,
|
authToken: true,
|
||||||
|
authApiKey: true,
|
||||||
collectionId,
|
collectionId,
|
||||||
per: WritePermissionVal
|
per: WritePermissionVal
|
||||||
});
|
});
|
||||||
|
|||||||
@ -16,13 +16,13 @@ async function handler(
|
|||||||
const user = await getUserDetail({ tmbId });
|
const user = await getUserDetail({ tmbId });
|
||||||
|
|
||||||
// Remove sensitive information
|
// Remove sensitive information
|
||||||
if (user.team.lafAccount) {
|
// if (user.team.lafAccount) {
|
||||||
user.team.lafAccount = {
|
// user.team.lafAccount = {
|
||||||
appid: user.team.lafAccount.appid,
|
// appid: user.team.lafAccount.appid,
|
||||||
token: '',
|
// token: '',
|
||||||
pat: ''
|
// pat: ''
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
if (user.team.openaiAccount) {
|
if (user.team.openaiAccount) {
|
||||||
user.team.openaiAccount = {
|
user.team.openaiAccount = {
|
||||||
key: '',
|
key: '',
|
||||||
|
|||||||
@ -302,65 +302,64 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// save chat
|
// save chat
|
||||||
if (chatId) {
|
const isOwnerUse = !shareId && !spaceTeamId && String(tmbId) === String(app.tmbId);
|
||||||
const isOwnerUse = !shareId && !spaceTeamId && String(tmbId) === String(app.tmbId);
|
const source = (() => {
|
||||||
const source = (() => {
|
if (shareId) {
|
||||||
if (shareId) {
|
return ChatSourceEnum.share;
|
||||||
return ChatSourceEnum.share;
|
|
||||||
}
|
|
||||||
if (authType === 'apikey') {
|
|
||||||
return ChatSourceEnum.api;
|
|
||||||
}
|
|
||||||
if (spaceTeamId) {
|
|
||||||
return ChatSourceEnum.team;
|
|
||||||
}
|
|
||||||
return ChatSourceEnum.online;
|
|
||||||
})();
|
|
||||||
|
|
||||||
const isInteractiveRequest = !!getLastInteractiveValue(histories);
|
|
||||||
const { text: userInteractiveVal } = chatValue2RuntimePrompt(userQuestion.value);
|
|
||||||
|
|
||||||
const newTitle = isPlugin
|
|
||||||
? variables.cTime ?? getSystemTime(timezone)
|
|
||||||
: getChatTitleFromChatMessage(userQuestion);
|
|
||||||
|
|
||||||
const aiResponse: AIChatItemType & { dataId?: string } = {
|
|
||||||
dataId: responseChatItemId,
|
|
||||||
obj: ChatRoleEnum.AI,
|
|
||||||
value: assistantResponses,
|
|
||||||
[DispatchNodeResponseKeyEnum.nodeResponse]: flowResponses
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isInteractiveRequest) {
|
|
||||||
await updateInteractiveChat({
|
|
||||||
chatId,
|
|
||||||
appId: app._id,
|
|
||||||
userInteractiveVal,
|
|
||||||
aiResponse,
|
|
||||||
newVariables
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await saveChat({
|
|
||||||
chatId,
|
|
||||||
appId: app._id,
|
|
||||||
teamId,
|
|
||||||
tmbId: tmbId,
|
|
||||||
nodes,
|
|
||||||
appChatConfig: chatConfig,
|
|
||||||
variables: newVariables,
|
|
||||||
isUpdateUseTime: isOwnerUse && source === ChatSourceEnum.online, // owner update use time
|
|
||||||
newTitle,
|
|
||||||
shareId,
|
|
||||||
outLinkUid: outLinkUserId,
|
|
||||||
source: source,
|
|
||||||
sourceName: sourceName || '',
|
|
||||||
content: [userQuestion, aiResponse],
|
|
||||||
metadata: {
|
|
||||||
originIp,
|
|
||||||
...metadata
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
if (authType === 'apikey') {
|
||||||
|
return ChatSourceEnum.api;
|
||||||
|
}
|
||||||
|
if (spaceTeamId) {
|
||||||
|
return ChatSourceEnum.team;
|
||||||
|
}
|
||||||
|
return ChatSourceEnum.online;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const isInteractiveRequest = !!getLastInteractiveValue(histories);
|
||||||
|
const { text: userInteractiveVal } = chatValue2RuntimePrompt(userQuestion.value);
|
||||||
|
|
||||||
|
const newTitle = isPlugin
|
||||||
|
? variables.cTime ?? getSystemTime(timezone)
|
||||||
|
: getChatTitleFromChatMessage(userQuestion);
|
||||||
|
|
||||||
|
const aiResponse: AIChatItemType & { dataId?: string } = {
|
||||||
|
dataId: responseChatItemId,
|
||||||
|
obj: ChatRoleEnum.AI,
|
||||||
|
value: assistantResponses,
|
||||||
|
[DispatchNodeResponseKeyEnum.nodeResponse]: flowResponses
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveChatId = chatId || getNanoid(24);
|
||||||
|
if (isInteractiveRequest) {
|
||||||
|
await updateInteractiveChat({
|
||||||
|
chatId: saveChatId,
|
||||||
|
appId: app._id,
|
||||||
|
userInteractiveVal,
|
||||||
|
aiResponse,
|
||||||
|
newVariables
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await saveChat({
|
||||||
|
chatId: saveChatId,
|
||||||
|
appId: app._id,
|
||||||
|
teamId,
|
||||||
|
tmbId: tmbId,
|
||||||
|
nodes,
|
||||||
|
appChatConfig: chatConfig,
|
||||||
|
variables: newVariables,
|
||||||
|
isUpdateUseTime: isOwnerUse && source === ChatSourceEnum.online, // owner update use time
|
||||||
|
newTitle,
|
||||||
|
shareId,
|
||||||
|
outLinkUid: outLinkUserId,
|
||||||
|
source,
|
||||||
|
sourceName: sourceName || '',
|
||||||
|
content: [userQuestion, aiResponse],
|
||||||
|
metadata: {
|
||||||
|
originIp,
|
||||||
|
...metadata
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addLog.info(`completions running time: ${(Date.now() - startTime) / 1000}s`);
|
addLog.info(`completions running time: ${(Date.now() - startTime) / 1000}s`);
|
||||||
@ -407,9 +406,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
return assistantResponses;
|
return assistantResponses;
|
||||||
})();
|
})();
|
||||||
|
const error = flowResponses[flowResponses.length - 1]?.error;
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
...(detail ? { responseData: feResponseData, newVariables } : {}),
|
...(detail ? { responseData: feResponseData, newVariables } : {}),
|
||||||
|
error,
|
||||||
id: chatId || '',
|
id: chatId || '',
|
||||||
model: '',
|
model: '',
|
||||||
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 1 },
|
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 1 },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user