Skip to content

Commit

Permalink
Context extract support value type (#1620)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
c121914yu authored May 28, 2024
1 parent 8ba8488 commit 1e48922
Show file tree
Hide file tree
Showing 48 changed files with 232 additions and 178 deletions.
6 changes: 3 additions & 3 deletions docSite/content/docs/development/openapi/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}]
```

Expand Down
5 changes: 3 additions & 2 deletions docSite/content/docs/development/upgrading/482.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ SANDBOX_URL=内网地址
## V4.8.2 更新说明

1. 新增 - js代码运行节点(更完整的type提醒,后续继续完善)
2. 修复 - 新增的站点同步无法使用
3. 修复 - 定时任务无法输入内容
2. 新增 - 内容提取节点支持数据类型选择
3. 修复 - 新增的站点同步无法使用
4. 修复 - 定时任务无法输入内容
20 changes: 12 additions & 8 deletions packages/global/core/ai/prompt/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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。
- 如果没有可提取的内容,忽略该字段。
</提取规则>
<JsonSchema>
{{json}}
</JsonSchema>
<对话记录>
{{text}}
</对话记录>
`;
提取的 json 字符串:`;

export const Prompt_CQJson = `请帮我执行一个“问题分类”任务,将问题分类为以下几种类型之一:
Expand Down
1 change: 1 addition & 0 deletions packages/global/core/workflow/runtime/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type DispatchNodeResponseType = {
runningTime?: number;
query?: string;
textOutput?: string;
error?: Record<string, any>;
customInputs?: Record<string, any>;
customOutputs?: Record<string, any>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
1 change: 1 addition & 0 deletions packages/global/core/workflow/type/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export type ClassifyQuestionAgentItemType = {
key: string;
};
export type ContextExtractAgentItemType = {
valueType: 'string' | 'number' | 'boolean';
desc: string;
key: string;
required: boolean;
Expand Down
1 change: 0 additions & 1 deletion packages/global/support/user/team/controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export type CreateTeamProps = {
lafAccount?: LafAccountType;
};
export type UpdateTeamProps = {
teamId: string;
name?: string;
avatar?: string;
teamDomain?: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/global/support/wallet/bill/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type BillSchemaType = {
status: 'SUCCESS' | 'REFUND' | 'NOTPAY' | 'CLOSED';
type: `${BillTypeEnum}`;
price: number;
hasInvoice: boolean;
metadata: {
payWay: `${BillPayWayEnum}`;
subMode?: `${SubModeEnum}`;
Expand All @@ -20,7 +21,6 @@ export type BillSchemaType = {
extraPoints?: number;
invoice: boolean;
};
username: string;
};

export type ChatNodeUsageType = {
Expand Down
21 changes: 13 additions & 8 deletions packages/service/core/workflow/dispatch/agent/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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') } : {})
};
Expand All @@ -198,7 +198,7 @@ ${description ? `- ${description}` : ''}
required: []
}
};

console.log(properties);
return {
filterMessages,
agentFunction
Expand Down Expand Up @@ -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}`
Expand Down Expand Up @@ -365,6 +369,7 @@ Human: ${content}`
arg: json5.parse(jsonStr) as Record<string, any>
};
} catch (error) {
console.log('Extract error, ai answer:', answer);
console.log(error);
return {
rawResponse: answer,
Expand Down
6 changes: 5 additions & 1 deletion packages/service/core/workflow/dispatch/code/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ export const dispatchRunCode = async (props: RunCodeType): Promise<RunCodeRespon
}
} catch (error) {
return {
[NodeOutputKeyEnum.error]: formatHttpError(error)
[NodeOutputKeyEnum.error]: formatHttpError(error),
[DispatchNodeResponseKeyEnum.nodeResponse]: {
customInputs: customVariables,
error: formatHttpError(error)
}
};
}
};
17 changes: 17 additions & 0 deletions packages/service/support/permission/auth/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
import { parseHeaderCert } from '../controller';
import { getTmbInfoByTmbId } from '../../user/team/controller';
import { UserErrEnum } from '../../../../global/common/error/code/user';
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';

export async function authUserNotVisitor(props: AuthModeType): Promise<
AuthResponseType & {
Expand Down Expand Up @@ -47,3 +48,19 @@ export async function authUserRole(props: AuthModeType): Promise<
canWrite
};
}

/* auth teamMember in team role */
export async function authTeamOwner(props: AuthModeType): Promise<
AuthResponseType & {
role: `${TeamMemberRoleEnum}`;
teamOwner: boolean;
}
> {
const authRes = await authUserRole(props);

if (authRes.role !== TeamMemberRoleEnum.owner) {
return Promise.reject(TeamErrEnum.unAuthTeam);
}

return authRes;
}
16 changes: 16 additions & 0 deletions packages/service/support/user/team/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>): Promise<TeamItemType> {
const tmb = (await MongoTeamMember.findOne(match).populate('teamId')) as TeamMemberWithTeamSchema;
Expand Down Expand Up @@ -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
});
}
19 changes: 9 additions & 10 deletions packages/web/hooks/useConfirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,17 @@ export const useConfirm = (props?: {
const confirmCb = useRef<Function>();
const cancelCb = useRef<any>();

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(
({
Expand Down
1 change: 1 addition & 0 deletions projects/app/i18n/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"App": "App",
"Code editor": "Code edit",
"Export": "Export",
"Field name": "Name",
"Folder": "Folder",
"Is open": "Opened",
"Login": "Login",
Expand Down
3 changes: 2 additions & 1 deletion projects/app/i18n/en/workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"response": {
"Custom inputs": "Custom inputs",
"Custom outputs": "Custom outputs"
"Custom outputs": "Custom outputs",
"Error": "Error"
}
}
6 changes: 3 additions & 3 deletions projects/app/i18n/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"App": "应用",
"Code editor": "代码编辑",
"Export": "导出",
"Field name": "字段名",
"Folder": "文件夹",
"Is open": "是否开启",
"Login": "登录",
Expand Down Expand Up @@ -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": "请求体",
Expand Down Expand Up @@ -584,8 +585,7 @@
"success": "开始同步"
}
},
"training": {
}
"training": {}
},
"data": {
"Auxiliary Data": "辅助数据",
Expand Down
3 changes: 2 additions & 1 deletion projects/app/i18n/zh/workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"response": {
"Custom inputs": "自定义输入",
"Custom outputs": "自定义输出"
"Custom outputs": "自定义输出",
"Error": "错误信息"
}
}
12 changes: 6 additions & 6 deletions projects/app/src/components/ChatBox/Input/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ 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';
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'));

Expand Down Expand Up @@ -60,7 +60,7 @@ const ChatInput = ({
whisperConfig,
autoTTSResponse,
chatInputGuide
} = useChatProviderStore();
} = useContextSelector(ChatBoxContext, (v) => v);
const { isPc, whisperModel } = useSystemStore();
const canvasRef = useRef<HTMLCanvasElement>(null);
const { t } = useTranslation();
Expand Down Expand Up @@ -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,
Expand All @@ -132,7 +132,7 @@ const ChatInput = ({
};
} else {
resolve({
id: nanoid(),
id: getNanoid(6),
rawFile: file,
type: ChatFileTypeEnum.file,
name: file.name,
Expand Down
5 changes: 3 additions & 2 deletions projects/app/src/components/ChatBox/Input/InputGuideBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 () => {
Expand Down
16 changes: 0 additions & 16 deletions projects/app/src/components/ChatBox/MarkModal.tsx

This file was deleted.

Loading

0 comments on commit 1e48922

Please sign in to comment.