From 1e48922bc957fa9df269634c296365af663ee473 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Tue, 28 May 2024 23:33:05 +0800 Subject: [PATCH] Context extract support value type (#1620) * perf: chat box components * perf: chatbox context * feat: extract support value type * workflow performance * update doc * feat: error response * feat: error response * oauth sort * perf: logo * fix: update laf account * perf: team permission api * update type --- .../content/docs/development/openapi/chat.md | 6 +-- .../content/docs/development/upgrading/482.md | 5 +- packages/global/core/ai/prompt/agent.ts | 20 ++++--- .../global/core/workflow/runtime/type.d.ts | 1 + .../template/system/contextExtract.ts | 2 +- packages/global/core/workflow/type/index.d.ts | 1 + .../global/support/user/team/controller.d.ts | 1 - packages/global/support/wallet/bill/type.d.ts | 2 +- .../core/workflow/dispatch/agent/extract.ts | 21 +++++--- .../core/workflow/dispatch/code/run.ts | 6 ++- .../service/support/permission/auth/user.ts | 17 ++++++ .../service/support/user/team/controller.ts | 16 ++++++ packages/web/hooks/useConfirm.tsx | 19 ++++--- projects/app/i18n/en/common.json | 1 + projects/app/i18n/en/workflow.json | 3 +- projects/app/i18n/zh/common.json | 6 +-- projects/app/i18n/zh/workflow.json | 3 +- .../components/ChatBox/Input/ChatInput.tsx | 12 ++--- .../ChatBox/Input/InputGuideBox.tsx | 5 +- .../app/src/components/ChatBox/MarkModal.tsx | 16 ------ .../app/src/components/ChatBox/Provider.tsx | 10 ++-- .../ChatBox/components/ChatController.tsx | 5 +- .../ChatBox/components/ChatItem.tsx | 5 +- .../ChatBox/{ => components}/ContextModal.tsx | 0 .../{ => components}/FeedbackModal.tsx | 0 .../ChatBox/{ => components}/QuoteModal.tsx | 4 +- .../{ => components}/ReadFeedbackModal.tsx | 0 .../ChatBox/{ => components}/ResponseTags.tsx | 2 +- .../{ => components}/SelectMarkCollection.tsx | 2 +- .../{ => components}/WholeResponseModal.tsx | 9 ++-- projects/app/src/components/ChatBox/index.tsx | 17 +++--- projects/app/src/components/Layout/navbar.tsx | 8 ++- .../core/workflow/Flow/nodes/NodeCode.tsx | 11 ++-- .../nodes/NodeExtract/ExtractFieldModal.tsx | 53 +++++++++++++------ .../workflow/Flow/nodes/NodeExtract/index.tsx | 3 +- .../core/workflow/Flow/nodes/NodeLaf.tsx | 1 - .../workflow/Flow/nodes/render/NodeCard.tsx | 8 +-- .../render/RenderToolInput/EditFieldModal.tsx | 18 +------ .../support/laf/LafAccountModal.tsx | 2 - .../user/team/TeamManageModal/EditModal.tsx | 1 - .../user/team/TeamManageModal/index.tsx | 18 +------ .../support/user/team/TeamTagModal/index.tsx | 2 +- .../pages/account/components/UsageTable.tsx | 2 +- .../src/pages/api/support/user/team/update.ts | 21 ++++++++ .../LoginForm/components/FormLayout.tsx | 20 +++---- projects/app/src/web/common/api/lafRequest.ts | 1 - .../web/core/workflow/constants/dataType.ts | 15 ++++++ projects/app/src/web/support/user/team/api.ts | 9 ++-- 48 files changed, 232 insertions(+), 178 deletions(-) delete mode 100644 projects/app/src/components/ChatBox/MarkModal.tsx rename projects/app/src/components/ChatBox/{ => components}/ContextModal.tsx (100%) rename projects/app/src/components/ChatBox/{ => components}/FeedbackModal.tsx (100%) rename projects/app/src/components/ChatBox/{ => components}/QuoteModal.tsx (95%) rename projects/app/src/components/ChatBox/{ => components}/ReadFeedbackModal.tsx (100%) rename projects/app/src/components/ChatBox/{ => components}/ResponseTags.tsx (99%) rename projects/app/src/components/ChatBox/{ => components}/SelectMarkCollection.tsx (99%) rename projects/app/src/components/ChatBox/{ => components}/WholeResponseModal.tsx (97%) create mode 100644 projects/app/src/pages/api/support/user/team/update.ts diff --git a/docSite/content/docs/development/openapi/chat.md b/docSite/content/docs/development/openapi/chat.md index c4407104519..f778f8374f1 100644 --- a/docSite/content/docs/development/openapi/chat.md +++ b/docSite/content/docs/development/openapi/chat.md @@ -211,10 +211,10 @@ data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"《"},"in {{< markdownify >}} ```bash -event: moduleStatus +event: flowNodeStatus data: {"status":"running","name":"知识库搜索"} -event: moduleStatus +event: flowNodeStatus data: {"status":"running","name":"AI 对话"} event: answer @@ -238,7 +238,7 @@ data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{},"index" event: answer data: [DONE] -event: appStreamResponse +event: flowResponses data: [{"moduleName":"知识库搜索","moduleType":"datasetSearchNode","runningTime":1.78},{"question":"导演是谁","quoteList":[{"id":"654f2e49b64caef1d9431e8b","q":"电影《铃芽之旅》的导演是谁?","a":"电影《铃芽之旅》的导演是新海诚!","indexes":[{"type":"qa","dataId":"3515487","text":"电影《铃芽之旅》的导演是谁?","_id":"654f2e49b64caef1d9431e8c","defaultIndex":true}],"datasetId":"646627f4f7b896cfd8910e38","collectionId":"653279b16cd42ab509e766e8","sourceName":"data (81).csv","sourceId":"64fd3b6423aa1307b65896f6","score":0.8935586214065552},{"id":"6552e14c50f4a2a8e632af11","q":"导演是谁?","a":"电影《铃芽之旅》的导演是新海诚。","indexes":[{"defaultIndex":true,"type":"qa","dataId":"3644565","text":"导演是谁?\n电影《铃芽之旅》的导演是新海诚。","_id":"6552e14dde5cc7ba3954e417"}],"datasetId":"646627f4f7b896cfd8910e38","collectionId":"653279b16cd42ab509e766e8","sourceName":"data (81).csv","sourceId":"64fd3b6423aa1307b65896f6","score":0.8890955448150635},{"id":"654f34a0b64caef1d946337e","q":"本作的主人公是谁?","a":"本作的主人公是名叫铃芽的少女。","indexes":[{"type":"qa","dataId":"3515541","text":"本作的主人公是谁?","_id":"654f34a0b64caef1d946337f","defaultIndex":true}],"datasetId":"646627f4f7b896cfd8910e38","collectionId":"653279b16cd42ab509e766e8","sourceName":"data (81).csv","sourceId":"64fd3b6423aa1307b65896f6","score":0.8738770484924316},{"id":"654f3002b64caef1d944207a","q":"电影《铃芽之旅》男主角是谁?","a":"电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。","indexes":[{"type":"qa","dataId":"3515538","text":"电影《铃芽之旅》男主角是谁?","_id":"654f3002b64caef1d944207b","defaultIndex":true}],"datasetId":"646627f4f7b896cfd8910e38","collectionId":"653279b16cd42ab509e766e8","sourceName":"data (81).csv","sourceId":"64fd3b6423aa1307b65896f6","score":0.8607980012893677},{"id":"654f2fc8b64caef1d943fd46","q":"电影《铃芽之旅》的编剧是谁?","a":"新海诚是本片的编剧。","indexes":[{"defaultIndex":true,"type":"qa","dataId":"3515550","text":"电影《铃芽之旅》的编剧是谁?22","_id":"654f2fc8b64caef1d943fd47"}],"datasetId":"646627f4f7b896cfd8910e38","collectionId":"653279b16cd42ab509e766e8","sourceName":"data (81).csv","sourceId":"64fd3b6423aa1307b65896f6","score":0.8468944430351257}],"moduleName":"AI 对话","moduleType":"chatNode","runningTime":1.86}] ``` diff --git a/docSite/content/docs/development/upgrading/482.md b/docSite/content/docs/development/upgrading/482.md index d8adf5de507..d2180d27d29 100644 --- a/docSite/content/docs/development/upgrading/482.md +++ b/docSite/content/docs/development/upgrading/482.md @@ -29,5 +29,6 @@ SANDBOX_URL=内网地址 ## V4.8.2 更新说明 1. 新增 - js代码运行节点(更完整的type提醒,后续继续完善) -2. 修复 - 新增的站点同步无法使用 -3. 修复 - 定时任务无法输入内容 \ No newline at end of file +2. 新增 - 内容提取节点支持数据类型选择 +3. 修复 - 新增的站点同步无法使用 +4. 修复 - 定时任务无法输入内容 \ No newline at end of file diff --git a/packages/global/core/ai/prompt/agent.ts b/packages/global/core/ai/prompt/agent.ts index 681d59f5b71..5e5a67a4d2d 100644 --- a/packages/global/core/ai/prompt/agent.ts +++ b/packages/global/core/ai/prompt/agent.ts @@ -24,22 +24,26 @@ A2: ` }; -export const Prompt_ExtractJson = `你可以从 <对话记录> 中提取指定 JSON 信息,你仅需返回 JSON 字符串,无需回答问题。 +export const Prompt_ExtractJson = `你可以从 <对话记录> 中提取指定 Json 信息,你仅需返回 Json 字符串,无需回答问题。 <提取要求> {{description}} -<字段说明> -1. 下面的 JSON 字符串均按照 JSON Schema 的规则描述。 -2. key 代表字段名;description 代表字段的描述;enum 是可选值,代表可选的 value。 -3. 如果没有可提取的内容,忽略该字段。 -4. 本次需提取的JSON Schema:{{json}} - +<提取规则> +- 本次需提取的 json 字符串,需符合 JsonSchema 的规则。 +- type 代表数据类型; key 代表字段名; description 代表字段的描述; enum 是枚举值,代表可选的 value。 +- 如果没有可提取的内容,忽略该字段。 + + + +{{json}} + <对话记录> {{text}} -`; + +提取的 json 字符串:`; export const Prompt_CQJson = `请帮我执行一个“问题分类”任务,将问题分类为以下几种类型之一: diff --git a/packages/global/core/workflow/runtime/type.d.ts b/packages/global/core/workflow/runtime/type.d.ts index 32287f226a8..f2dc6861a48 100644 --- a/packages/global/core/workflow/runtime/type.d.ts +++ b/packages/global/core/workflow/runtime/type.d.ts @@ -31,6 +31,7 @@ export type DispatchNodeResponseType = { runningTime?: number; query?: string; textOutput?: string; + error?: Record; customInputs?: Record; customOutputs?: Record; diff --git a/packages/global/core/workflow/template/system/contextExtract.ts b/packages/global/core/workflow/template/system/contextExtract.ts index 2223d35f97a..2043fafc814 100644 --- a/packages/global/core/workflow/template/system/contextExtract.ts +++ b/packages/global/core/workflow/template/system/contextExtract.ts @@ -56,7 +56,7 @@ export const ContextExtractModule: FlowNodeTemplateType = { label: '', valueType: WorkflowIOValueTypeEnum.any, description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段", - value: [] // {desc: string; key: string; required: boolean; enum: string[]}[] + value: [] // {valueType: string; desc: string; key: string; required: boolean; enum: string[]}[] } ], outputs: [ diff --git a/packages/global/core/workflow/type/index.d.ts b/packages/global/core/workflow/type/index.d.ts index 9e50458fae4..04409abe7c6 100644 --- a/packages/global/core/workflow/type/index.d.ts +++ b/packages/global/core/workflow/type/index.d.ts @@ -115,6 +115,7 @@ export type ClassifyQuestionAgentItemType = { key: string; }; export type ContextExtractAgentItemType = { + valueType: 'string' | 'number' | 'boolean'; desc: string; key: string; required: boolean; diff --git a/packages/global/support/user/team/controller.d.ts b/packages/global/support/user/team/controller.d.ts index 316bacd5875..4ea50792e74 100644 --- a/packages/global/support/user/team/controller.d.ts +++ b/packages/global/support/user/team/controller.d.ts @@ -14,7 +14,6 @@ export type CreateTeamProps = { lafAccount?: LafAccountType; }; export type UpdateTeamProps = { - teamId: string; name?: string; avatar?: string; teamDomain?: string; diff --git a/packages/global/support/wallet/bill/type.d.ts b/packages/global/support/wallet/bill/type.d.ts index cf808dce575..cb8b6c919c3 100644 --- a/packages/global/support/wallet/bill/type.d.ts +++ b/packages/global/support/wallet/bill/type.d.ts @@ -11,6 +11,7 @@ export type BillSchemaType = { status: 'SUCCESS' | 'REFUND' | 'NOTPAY' | 'CLOSED'; type: `${BillTypeEnum}`; price: number; + hasInvoice: boolean; metadata: { payWay: `${BillPayWayEnum}`; subMode?: `${SubModeEnum}`; @@ -20,7 +21,6 @@ export type BillSchemaType = { extraPoints?: number; invoice: boolean; }; - username: string; }; export type ChatNodeUsageType = { diff --git a/packages/service/core/workflow/dispatch/agent/extract.ts b/packages/service/core/workflow/dispatch/agent/extract.ts index 9d73b52c5fb..b07681b357b 100644 --- a/packages/service/core/workflow/dispatch/agent/extract.ts +++ b/packages/service/core/workflow/dispatch/agent/extract.ts @@ -183,7 +183,7 @@ ${description ? `- ${description}` : ''} > = {}; extractKeys.forEach((item) => { properties[item.key] = { - type: 'string', + type: item.valueType || 'string', description: item.desc, ...(item.enum ? { enum: item.enum.split('\n') } : {}) }; @@ -198,7 +198,7 @@ ${description ? `- ${description}` : ''} required: [] } }; - + console.log(properties); return { filterMessages, agentFunction @@ -319,12 +319,16 @@ const completions = async ({ content: replaceVariable(extractModel.customExtractPrompt || Prompt_ExtractJson, { description, json: extractKeys - .map( - (item) => - `{"key":"${item.key}", "description":"${item.desc}"${ - item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : '' - }}` - ) + .map((item) => { + const valueType = item.valueType || 'string'; + if (valueType !== 'string' && valueType !== 'number') { + item.enum = undefined; + } + + return `{"type":${item.valueType || 'string'}, "key":"${item.key}", "description":"${item.desc}" ${ + item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : '' + }}`; + }) .join('\n'), text: `${histories.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`).join('\n')} Human: ${content}` @@ -365,6 +369,7 @@ Human: ${content}` arg: json5.parse(jsonStr) as Record }; } catch (error) { + console.log('Extract error, ai answer:', answer); console.log(error); return { rawResponse: answer, diff --git a/packages/service/core/workflow/dispatch/code/run.ts b/packages/service/core/workflow/dispatch/code/run.ts index 5b8c93dff50..d8fd77b7b75 100644 --- a/packages/service/core/workflow/dispatch/code/run.ts +++ b/packages/service/core/workflow/dispatch/code/run.ts @@ -45,7 +45,11 @@ export const dispatchRunCode = async (props: RunCodeType): Promise { + const authRes = await authUserRole(props); + + if (authRes.role !== TeamMemberRoleEnum.owner) { + return Promise.reject(TeamErrEnum.unAuthTeam); + } + + return authRes; +} diff --git a/packages/service/support/user/team/controller.ts b/packages/service/support/user/team/controller.ts index 73592e8060d..ff2da42ead8 100644 --- a/packages/service/support/user/team/controller.ts +++ b/packages/service/support/user/team/controller.ts @@ -7,6 +7,7 @@ import { } from '@fastgpt/global/support/user/team/constant'; import { MongoTeamMember } from './teamMemberSchema'; import { MongoTeam } from './teamSchema'; +import { UpdateTeamProps } from '@fastgpt/global/support/user/team/controller'; async function getTeamMember(match: Record): Promise { const tmb = (await MongoTeamMember.findOne(match).populate('teamId')) as TeamMemberWithTeamSchema; @@ -108,3 +109,18 @@ export async function createDefaultTeam({ }); } } + +export async function updateTeam({ + teamId, + name, + avatar, + teamDomain, + lafAccount +}: UpdateTeamProps & { teamId: string }) { + await MongoTeam.findByIdAndUpdate(teamId, { + name, + avatar, + teamDomain, + lafAccount + }); +} diff --git a/packages/web/hooks/useConfirm.tsx b/packages/web/hooks/useConfirm.tsx index 84ca4363604..cf1a71e9e89 100644 --- a/packages/web/hooks/useConfirm.tsx +++ b/packages/web/hooks/useConfirm.tsx @@ -44,18 +44,17 @@ export const useConfirm = (props?: { const confirmCb = useRef(); const cancelCb = useRef(); - const openConfirm = ( - confirm?: Function, - cancel?: any, - customContent?: string | React.ReactNode - ) => { - confirmCb.current = confirm; - cancelCb.current = cancel; + const openConfirm = useCallback( + (confirm?: Function, cancel?: any, customContent?: string | React.ReactNode) => { + confirmCb.current = confirm; + cancelCb.current = cancel; - customContent && setCustomContent(customContent); + customContent && setCustomContent(customContent); - return onOpen; - }; + return onOpen; + }, + [] + ); const ConfirmModal = useCallback( ({ diff --git a/projects/app/i18n/en/common.json b/projects/app/i18n/en/common.json index e9fe5331505..30d793e8a97 100644 --- a/projects/app/i18n/en/common.json +++ b/projects/app/i18n/en/common.json @@ -3,6 +3,7 @@ "App": "App", "Code editor": "Code edit", "Export": "Export", + "Field name": "Name", "Folder": "Folder", "Is open": "Opened", "Login": "Login", diff --git a/projects/app/i18n/en/workflow.json b/projects/app/i18n/en/workflow.json index d44debf0388..8e61365e233 100644 --- a/projects/app/i18n/en/workflow.json +++ b/projects/app/i18n/en/workflow.json @@ -7,6 +7,7 @@ }, "response": { "Custom inputs": "Custom inputs", - "Custom outputs": "Custom outputs" + "Custom outputs": "Custom outputs", + "Error": "Error" } } diff --git a/projects/app/i18n/zh/common.json b/projects/app/i18n/zh/common.json index d2d0069c8d0..c307f9296bc 100644 --- a/projects/app/i18n/zh/common.json +++ b/projects/app/i18n/zh/common.json @@ -3,6 +3,7 @@ "App": "应用", "Code editor": "代码编辑", "Export": "导出", + "Field name": "字段名", "Folder": "文件夹", "Is open": "是否开启", "Login": "登录", @@ -476,7 +477,7 @@ "context total length": "上下文总长度", "module cq": "问题分类列表", "module cq result": "分类结果", - "module extract description": "提取要求描述", + "module extract description": "提取背景描述", "module extract result": "提取结果", "module historyPreview": "完整记录", "module http body": "请求体", @@ -584,8 +585,7 @@ "success": "开始同步" } }, - "training": { - } + "training": {} }, "data": { "Auxiliary Data": "辅助数据", diff --git a/projects/app/i18n/zh/workflow.json b/projects/app/i18n/zh/workflow.json index c52b112367e..f3636f5bc78 100644 --- a/projects/app/i18n/zh/workflow.json +++ b/projects/app/i18n/zh/workflow.json @@ -7,6 +7,7 @@ }, "response": { "Custom inputs": "自定义输入", - "Custom outputs": "自定义输出" + "Custom outputs": "自定义输出", + "Error": "错误信息" } } diff --git a/projects/app/src/components/ChatBox/Input/ChatInput.tsx b/projects/app/src/components/ChatBox/Input/ChatInput.tsx index afcbbdef43a..202e7072da6 100644 --- a/projects/app/src/components/ChatBox/Input/ChatInput.tsx +++ b/projects/app/src/components/ChatBox/Input/ChatInput.tsx @@ -7,7 +7,6 @@ import MyTooltip from '../../MyTooltip'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { compressImgFileAndUpload } from '@/web/common/file/controller'; -import { customAlphabet } from 'nanoid'; import { ChatFileTypeEnum } from '@fastgpt/global/core/chat/constants'; import { addDays } from 'date-fns'; import { useRequest } from '@fastgpt/web/hooks/useRequest'; @@ -15,9 +14,10 @@ import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants' import { ChatBoxInputFormType, ChatBoxInputType, UserInputFileItemType } from '../type'; import { textareaMinH } from '../constants'; import { UseFormReturn, useFieldArray } from 'react-hook-form'; -import { useChatProviderStore } from '../Provider'; +import { ChatBoxContext } from '../Provider'; import dynamic from 'next/dynamic'; -const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6); +import { useContextSelector } from 'use-context-selector'; +import { getNanoid } from '@fastgpt/global/common/string/tools'; const InputGuideBox = dynamic(() => import('./InputGuideBox')); @@ -60,7 +60,7 @@ const ChatInput = ({ whisperConfig, autoTTSResponse, chatInputGuide - } = useChatProviderStore(); + } = useContextSelector(ChatBoxContext, (v) => v); const { isPc, whisperModel } = useSystemStore(); const canvasRef = useRef(null); const { t } = useTranslation(); @@ -119,7 +119,7 @@ const ChatInput = ({ reader.readAsDataURL(file); reader.onload = () => { const item = { - id: nanoid(), + id: getNanoid(6), rawFile: file, type: ChatFileTypeEnum.image, name: file.name, @@ -132,7 +132,7 @@ const ChatInput = ({ }; } else { resolve({ - id: nanoid(), + id: getNanoid(6), rawFile: file, type: ChatFileTypeEnum.file, name: file.name, diff --git a/projects/app/src/components/ChatBox/Input/InputGuideBox.tsx b/projects/app/src/components/ChatBox/Input/InputGuideBox.tsx index e923dc0ff0f..b1108211ff5 100644 --- a/projects/app/src/components/ChatBox/Input/InputGuideBox.tsx +++ b/projects/app/src/components/ChatBox/Input/InputGuideBox.tsx @@ -7,7 +7,8 @@ import { queryChatInputGuideList } from '@/web/core/chat/inputGuide/api'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useTranslation } from 'next-i18next'; import HighlightText from '@fastgpt/web/components/common/String/HighlightText'; -import { useChatProviderStore } from '../Provider'; +import { ChatBoxContext } from '../Provider'; +import { useContextSelector } from 'use-context-selector'; export default function InputGuideBox({ appId, @@ -22,7 +23,7 @@ export default function InputGuideBox({ }) { const { t } = useTranslation(); const { chatT } = useI18n(); - const { chatInputGuide } = useChatProviderStore(); + const chatInputGuide = useContextSelector(ChatBoxContext, (v) => v.chatInputGuide); const { data = [] } = useRequest2( async () => { diff --git a/projects/app/src/components/ChatBox/MarkModal.tsx b/projects/app/src/components/ChatBox/MarkModal.tsx deleted file mode 100644 index da2bfaa3eec..00000000000 --- a/projects/app/src/components/ChatBox/MarkModal.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React, { useState } from 'react'; - -const MarkModal = () => { - const [adminMarkData, setAdminMarkData] = useState<{ - chatItemId: string; - dataId?: string; - datasetId?: string; - collectionId?: string; - q: string; - a: string; - }>(); - - return
MarkModal
; -}; - -export default MarkModal; diff --git a/projects/app/src/components/ChatBox/Provider.tsx b/projects/app/src/components/ChatBox/Provider.tsx index b6d9149003b..970c0443f89 100644 --- a/projects/app/src/components/ChatBox/Provider.tsx +++ b/projects/app/src/components/ChatBox/Provider.tsx @@ -1,7 +1,6 @@ -import React, { useContext, createContext, useState, useMemo, useEffect, useCallback } from 'react'; +import React, { useState, useMemo } from 'react'; import { useAudioPlay } from '@/web/common/utils/voice'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; -import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/index.d'; import { AppChatConfigType, AppTTSConfigType, @@ -15,6 +14,7 @@ import { defaultTTSConfig, defaultWhisperConfig } from '@fastgpt/global/core/app/constants'; +import { createContext } from 'use-context-selector'; type useChatStoreType = OutLinkChatAuthProps & { welcomeText: string; @@ -46,7 +46,7 @@ type useChatStoreType = OutLinkChatAuthProps & { isChatting: boolean; chatInputGuide: ChatInputGuideConfigType; }; -const StateContext = createContext({ +export const ChatBoxContext = createContext({ welcomeText: '', variableList: [], questionGuide: false, @@ -109,8 +109,6 @@ export type ChatProviderProps = OutLinkChatAuthProps & { children: React.ReactNode; }; -export const useChatProviderStore = () => useContext(StateContext); - const Provider = ({ shareId, outLinkUid, @@ -186,7 +184,7 @@ const Provider = ({ chatInputGuide }; - return {children}; + return {children}; }; export default React.memo(Provider); diff --git a/projects/app/src/components/ChatBox/components/ChatController.tsx b/projects/app/src/components/ChatBox/components/ChatController.tsx index dd114b23dc0..1b140395d48 100644 --- a/projects/app/src/components/ChatBox/components/ChatController.tsx +++ b/projects/app/src/components/ChatBox/components/ChatController.tsx @@ -7,7 +7,8 @@ import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { formatChatValue2InputType } from '../utils'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; -import { useChatProviderStore } from '../Provider'; +import { ChatBoxContext } from '../Provider'; +import { useContextSelector } from 'use-context-selector'; export type ChatControllerProps = { isLastChild: boolean; @@ -45,7 +46,7 @@ const ChatController = ({ cancelAudio, audioPlayingChatId, setAudioPlayingChatId - } = useChatProviderStore(); + } = useContextSelector(ChatBoxContext, (v) => v); const controlIconStyle = { w: '14px', cursor: 'pointer', diff --git a/projects/app/src/components/ChatBox/components/ChatItem.tsx b/projects/app/src/components/ChatBox/components/ChatItem.tsx index cfd0e22a7d4..09fe437b4da 100644 --- a/projects/app/src/components/ChatBox/components/ChatItem.tsx +++ b/projects/app/src/components/ChatBox/components/ChatItem.tsx @@ -25,8 +25,9 @@ import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants'; import FilesBlock from './FilesBox'; -import { useChatProviderStore } from '../Provider'; +import { ChatBoxContext } from '../Provider'; import Avatar from '@/components/Avatar'; +import { useContextSelector } from 'use-context-selector'; const colorMap = { [ChatStatusEnum.loading]: { @@ -78,7 +79,7 @@ const ChatItem = ({ bg: 'myGray.50' }; - const { isChatting } = useChatProviderStore(); + const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting); const { chat } = chatControllerProps; const ContentCard = useMemo(() => { diff --git a/projects/app/src/components/ChatBox/ContextModal.tsx b/projects/app/src/components/ChatBox/components/ContextModal.tsx similarity index 100% rename from projects/app/src/components/ChatBox/ContextModal.tsx rename to projects/app/src/components/ChatBox/components/ContextModal.tsx diff --git a/projects/app/src/components/ChatBox/FeedbackModal.tsx b/projects/app/src/components/ChatBox/components/FeedbackModal.tsx similarity index 100% rename from projects/app/src/components/ChatBox/FeedbackModal.tsx rename to projects/app/src/components/ChatBox/components/FeedbackModal.tsx diff --git a/projects/app/src/components/ChatBox/QuoteModal.tsx b/projects/app/src/components/ChatBox/components/QuoteModal.tsx similarity index 95% rename from projects/app/src/components/ChatBox/QuoteModal.tsx rename to projects/app/src/components/ChatBox/components/QuoteModal.tsx index ed65203278f..2fbc89572c5 100644 --- a/projects/app/src/components/ChatBox/QuoteModal.tsx +++ b/projects/app/src/components/ChatBox/components/QuoteModal.tsx @@ -4,8 +4,8 @@ import { ModalBody, Box, useTheme } from '@chakra-ui/react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { useTranslation } from 'next-i18next'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; -import QuoteItem from '../core/dataset/QuoteItem'; -import RawSourceBox from '../core/dataset/RawSourceBox'; +import QuoteItem from '../../core/dataset/QuoteItem'; +import RawSourceBox from '../../core/dataset/RawSourceBox'; const QuoteModal = ({ rawSearch = [], diff --git a/projects/app/src/components/ChatBox/ReadFeedbackModal.tsx b/projects/app/src/components/ChatBox/components/ReadFeedbackModal.tsx similarity index 100% rename from projects/app/src/components/ChatBox/ReadFeedbackModal.tsx rename to projects/app/src/components/ChatBox/components/ReadFeedbackModal.tsx diff --git a/projects/app/src/components/ChatBox/ResponseTags.tsx b/projects/app/src/components/ChatBox/components/ResponseTags.tsx similarity index 99% rename from projects/app/src/components/ChatBox/ResponseTags.tsx rename to projects/app/src/components/ChatBox/components/ResponseTags.tsx index fe5f5743fca..b695a9216fc 100644 --- a/projects/app/src/components/ChatBox/ResponseTags.tsx +++ b/projects/app/src/components/ChatBox/components/ResponseTags.tsx @@ -7,7 +7,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; import dynamic from 'next/dynamic'; import MyTag from '@fastgpt/web/components/common/Tag/index'; -import MyTooltip from '../MyTooltip'; +import MyTooltip from '../../MyTooltip'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils'; import ChatBoxDivider from '@/components/core/chat/Divider'; diff --git a/projects/app/src/components/ChatBox/SelectMarkCollection.tsx b/projects/app/src/components/ChatBox/components/SelectMarkCollection.tsx similarity index 99% rename from projects/app/src/components/ChatBox/SelectMarkCollection.tsx rename to projects/app/src/components/ChatBox/components/SelectMarkCollection.tsx index 7dc187a2a76..46166eeb8b3 100644 --- a/projects/app/src/components/ChatBox/SelectMarkCollection.tsx +++ b/projects/app/src/components/ChatBox/components/SelectMarkCollection.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; -import Avatar from '../Avatar'; +import Avatar from '@/components/Avatar'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import DatasetSelectModal, { useDatasetSelect } from '@/components/core/dataset/SelectModal'; diff --git a/projects/app/src/components/ChatBox/WholeResponseModal.tsx b/projects/app/src/components/ChatBox/components/WholeResponseModal.tsx similarity index 97% rename from projects/app/src/components/ChatBox/WholeResponseModal.tsx rename to projects/app/src/components/ChatBox/components/WholeResponseModal.tsx index 293e749cab9..5e272723da8 100644 --- a/projects/app/src/components/ChatBox/WholeResponseModal.tsx +++ b/projects/app/src/components/ChatBox/components/WholeResponseModal.tsx @@ -1,14 +1,14 @@ -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { Box, useTheme, Flex, Image, BoxProps } from '@chakra-ui/react'; import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d'; import { useTranslation } from 'next-i18next'; import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants'; -import Tabs from '../Tabs'; +import Tabs from '../../Tabs'; import MyModal from '@fastgpt/web/components/common/MyModal'; -import MyTooltip from '../MyTooltip'; +import MyTooltip from '../../MyTooltip'; import { QuestionOutlineIcon } from '@chakra-ui/icons'; -import Markdown from '../Markdown'; +import Markdown from '../../Markdown'; import { QuoteList } from './QuoteModal'; import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants'; import { formatNumber } from '@fastgpt/global/common/math/tools'; @@ -185,6 +185,7 @@ export const ResponseBox = React.memo(function ResponseBox({ label={t('core.chat.response.context total length')} value={activeModule?.contextTotalLen} /> + {/* ai chat */} diff --git a/projects/app/src/components/ChatBox/index.tsx b/projects/app/src/components/ChatBox/index.tsx index c7bb456cba3..fc1e568c888 100644 --- a/projects/app/src/components/ChatBox/index.tsx +++ b/projects/app/src/components/ChatBox/index.tsx @@ -15,14 +15,12 @@ import type { ChatSiteItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type.d'; -import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { Box, Flex, Checkbox } from '@chakra-ui/react'; import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus'; import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants'; -import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { useForm } from 'react-hook-form'; import { useRouter } from 'next/router'; import { useSystemStore } from '@/web/common/system/useSystemStore'; @@ -32,7 +30,7 @@ import { updateChatAdminFeedback, updateChatUserFeedback } from '@/web/core/chat/api'; -import type { AdminMarkType } from './SelectMarkCollection'; +import type { AdminMarkType } from './components/SelectMarkCollection'; import MyTooltip from '../MyTooltip'; @@ -52,7 +50,7 @@ import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/c import { formatChatValue2InputType } from './utils'; import { textareaMinH } from './constants'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; -import ChatProvider, { useChatProviderStore } from './Provider'; +import ChatProvider, { ChatBoxContext } from './Provider'; import ChatItem from './components/ChatItem'; @@ -60,11 +58,12 @@ import dynamic from 'next/dynamic'; import { useCreation } from 'ahooks'; import { AppChatConfigType } from '@fastgpt/global/core/app/type'; import type { StreamResponseType } from '@/web/common/api/fetch'; +import { useContextSelector } from 'use-context-selector'; -const ResponseTags = dynamic(() => import('./ResponseTags')); -const FeedbackModal = dynamic(() => import('./FeedbackModal')); -const ReadFeedbackModal = dynamic(() => import('./ReadFeedbackModal')); -const SelectMarkCollection = dynamic(() => import('./SelectMarkCollection')); +const ResponseTags = dynamic(() => import('./components/ResponseTags')); +const FeedbackModal = dynamic(() => import('./components/FeedbackModal')); +const ReadFeedbackModal = dynamic(() => import('./components/ReadFeedbackModal')); +const SelectMarkCollection = dynamic(() => import('./components/SelectMarkCollection')); const Empty = dynamic(() => import('./components/Empty')); const WelcomeBox = dynamic(() => import('./components/WelcomeBox')); const VariableInput = dynamic(() => import('./components/VariableInput')); @@ -158,7 +157,7 @@ const ChatBox = ( chatHistories, setChatHistories, isChatting - } = useChatProviderStore(); + } = useContextSelector(ChatBoxContext, (v) => v); // compute variable input is finish. const chatForm = useForm({ diff --git a/projects/app/src/components/Layout/navbar.tsx b/projects/app/src/components/Layout/navbar.tsx index dd927b7db28..aed0aff0c98 100644 --- a/projects/app/src/components/Layout/navbar.tsx +++ b/projects/app/src/components/Layout/navbar.tsx @@ -102,7 +102,13 @@ const Navbar = ({ unread }: { unread: number }) => { cursor={'pointer'} onClick={() => router.push('/account')} > - + {/* 导航列表 */} diff --git a/projects/app/src/components/core/workflow/Flow/nodes/NodeCode.tsx b/projects/app/src/components/core/workflow/Flow/nodes/NodeCode.tsx index 847097d6bd0..5a061c91bc2 100644 --- a/projects/app/src/components/core/workflow/Flow/nodes/NodeCode.tsx +++ b/projects/app/src/components/core/workflow/Flow/nodes/NodeCode.tsx @@ -29,13 +29,13 @@ const NodeCode = ({ data, selected }: NodeProps) => { content: workflowT('code.Reset template confirm') }); - const CustomComponent = useMemo( - () => ({ + const CustomComponent = useMemo(() => { + return { [NodeInputKeyEnum.code]: (item: FlowNodeInputItemType) => { return ( - {workflowT('Code')} + Javascript{workflowT('Code')} ) => { ); } - }), - [nodeId, onChangeNode, openConfirm, workflowT] - ); + }; + }, [nodeId, onChangeNode, openConfirm, workflowT]); return ( diff --git a/projects/app/src/components/core/workflow/Flow/nodes/NodeExtract/ExtractFieldModal.tsx b/projects/app/src/components/core/workflow/Flow/nodes/NodeExtract/ExtractFieldModal.tsx index e7e421bf354..d2ef331d9d6 100644 --- a/projects/app/src/components/core/workflow/Flow/nodes/NodeExtract/ExtractFieldModal.tsx +++ b/projects/app/src/components/core/workflow/Flow/nodes/NodeExtract/ExtractFieldModal.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React from 'react'; import { Box, Button, @@ -15,8 +15,11 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import { useTranslation } from 'next-i18next'; import MyTooltip from '@/components/MyTooltip'; import { QuestionOutlineIcon } from '@chakra-ui/icons'; +import MySelect from '@fastgpt/web/components/common/MySelect'; +import { fnValueTypeSelect } from '@/web/core/workflow/constants/dataType'; export const defaultField: ContextExtractAgentItemType = { + valueType: 'string', required: false, defaultValue: '', desc: '', @@ -34,10 +37,11 @@ const ExtractFieldModal = ({ onSubmit: (data: ContextExtractAgentItemType) => void; }) => { const { t } = useTranslation(); - const { register, handleSubmit, watch } = useForm({ + const { register, setValue, handleSubmit, watch } = useForm({ defaultValues: defaultField }); const required = watch('required'); + const valueType = watch('valueType'); return ( )} + + {t('core.module.Data Type')} + + { + setValue('valueType', e); + }} + /> + + + - {t('core.module.Field key')} + {t('Field name')} - - - {t('core.module.extract.Enum Value')}({t('common.choosable')}) - - - - + {(valueType === 'string' || valueType === 'number') && ( + + + {t('core.module.extract.Enum Value')}({t('common.choosable')}) + + + + -