From 752e1ebc532cd8c77aa1a07935606af60ea8e087 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 Date: Fri, 21 Feb 2025 10:56:37 +0800 Subject: [PATCH 01/26] feat: The demonstration page supports modifying dialogue summaries --- .../serializers/chat_serializers.py | 13 +++++++++ apps/application/swagger_api/chat_api.py | 28 +++++++++++++++++++ apps/application/views/chat_views.py | 19 ++++++++++++- apps/locales/en_US/LC_MESSAGES/django.po | 2 ++ apps/locales/zh_CN/LC_MESSAGES/django.po | 3 +- apps/locales/zh_Hant/LC_MESSAGES/django.po | 5 +++- 6 files changed, 67 insertions(+), 3 deletions(-) diff --git a/apps/application/serializers/chat_serializers.py b/apps/application/serializers/chat_serializers.py index 3d8d7696f17..055ec4a623a 100644 --- a/apps/application/serializers/chat_serializers.py +++ b/apps/application/serializers/chat_serializers.py @@ -66,6 +66,10 @@ def valid_model_params_setting(model_id, model_params_setting): credential.get_model_params_setting_form(model.model_name).valid_form(model_params_setting) +class ReAbstractInstanceSerializers(serializers.Serializer): + abstract = serializers.CharField(required=True, error_messages=ErrMessage.char(_("abstract"))) + + class ChatSerializers(serializers.Serializer): class Operate(serializers.Serializer): chat_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid(_("Conversation ID"))) @@ -78,6 +82,15 @@ def logic_delete(self, with_valid=True): is_deleted=True) return True + def re_abstract(self, instance, with_valid=True): + if with_valid: + self.is_valid(raise_exception=True) + ReAbstractInstanceSerializers(data=instance).is_valid(raise_exception=True) + + QuerySet(Chat).filter(id=self.data.get('chat_id'), application_id=self.data.get('application_id')).update( + abstract=instance.get('abstract')) + return True + def delete(self, with_valid=True): if with_valid: self.is_valid(raise_exception=True) diff --git a/apps/application/swagger_api/chat_api.py b/apps/application/swagger_api/chat_api.py index a0cfc8e1b97..32522fd9457 100644 --- a/apps/application/swagger_api/chat_api.py +++ b/apps/application/swagger_api/chat_api.py @@ -23,6 +23,34 @@ def get_request_params_api(): description=_('Application ID')) ] + class Operate(ApiMixin): + @staticmethod + def get_request_params_api(): + return [openapi.Parameter(name='application_id', + in_=openapi.IN_PATH, + type=openapi.TYPE_STRING, + required=True, + description=_('Application ID')), + openapi.Parameter(name='chat_id', + in_=openapi.IN_PATH, + type=openapi.TYPE_STRING, + required=True, + description=_('Conversation ID')), + ] + + class ReAbstract(ApiMixin): + @staticmethod + def get_request_body_api(): + return openapi.Schema( + type=openapi.TYPE_OBJECT, + required=['abstract'], + properties={ + 'abstract': openapi.Schema(type=openapi.TYPE_STRING, title=_("abstract"), + description=_("abstract")) + + } + ) + class OpenAIChatApi(ApiMixin): @staticmethod diff --git a/apps/application/views/chat_views.py b/apps/application/views/chat_views.py index b87309bb298..556f99f26b4 100644 --- a/apps/application/views/chat_views.py +++ b/apps/application/views/chat_views.py @@ -150,7 +150,7 @@ def post(self, request: Request, chat_id: str): operation_id=_("Get the conversation list"), manual_parameters=ChatApi.get_request_params_api(), responses=result.get_api_array_response(ChatApi.get_response_body_api()), - tags=[_("Application/Conversation Log")] + tags=[_("Application/Conversation Log")] ) @has_permissions( ViewPermission([RoleConstants.ADMIN, RoleConstants.USER, RoleConstants.APPLICATION_KEY], @@ -222,6 +222,23 @@ def delete(self, request: Request, application_id: str, chat_id: str): data={'application_id': application_id, 'user_id': request.user.id, 'chat_id': chat_id}).logic_delete()) + @action(methods=['PUT'], detail=False) + @swagger_auto_schema(operation_summary=_("Client modifies dialogue summary"), + operation_id=_("Client modifies dialogue summary"), + request_body=ChatClientHistoryApi.Operate.ReAbstract.get_request_body_api(), + tags=[_("Application/Conversation Log")]) + @has_permissions(ViewPermission( + [RoleConstants.APPLICATION_ACCESS_TOKEN], + [lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE, + dynamic_tag=keywords.get('application_id'))], + compare=CompareConstants.AND), + compare=CompareConstants.AND) + def put(self, request: Request, application_id: str, chat_id: str): + return result.success( + ChatSerializers.Operate( + data={'application_id': application_id, 'user_id': request.user.id, + 'chat_id': chat_id}).re_abstract(request.data)) + class Page(APIView): authentication_classes = [TokenAuth] diff --git a/apps/locales/en_US/LC_MESSAGES/django.po b/apps/locales/en_US/LC_MESSAGES/django.po index 04cb138e3dc..eab7f3db8ed 100644 --- a/apps/locales/en_US/LC_MESSAGES/django.po +++ b/apps/locales/en_US/LC_MESSAGES/django.po @@ -6753,3 +6753,5 @@ msgstr "" msgid "Image download failed, check network" msgstr "" +msgid "Client modifies dialogue summary" +msgstr "" diff --git a/apps/locales/zh_CN/LC_MESSAGES/django.po b/apps/locales/zh_CN/LC_MESSAGES/django.po index 77d44475870..9e29bb722a8 100644 --- a/apps/locales/zh_CN/LC_MESSAGES/django.po +++ b/apps/locales/zh_CN/LC_MESSAGES/django.po @@ -6892,4 +6892,5 @@ msgstr "超出许可证使用限制。" msgid "Image download failed, check network" msgstr "图片下载失败,请检查网络" - +msgid "Client modifies dialogue summary" +msgstr "客户端修改对话摘要" diff --git a/apps/locales/zh_Hant/LC_MESSAGES/django.po b/apps/locales/zh_Hant/LC_MESSAGES/django.po index e0386d030f3..d61d8e98c61 100644 --- a/apps/locales/zh_Hant/LC_MESSAGES/django.po +++ b/apps/locales/zh_Hant/LC_MESSAGES/django.po @@ -6902,4 +6902,7 @@ msgid "License usage limit exceeded." msgstr "超出許可證使用限制。" msgid "Image download failed, check network" -msgstr "圖片下載失敗,檢查網絡" \ No newline at end of file +msgstr "圖片下載失敗,檢查網絡" + +msgid "Client modifies dialogue summary" +msgstr "用戶端修改對話摘要" \ No newline at end of file From b50db413cf86b60bab28d9801f9a16fcf29132db Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Fri, 21 Feb 2025 18:54:05 +0800 Subject: [PATCH 02/26] feat: History record supports modifying chat abstract --- ui/src/api/log.ts | 26 +++++++- ui/src/locales/lang/en-US/ai-chat.ts | 3 +- ui/src/locales/lang/zh-CN/ai-chat.ts | 4 +- ui/src/locales/lang/zh-Hant/ai-chat.ts | 3 +- ui/src/stores/modules/log.ts | 12 ++++ ui/src/views/chat/pc/EditTitleDialog.vue | 85 ++++++++++++++++++++++++ ui/src/views/chat/pc/index.vue | 33 +++++++-- 7 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 ui/src/views/chat/pc/EditTitleDialog.vue diff --git a/ui/src/api/log.ts b/ui/src/api/log.ts index 20973a37104..edcd4d93e33 100644 --- a/ui/src/api/log.ts +++ b/ui/src/api/log.ts @@ -220,6 +220,29 @@ const delChatClientLog: ( return del(`${prefix}/${application_id}/chat/client/${chat_id}`, undefined, {}, loading) } +/** + * 修改历史日志abstract + * @param 参数 + * application_id, chat_id, + * data { + "abstract": "string", + } + */ + +const putChatClientLog: ( + application_id: string, + chat_id: string, + data: any, + loading?: Ref +) => Promise> = (application_id, chat_id, data, loading) => { + return put( + `${prefix}/${application_id}/chat/client/${chat_id}`, + data, + undefined, + loading + ) +} + export default { getChatLog, delChatLog, @@ -231,5 +254,6 @@ export default { exportChatLog, getChatLogClient, delChatClientLog, - postChatRecordLog + postChatRecordLog, + putChatClientLog } diff --git a/ui/src/locales/lang/en-US/ai-chat.ts b/ui/src/locales/lang/en-US/ai-chat.ts index d5629716ec3..ac6cc886d3a 100644 --- a/ui/src/locales/lang/en-US/ai-chat.ts +++ b/ui/src/locales/lang/en-US/ai-chat.ts @@ -90,5 +90,6 @@ export default { title: 'Knowledge Quote', question: 'User Question', optimizationQuestion: 'Optimized Question' - } + }, + editTitle: 'Edit Title', } diff --git a/ui/src/locales/lang/zh-CN/ai-chat.ts b/ui/src/locales/lang/zh-CN/ai-chat.ts index a4b54ad03df..fdc4a55f757 100644 --- a/ui/src/locales/lang/zh-CN/ai-chat.ts +++ b/ui/src/locales/lang/zh-CN/ai-chat.ts @@ -25,7 +25,6 @@ export default { continue: '继续', stopChat: '停止回答' }, - tip: { error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!', errorIdentifyMessage: '无法识别用户身份', @@ -91,5 +90,6 @@ export default { title: '知识库引用', question: '用户问题', optimizationQuestion: '优化后问题' - } + }, + editTitle: '编辑标题', } diff --git a/ui/src/locales/lang/zh-Hant/ai-chat.ts b/ui/src/locales/lang/zh-Hant/ai-chat.ts index a0aa1c27bed..2972bfe4f3c 100644 --- a/ui/src/locales/lang/zh-Hant/ai-chat.ts +++ b/ui/src/locales/lang/zh-Hant/ai-chat.ts @@ -90,5 +90,6 @@ export default { title: '知識庫引用', question: '用戶問題', optimizationQuestion: '優化後問題' - } + }, + editTitle: '編輯標題', } diff --git a/ui/src/stores/modules/log.ts b/ui/src/stores/modules/log.ts index d7a8d64988e..d487c1baf70 100644 --- a/ui/src/stores/modules/log.ts +++ b/ui/src/stores/modules/log.ts @@ -60,6 +60,18 @@ const useLogStore = defineStore({ reject(error) }) }) + }, + async asyncPutChatClientLog(id: string, chatId: string, data: any, loading?: Ref) { + return new Promise((resolve, reject) => { + logApi + .putChatClientLog(id, chatId, data, loading) + .then((data) => { + resolve(data) + }) + .catch((error) => { + reject(error) + }) + }) } } }) diff --git a/ui/src/views/chat/pc/EditTitleDialog.vue b/ui/src/views/chat/pc/EditTitleDialog.vue new file mode 100644 index 00000000000..eea839ea84c --- /dev/null +++ b/ui/src/views/chat/pc/EditTitleDialog.vue @@ -0,0 +1,85 @@ + + + diff --git a/ui/src/views/chat/pc/index.vue b/ui/src/views/chat/pc/index.vue index ba4338ed1ef..3bcaca6572d 100644 --- a/ui/src/views/chat/pc/index.vue +++ b/ui/src/views/chat/pc/index.vue @@ -66,10 +66,22 @@ {{ row.abstract }} -
- - - +
+ + + +
@@ -145,6 +157,7 @@ + diff --git a/ui/src/workflow/common/data.ts b/ui/src/workflow/common/data.ts index 43a632adf0c..ab1a6b9da84 100644 --- a/ui/src/workflow/common/data.ts +++ b/ui/src/workflow/common/data.ts @@ -239,6 +239,19 @@ export const imageUnderstandNode = { } } +export const variableAssignNode = { + type: WorkflowType.VariableAssignNode, + text: t('views.applicationWorkflow.nodes.variableAssignNode.text'), + label: t('views.applicationWorkflow.nodes.variableAssignNode.label'), + height: 252, + properties: { + stepName: t('views.applicationWorkflow.nodes.variableAssignNode.label'), + config: { + + } + } +} + export const imageGenerateNode = { type: WorkflowType.ImageGenerateNode, text: t('views.applicationWorkflow.nodes.imageGenerateNode.text'), @@ -307,7 +320,8 @@ export const menuNodes = [ questionNode, documentExtractNode, speechToTextNode, - textToSpeechNode + textToSpeechNode, + variableAssignNode ] /** @@ -400,7 +414,8 @@ export const nodeDict: any = { [WorkflowType.ImageUnderstandNode]: imageUnderstandNode, [WorkflowType.TextToSpeechNode]: textToSpeechNode, [WorkflowType.SpeechToTextNode]: speechToTextNode, - [WorkflowType.ImageGenerateNode]: imageGenerateNode + [WorkflowType.ImageGenerateNode]: imageGenerateNode, + [WorkflowType.VariableAssignNode]: variableAssignNode, } export function isWorkFlow(type: string | undefined) { return type === 'WORK_FLOW' diff --git a/ui/src/workflow/icons/variable-assign-node-icon.vue b/ui/src/workflow/icons/variable-assign-node-icon.vue new file mode 100644 index 00000000000..d83f578d1d9 --- /dev/null +++ b/ui/src/workflow/icons/variable-assign-node-icon.vue @@ -0,0 +1,6 @@ + + diff --git a/ui/src/workflow/nodes/condition-node/index.vue b/ui/src/workflow/nodes/condition-node/index.vue index 706c315b240..00f2ffbe718 100644 --- a/ui/src/workflow/nodes/condition-node/index.vue +++ b/ui/src/workflow/nodes/condition-node/index.vue @@ -48,7 +48,7 @@ :rules="{ type: 'array', required: true, - message: $t('views.applicationWorkflow.variable.fieldMessage'), + message: $t('views.applicationWorkflow.variable.placeholder'), trigger: 'change' }" > @@ -57,7 +57,7 @@ :nodeModel="nodeModel" class="w-full" :placeholder=" - $t('views.applicationWorkflow.variable.fieldMessage') + $t('views.applicationWorkflow.variable.placeholder') " v-model="condition.field" /> diff --git a/ui/src/workflow/nodes/reranker-node/index.vue b/ui/src/workflow/nodes/reranker-node/index.vue index d8bab107e0a..51567b78b9f 100644 --- a/ui/src/workflow/nodes/reranker-node/index.vue +++ b/ui/src/workflow/nodes/reranker-node/index.vue @@ -45,7 +45,7 @@ :rules="{ type: 'array', required: true, - message: $t('views.applicationWorkflow.variable.fieldMessage'), + message: $t('views.applicationWorkflow.variable.placeholder'), trigger: 'change' }" > diff --git a/ui/src/workflow/nodes/variable-assign-node/index.ts b/ui/src/workflow/nodes/variable-assign-node/index.ts new file mode 100644 index 00000000000..567bf425ae1 --- /dev/null +++ b/ui/src/workflow/nodes/variable-assign-node/index.ts @@ -0,0 +1,14 @@ +import VariableAssignNodeVue from './index.vue' +import { AppNode, AppNodeModel } from '@/workflow/common/app-node' + +class VariableAssignNode extends AppNode { + constructor(props: any) { + super(props, VariableAssignNodeVue) + } +} + +export default { + type: 'variable-assign-node', + model: AppNodeModel, + view: VariableAssignNode +} diff --git a/ui/src/workflow/nodes/variable-assign-node/index.vue b/ui/src/workflow/nodes/variable-assign-node/index.vue new file mode 100644 index 00000000000..315624b2031 --- /dev/null +++ b/ui/src/workflow/nodes/variable-assign-node/index.vue @@ -0,0 +1,201 @@ + + + From b1a3d973c75ea56fe27039095d91c9d8d5166cfc Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud <79562285+wangdan-fit2cloud@users.noreply.github.com> Date: Fri, 21 Feb 2025 12:21:00 +0800 Subject: [PATCH 04/26] feat: User input parameters and interface parameters support adjusting the order(#2103) * feat: table support sort(#2103) * feat: User input parameters and interface parameters support adjusting the order(#2103) * feat: User input parameters and interface parameters support adjusting the order(#2103) --- ui/package.json | 2 ++ .../component/ApiInputFieldTable.vue | 33 +++++++++++++++++-- .../component/UserInputFieldTable.vue | 30 +++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/ui/package.json b/ui/package.json index df369cee555..960dd86829d 100644 --- a/ui/package.json +++ b/ui/package.json @@ -18,6 +18,7 @@ "@ctrl/tinycolor": "^4.1.0", "@logicflow/core": "^1.2.27", "@logicflow/extension": "^1.2.27", + "@types/sortablejs": "^1.15.8", "@vavt/cm-extension": "^1.6.0", "@vueuse/core": "^10.9.0", "@wecom/jssdk": "^2.1.0", @@ -42,6 +43,7 @@ "pinyin-pro": "^3.18.2", "recorder-core": "^1.3.24040900", "screenfull": "^6.0.2", + "sortablejs": "^1.15.6", "use-element-plus-theme": "^0.0.5", "vue": "^3.3.4", "vue-clipboard3": "^2.0.0", diff --git a/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue b/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue index acb40bbeb21..099b511b2a4 100644 --- a/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue +++ b/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue @@ -5,13 +5,15 @@ - {{$t('common.add')}} + {{ $t('common.add') }} @@ -48,11 +50,13 @@ From 43e2e5eebbdc381ee25e1e6e73344a78b94dde9e Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Fri, 21 Feb 2025 15:07:16 +0800 Subject: [PATCH 05/26] fix: type bugs --- ui/src/workflow/common/NodeCascader.vue | 4 ++-- .../workflow/nodes/base-node/component/ApiInputFieldTable.vue | 2 +- .../nodes/base-node/component/UserInputFieldTable.vue | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/workflow/common/NodeCascader.vue b/ui/src/workflow/common/NodeCascader.vue index 4f5a36744cd..66a039cfe98 100644 --- a/ui/src/workflow/common/NodeCascader.vue +++ b/ui/src/workflow/common/NodeCascader.vue @@ -51,7 +51,7 @@ const wheel = (e: any) => { function visibleChange(bool: boolean) { if (bool) { options.value = props.global - ? props.nodeModel.get_up_node_field_list(false, true).filter((v) => v.value === 'global') + ? props.nodeModel.get_up_node_field_list(false, true).filter((v: any) => v.value === 'global') : props.nodeModel.get_up_node_field_list(false, true) } } @@ -80,7 +80,7 @@ const validate = () => { defineExpose({ validate }) onMounted(() => { options.value = props.global - ? props.nodeModel.get_up_node_field_list(false, true).filter((v) => v.value === 'global') + ? props.nodeModel.get_up_node_field_list(false, true).filter((v: any) => v.value === 'global') : props.nodeModel.get_up_node_field_list(false, true) }) diff --git a/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue b/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue index 099b511b2a4..81133d8d8ac 100644 --- a/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue +++ b/ui/src/workflow/nodes/base-node/component/ApiInputFieldTable.vue @@ -108,7 +108,7 @@ function onDragHandle() { const tbody = wrapper.querySelector('.el-table__body-wrapper tbody') if (!tbody) return // 初始化 Sortable - Sortable.create(tbody, { + Sortable.create(tbody as HTMLElement, { animation: 150, ghostClass: 'ghost-row', onEnd: (evt) => { diff --git a/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue b/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue index f9b8bdd10cf..26d0c9c99a7 100644 --- a/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue +++ b/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue @@ -192,7 +192,7 @@ function onDragHandle() { const tbody = wrapper.querySelector('.el-table__body-wrapper tbody') if (!tbody) return // 初始化 Sortable - Sortable.create(tbody, { + Sortable.create(tbody as HTMLElement, { animation: 150, ghostClass: 'ghost-row', onEnd: (evt) => { From 3d7a9fc11ae33514d0ab50b495d61ab24b875ed2 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Mon, 24 Feb 2025 10:07:14 +0800 Subject: [PATCH 06/26] fix: Function library execution role group (#2358) --- apps/common/util/function_code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/util/function_code.py b/apps/common/util/function_code.py index fa3dc503801..31797a9f425 100644 --- a/apps/common/util/function_code.py +++ b/apps/common/util/function_code.py @@ -31,7 +31,7 @@ def __init__(self, sandbox=False): self.user = None self._createdir() if self.sandbox: - os.system(f"chown -R {self.user}:{self.user} {self.sandbox_path}") + os.system(f"chown -R {self.user}:root {self.sandbox_path}") def _createdir(self): old_mask = os.umask(0o077) From fbca79223531b0a95c79ba3b8d232915fb72a968 Mon Sep 17 00:00:00 2001 From: guqing <1484563614@qq.com> Date: Mon, 24 Feb 2025 11:08:43 +0800 Subject: [PATCH 07/26] fix: drawer title for slack setting --- .../component/AccessSettingDrawer.vue | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/ui/src/views/application/component/AccessSettingDrawer.vue b/ui/src/views/application/component/AccessSettingDrawer.vue index 7b6d8f68e25..19edbd57843 100644 --- a/ui/src/views/application/component/AccessSettingDrawer.vue +++ b/ui/src/views/application/component/AccessSettingDrawer.vue @@ -90,8 +90,8 @@ @@ -107,11 +107,13 @@ import { MsgError, MsgSuccess } from '@/utils/message' import { copyClick } from '@/utils/clipboard' import { t } from '@/locales' +type PlatformType = 'wechat' | 'dingtalk' | 'wecom' | 'feishu' | 'slack' + const formRef = ref() const visible = ref(false) const loading = ref(false) const dataLoaded = ref(false) -const configType = ref<'wechat' | 'dingtalk' | 'wecom' | 'feishu'>('wechat') +const configType = ref('wechat') const route = useRoute() const emit = defineEmits(['refresh']) const { @@ -137,7 +139,7 @@ const form = reactive({ callback_url: '' }, feishu: { app_id: '', app_secret: '', verification_token: '', callback_url: '' }, - slack: { signing_secret: '', bot_user_token: '', callback_url: '' } + slack: { signing_secret: '', bot_user_token: '', callback_url: '' } }) const rules = reactive<{ [propName: string]: any }>({ @@ -306,7 +308,13 @@ const configFields: { [propName: string]: { [propName: string]: any } } = { } } -const passwordFields = new Set(['app_secret', 'client_secret', 'secret']) +const passwordFields = new Set([ + 'app_secret', + 'client_secret', + 'secret', + 'bot_user_token', + 'signing_secret' +]) const drawerTitle = computed( () => @@ -314,8 +322,9 @@ const drawerTitle = computed( wechat: t('views.application.applicationAccess.wechatSetting.title'), dingtalk: t('views.application.applicationAccess.dingtalkSetting.title'), wecom: t('views.application.applicationAccess.wecomSetting.title'), - feishu: t('views.application.applicationAccess.larkSetting.title') - })[configType.value] + feishu: t('views.application.applicationAccess.larkSetting.title'), + slack: t('views.application.applicationAccess.slackSetting.title') + }[configType.value]) ) const infoTitle = computed( @@ -324,8 +333,9 @@ const infoTitle = computed( wechat: t('views.applicationOverview.appInfo.header'), dingtalk: t('views.applicationOverview.appInfo.header'), wecom: t('views.applicationOverview.appInfo.header'), - feishu: t('views.applicationOverview.appInfo.header') - })[configType.value] + feishu: t('views.applicationOverview.appInfo.header'), + slack: t('views.applicationOverview.appInfo.header') + }[configType.value]) ) const passwordVisible = reactive>( @@ -366,7 +376,7 @@ const submit = async () => { }) } -const open = async (id: string, type: 'wechat' | 'dingtalk' | 'wecom' | 'feishu') => { +const open = async (id: string, type: PlatformType) => { visible.value = true configType.value = type loading.value = true @@ -388,5 +398,3 @@ const open = async (id: string, type: 'wechat' | 'dingtalk' | 'wecom' | 'feishu' defineExpose({ open }) - - From f034f2a26bbe63c99ceb461ec0657440f0d5645d Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:39:53 +0800 Subject: [PATCH 08/26] chore: Update README.md (#2363) --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/README.md b/README.md index 10eff3a6a0e..d69de7d3c99 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,69 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr - LLM Framework:[LangChain](https://www.langchain.com/) - Database:[PostgreSQL + pgvector](https://www.postgresql.org/) +## Feature Comparison + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureDify.AILangChainFlowiseMaxKB
(Built upon LangChain)
Supported LLMsRich VarietyRich VarietyRich VarietyRich Variety
RAG Engine
Agent
Workflow
Observability
Enterprise Feature (SSO/Access control)✅ (Pro)
Local Deployment
+ ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=1Panel-dev/MaxKB&type=Date)](https://star-history.com/#1Panel-dev/MaxKB&Date) From 097c5f8a0513acf42fa9759faff61c3f1182f79a Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:40:44 +0800 Subject: [PATCH 09/26] chore: Update README.md (#2364) --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index d69de7d3c99..a745f33ce74 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,6 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr ## Feature Comparison - - From 83254bfe1bac9893b3c027479d7d5f3e6c0dd28c Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:42:15 +0800 Subject: [PATCH 10/26] chore: Update README.md (#2365) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a745f33ce74..47a2ecfca2c 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr - + From 3518433ff10aa0539c151766e8c8bdc5e7eecfe3 Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:47:51 +0800 Subject: [PATCH 11/26] chore: Update README.md (#2366) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 47a2ecfca2c..ddfd6adbc60 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr
Feature
Enterprise Feature (SSO/Access control)SSO/Access control
- + @@ -86,10 +86,10 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr - + @@ -100,8 +100,8 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr - + From 8b293ae2471cf263984f6581f015f44214067805 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Mon, 24 Feb 2025 15:52:40 +0800 Subject: [PATCH 12/26] chore(i18n): optimize english translations and standardize title case (#2367) --- ui/src/locales/lang/en-US/views/dataset.ts | 2 +- ui/src/locales/lang/en-US/views/system.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/locales/lang/en-US/views/dataset.ts b/ui/src/locales/lang/en-US/views/dataset.ts index f11a9dbc490..7764c7c5427 100644 --- a/ui/src/locales/lang/en-US/views/dataset.ts +++ b/ui/src/locales/lang/en-US/views/dataset.ts @@ -27,7 +27,7 @@ export default { }, datasetForm: { title: { - info: 'Knowledge settings' + info: 'Knowledge Settings' }, form: { datasetName: { diff --git a/ui/src/locales/lang/en-US/views/system.ts b/ui/src/locales/lang/en-US/views/system.ts index bc4a9075f35..3487bd96ba0 100644 --- a/ui/src/locales/lang/en-US/views/system.ts +++ b/ui/src/locales/lang/en-US/views/system.ts @@ -136,15 +136,15 @@ export default { saveSuccess: 'Appearance settings successfully applied' }, email: { - title: 'Mail Settings', + title: 'Email Settings', smtpHost: 'SMTP Host', smtpHostPlaceholder: 'Please enter SMTP host', smtpPort: 'SMTP Port', smtpPortPlaceholder: 'Please enter SMTP port', smtpUser: 'SMTP User', smtpUserPlaceholder: 'Please enter SMTP user', - sendEmail: 'Send Email', - sendEmailPlaceholder: 'Please enter send email', + sendEmail: 'Sender\'s Email', + sendEmailPlaceholder: 'Please enter the sender\'s email', smtpPassword: 'SMTP Password', smtpPasswordPlaceholder: 'Please enter SMTP password', enableSSL: 'Enable SSL (if the SMTP port is 465, you usually need to enable SSL)', From b6de93e1d400fd302a9e062f5b2c3dcbcf8b6799 Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:09:06 +0800 Subject: [PATCH 13/26] chore: Update README.md (#2369) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ddfd6adbc60..d36d30f3721 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ Access MaxKB web interface at `http://your_server_ip:8080` with default admin cr ## Feature Comparison +MaxKB is positioned as an Ready-to-use RAG (Retrieval-Augmented Generation) intelligent Q&A application, rather than a middleware platform for building large model applications. The following table is merely a comparison from a functional perspective. +
FeatureDify.AI LangChainDify.AI Flowise MaxKB
(Built upon LangChain)
Workflow
Observability
SSO/Access control ✅ (Pro)
From 131b1862e5d533d864b829851fc15a4f3455201b Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:12:35 +0800 Subject: [PATCH 14/26] chore: Update README.md (#2371) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d36d30f3721..9556afe3184 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ MaxKB is positioned as an Ready-to-use RAG (Retrieval-Augmented Generation) inte - + From 1a4cc6e5a82c097e80701eb716dc7fc593c5f32a Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:29:59 +0800 Subject: [PATCH 15/26] fix: Workflow execution decimal cannot be serialized (#2372) --- apps/application/models/application.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/application/models/application.py b/apps/application/models/application.py index ace8c29d427..cc38ff88ddb 100644 --- a/apps/application/models/application.py +++ b/apps/application/models/application.py @@ -7,6 +7,7 @@ @desc: """ import datetime +import decimal import json import uuid @@ -140,6 +141,8 @@ def default(self, obj): return str(obj) if isinstance(obj, datetime.datetime): return obj.strftime("%Y-%m-%d %H:%M:%S") + if isinstance(obj, decimal.Decimal): + return float(obj) else: return json.JSONEncoder.default(self, obj) From 99b8448b96fd0a087fec64686b4834d9e82517e2 Mon Sep 17 00:00:00 2001 From: CaptainB Date: Mon, 24 Feb 2025 16:29:20 +0800 Subject: [PATCH 16/26] fix: Remove vllm image cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1052365 --user=刘瑞斌 【github#2353】vllm视觉模型修改最大tokens不生效 https://www.tapd.cn/57709429/s/1657667 --- .../models_provider/impl/vllm_model_provider/model/image.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/setting/models_provider/impl/vllm_model_provider/model/image.py b/apps/setting/models_provider/impl/vllm_model_provider/model/image.py index f3b69a382e1..75eafd80beb 100644 --- a/apps/setting/models_provider/impl/vllm_model_provider/model/image.py +++ b/apps/setting/models_provider/impl/vllm_model_provider/model/image.py @@ -18,3 +18,6 @@ def new_instance(model_type, model_name, model_credential: Dict[str, object], ** stream_usage=True, **optional_params, ) + + def is_cache_model(self): + return False From 5869af04693516f48d6458ba293cc0858129f8f7 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:33:35 +0800 Subject: [PATCH 17/26] docs: Create an application and add workflow parameters (#2374) --- apps/application/swagger_api/application_api.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/application/swagger_api/application_api.py b/apps/application/swagger_api/application_api.py index 2cabe2150a0..2c9cbd86bf4 100644 --- a/apps/application/swagger_api/application_api.py +++ b/apps/application/swagger_api/application_api.py @@ -234,7 +234,7 @@ def get_request_body_api(): default=[]), 'edges': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_OBJECT), title=_('Connection List'), description=_("Connection List"), - default={}), + default=[]), } ) @@ -324,7 +324,8 @@ def get_request_body_api(): return openapi.Schema( type=openapi.TYPE_OBJECT, required=['name', 'desc', 'model_id', 'dialogue_number', 'dataset_setting', 'model_setting', - 'problem_optimization', 'stt_model_enable', 'stt_model_enable', 'tts_type'], + 'problem_optimization', 'stt_model_enable', 'stt_model_enable', 'tts_type', + 'work_flow'], properties={ 'name': openapi.Schema(type=openapi.TYPE_STRING, title=_("Application Name"), description=_("Application Name")), @@ -361,7 +362,8 @@ def get_request_body_api(): 'tts_model_enable': openapi.Schema(type=openapi.TYPE_STRING, title=_("Is text-to-speech enabled"), description=_("Is text-to-speech enabled")), 'tts_type': openapi.Schema(type=openapi.TYPE_STRING, title=_("Text-to-speech type"), - description=_("Text-to-speech type")) + description=_("Text-to-speech type")), + 'work_flow': ApplicationApi.WorkFlow.get_request_body_api(), } ) @@ -432,4 +434,4 @@ def get_request_body_api(): 'text': openapi.Schema(type=openapi.TYPE_STRING, title=_("Text"), description=_("Text")), } - ) \ No newline at end of file + ) From a6525d3c2fe88beeab4e6945483d79cc402ad771 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:15:46 +0800 Subject: [PATCH 18/26] fix: VLLM supplier recalculates token function (#2375) --- .../impl/vllm_model_provider/model/image.py | 17 ++++++++++++++++- .../impl/vllm_model_provider/model/llm.py | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apps/setting/models_provider/impl/vllm_model_provider/model/image.py b/apps/setting/models_provider/impl/vllm_model_provider/model/image.py index 75eafd80beb..4d5dda29dd7 100644 --- a/apps/setting/models_provider/impl/vllm_model_provider/model/image.py +++ b/apps/setting/models_provider/impl/vllm_model_provider/model/image.py @@ -1,5 +1,8 @@ -from typing import Dict +from typing import Dict, List +from langchain_core.messages import get_buffer_string, BaseMessage + +from common.config.tokenizer_manage_config import TokenizerManage from setting.models_provider.base_model_provider import MaxKBBaseModel from setting.models_provider.impl.base_chat_open_ai import BaseChatOpenAI @@ -21,3 +24,15 @@ def new_instance(model_type, model_name, model_credential: Dict[str, object], ** def is_cache_model(self): return False + + def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int: + if self.usage_metadata is None or self.usage_metadata == {}: + tokenizer = TokenizerManage.get_tokenizer() + return sum([len(tokenizer.encode(get_buffer_string([m]))) for m in messages]) + return self.usage_metadata.get('input_tokens', 0) + + def get_num_tokens(self, text: str) -> int: + if self.usage_metadata is None or self.usage_metadata == {}: + tokenizer = TokenizerManage.get_tokenizer() + return len(tokenizer.encode(text)) + return self.get_last_generation_info().get('output_tokens', 0) diff --git a/apps/setting/models_provider/impl/vllm_model_provider/model/llm.py b/apps/setting/models_provider/impl/vllm_model_provider/model/llm.py index 6f3ed0620d0..7d2a63acd08 100644 --- a/apps/setting/models_provider/impl/vllm_model_provider/model/llm.py +++ b/apps/setting/models_provider/impl/vllm_model_provider/model/llm.py @@ -1,8 +1,11 @@ # coding=utf-8 -from typing import Dict +from typing import Dict, List from urllib.parse import urlparse, ParseResult +from langchain_core.messages import BaseMessage, get_buffer_string + +from common.config.tokenizer_manage_config import TokenizerManage from setting.models_provider.base_model_provider import MaxKBBaseModel from setting.models_provider.impl.base_chat_open_ai import BaseChatOpenAI @@ -33,3 +36,15 @@ def new_instance(model_type, model_name, model_credential: Dict[str, object], ** stream_usage=True, ) return vllm_chat_open_ai + + def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int: + if self.usage_metadata is None or self.usage_metadata == {}: + tokenizer = TokenizerManage.get_tokenizer() + return sum([len(tokenizer.encode(get_buffer_string([m]))) for m in messages]) + return self.usage_metadata.get('input_tokens', 0) + + def get_num_tokens(self, text: str) -> int: + if self.usage_metadata is None or self.usage_metadata == {}: + tokenizer = TokenizerManage.get_tokenizer() + return len(tokenizer.encode(text)) + return self.get_last_generation_info().get('output_tokens', 0) From 28c2d6bf1d6ce591747c634595303371c929bc2a Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud <79562285+wangdan-fit2cloud@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:29:54 +0800 Subject: [PATCH 19/26] feat: Create workflow applications that support template selection --- .../locales/lang/en-US/views/application.ts | 8 ++- .../locales/lang/zh-CN/views/application.ts | 6 +- .../locales/lang/zh-Hant/views/application.ts | 4 ++ .../component/CreateApplicationDialog.vue | 67 ++++++++++++++++--- ui/src/workflow/common/data.ts | 42 ++++++++---- 5 files changed, 99 insertions(+), 28 deletions(-) diff --git a/ui/src/locales/lang/en-US/views/application.ts b/ui/src/locales/lang/en-US/views/application.ts index 82ed3fef316..10f5d9495a2 100644 --- a/ui/src/locales/lang/en-US/views/application.ts +++ b/ui/src/locales/lang/en-US/views/application.ts @@ -46,6 +46,10 @@ export default { simplePlaceholder: 'Suitable for beginners to create assistant.', workflowPlaceholder: 'Suitable for advanced users to customize the workflow of assistant' }, + appTemplate: { + blankApp: 'Blank APP', + assistantApp: 'Knowledge Assistant' + }, aiModel: { label: 'AI Model', placeholder: 'Please select an AI model' @@ -110,7 +114,7 @@ export default { reasoningContent: { label: 'Output Thinking', tooltip: - 'Please set the thinking label based on the model\'s return, and the content in the middle of the label will be recognized as the thinking process.', + "Please set the thinking label based on the model's return, and the content in the middle of the label will be recognized as the thinking process.", start: 'Start', end: 'End' } @@ -211,7 +215,7 @@ export default { slackSetting: { title: 'Slack Configuration', signingSecretPlaceholder: 'Please enter signing secret', - botUserTokenPlaceholder: 'Please enter bot user token', + botUserTokenPlaceholder: 'Please enter bot user token' }, copyUrl: 'Copy the link and fill it in' }, diff --git a/ui/src/locales/lang/zh-CN/views/application.ts b/ui/src/locales/lang/zh-CN/views/application.ts index 0f6733e13c0..f794936f581 100644 --- a/ui/src/locales/lang/zh-CN/views/application.ts +++ b/ui/src/locales/lang/zh-CN/views/application.ts @@ -41,6 +41,10 @@ export default { simplePlaceholder: '适合新手创建小助手', workflowPlaceholder: '适合高级用户自定义小助手的工作流' }, + appTemplate: { + blankApp: '空白应用', + assistantApp: '知识库问答助手' + }, aiModel: { label: 'AI 模型', placeholder: '请选择 AI 模型' @@ -198,7 +202,7 @@ export default { slackSetting: { title: 'Slack 应用配置', signingSecretPlaceholder: '请输入 Signing Secret', - botUserTokenPlaceholder: '请输入 Bot User Token', + botUserTokenPlaceholder: '请输入 Bot User Token' }, copyUrl: '复制链接填入到' }, diff --git a/ui/src/locales/lang/zh-Hant/views/application.ts b/ui/src/locales/lang/zh-Hant/views/application.ts index be2c236bac9..47af0334afe 100644 --- a/ui/src/locales/lang/zh-Hant/views/application.ts +++ b/ui/src/locales/lang/zh-Hant/views/application.ts @@ -41,6 +41,10 @@ export default { simplePlaceholder: '適合新手建立小助手', workflowPlaceholder: '適合高階用戶自訂小助手的工作流程' }, + appTemplate: { + blankApp: '空白應用', + assistantApp: '知識庫問答助手' + }, aiModel: { label: 'AI 模型', placeholder: '請選擇 AI 模型' diff --git a/ui/src/views/application/component/CreateApplicationDialog.vue b/ui/src/views/application/component/CreateApplicationDialog.vue index 234d56f75b9..11a0796429b 100644 --- a/ui/src/views/application/component/CreateApplicationDialog.vue +++ b/ui/src/views/application/component/CreateApplicationDialog.vue @@ -38,11 +38,7 @@ - +

{{ $t('views.application.simple') }}

{{ @@ -52,11 +48,7 @@
- +

{{ $t('views.application.workflow') }}

{{ @@ -68,6 +60,35 @@
+ +
+ + + + {{ $t('views.application.applicationForm.form.appTemplate.blankApp') }} + + + + + {{ $t('views.application.applicationForm.form.appTemplate.assistantApp') }} + + + +
+
Feature✅ (Pro)
Local DeploymentOn-premise Deployment