This commit is contained in:
archer
2023-08-04 10:06:34 +08:00
parent ffd4e194bf
commit eb28bfb27b
10 changed files with 663 additions and 95 deletions

View File

@@ -7,15 +7,16 @@ WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json ./
COPY pnpm-lock.yaml* ./
RUN pnpm config set registry https://registry.npmmirror.com/
RUN \
[ -f pnpm-lock.yaml ] && pnpm install || \
[ -f pnpm-lock.yaml ] && pnpm fetch || \
(echo "Lockfile not found." && exit 1)
# Rebuild the source code only when needed
FROM node:current-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY pnpm-lock.yaml* ./
COPY package.json ./
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
@@ -23,7 +24,10 @@ COPY . .
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm install -g pnpm && pnpm run build
RUN npm install -g pnpm
RUN \
[ -f pnpm-lock.yaml ] && (pnpm --offline install && pnpm run build) || \
(echo "Lockfile not found." && exit 1)
# Production image, copy all the files and run next
FROM node:current-alpine AS runner

File diff suppressed because it is too large Load Diff

View File

@@ -25,42 +25,60 @@ const chatModelInput = ({
{
key: 'model',
value: model,
type: 'custom',
label: '对话模型',
connected: true
},
{
key: 'temperature',
value: temperature,
label: '温度',
type: 'slider',
connected: true
},
{
key: 'maxToken',
value: maxToken,
type: 'custom',
label: '回复上限',
connected: true
},
{
key: 'systemPrompt',
value: systemPrompt,
type: 'textarea',
label: '系统提示词',
connected: true
},
{
key: 'limitPrompt',
label: '限定词',
type: 'textarea',
value: limitPrompt,
connected: true
},
{
key: 'switch',
type: 'target',
label: '触发器',
connected: kbList.length > 0
},
{
key: 'quoteQA',
type: 'target',
label: '引用内容',
connected: kbList.length > 0
},
{
key: 'history',
type: 'target',
label: '聊天记录',
connected: true
},
{
key: 'userChatInput',
type: 'target',
label: '用户问题',
connected: true
}
];

View File

@@ -22,7 +22,7 @@ const NodeExtract = ({
const [editExtractFiled, setEditExtractField] = useState<ContextExtractAgentItemType>();
return (
<NodeCard minW={'380px'} moduleId={moduleId} {...props}>
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
<Divider text="Input" />
<Container>
<RenderInput
@@ -64,11 +64,14 @@ const NodeExtract = ({
</Thead>
<Tbody>
{extractKeys.map((item, index) => (
<Tr key={index} position={'relative'}>
<Tr
key={index}
position={'relative'}
whiteSpace={'pre-wrap'}
wordBreak={'break-all'}
>
<Td>{item.key}</Td>
<Td whiteSpace={'pre-wrap'} wordBreak={'break-all'}>
{item.desc}
</Td>
<Td>{item.desc}</Td>
<Td>{item.required ? '✔' : ''}</Td>
<Td whiteSpace={'nowrap'}>
<MyIcon
@@ -139,24 +142,6 @@ const NodeExtract = ({
const newInputs = exists
? extracts.map((item) => (item.key === editExtractFiled.key ? data : item))
: extracts.concat(data);
const newOutputs = exists
? outputs.map((output) =>
output.key === editExtractFiled.key
? {
...output,
key: data.key,
label: `提取结果-${data.desc}`
}
: output
)
: outputs.concat({
key: data.key,
label: `提取结果-${data.desc}`,
description: '无法提取时不会返回',
valueType: FlowValueTypeEnum.string,
type: FlowOutputItemTypeEnum.source,
targets: []
});
onChangeNode({
moduleId,
@@ -167,15 +152,63 @@ const NodeExtract = ({
value: newInputs
}
});
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: newOutputs
});
if (editExtractFiled.key && editExtractFiled.key !== data.key) {
onDelEdge({ moduleId, sourceHandle: editExtractFiled.key });
if (!exists) {
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: outputs.concat({
key: data.key,
label: `提取结果-${data.desc}`,
description: '无法提取时不会返回',
valueType: FlowValueTypeEnum.string,
type: FlowOutputItemTypeEnum.source,
targets: []
})
});
} else {
if (editExtractFiled.key === data.key) {
// update
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: outputs.map((output) =>
output.key === data.key
? {
...output,
label: `提取结果-${data.desc}`
}
: output
)
});
} else {
// del and push
const newOutputs = outputs.filter((output) => output.key !== editExtractFiled.key);
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: newOutputs
});
setTimeout(() => {
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: newOutputs.concat({
key: data.key,
label: `提取结果-${data.desc}`,
description: '无法提取时不会返回',
valueType: FlowValueTypeEnum.string,
type: FlowOutputItemTypeEnum.source,
targets: []
})
});
}, 10);
}
}
setEditExtractField(undefined);
@@ -186,4 +219,4 @@ const NodeExtract = ({
);
};
export default NodeExtract;
export default React.memo(NodeExtract);

View File

@@ -34,7 +34,6 @@ const ExtractFieldModal = ({
const { register, handleSubmit } = useForm<ContextExtractAgentItemType>({
defaultValues: defaultField
});
const isEdit = useMemo(() => !!defaultField.key, [defaultField]);
return (
<MyModal isOpen={true} onClose={onClose}>
@@ -56,17 +55,11 @@ const ExtractFieldModal = ({
</Flex>
<Flex mt={5} alignItems={'center'}>
<Box flex={'0 0 70px'}> key</Box>
<MyTooltip label={isEdit ? '不支持修改 key' : ''} shouldWrapChildren={false}>
<Input
isDisabled={isEdit}
placeholder="name/age/sql"
{...register('key', { required: '字段 key 不能为空' })}
/>
</MyTooltip>
<Input
placeholder="name/age/sql"
{...register('key', { required: '字段 key 不能为空' })}
/>
</Flex>
<Box mt={1} pl={'70px'} color={'myGray.600'} fontSize={'sm'}>
注意: key
</Box>
</ModalBody>
<ModalFooter>

View File

@@ -114,11 +114,13 @@ export const Label = ({
key: data.key,
value: data
});
onChangeNode({
moduleId,
type: 'delInput',
key: editField.key,
value: ''
setTimeout(() => {
onChangeNode({
moduleId,
type: 'delInput',
key: editField.key,
value: ''
});
});
}
setEditField(undefined);

View File

@@ -77,12 +77,31 @@ const Label = ({
defaultField={editField}
onClose={() => setEditField(undefined)}
onSubmit={(data) => {
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: outputs.map((output) => (output.key === outputKey ? data : output))
});
if (editField.key === data.key) {
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: outputs.map((output) => (output.key === outputKey ? data : output))
});
} else {
const storeOutputs = outputs.filter((output) => output.key !== editField.key);
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: storeOutputs
});
setTimeout(() => {
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: storeOutputs.concat(data)
});
}, 10);
}
setEditField(undefined);
}}

View File

@@ -42,4 +42,4 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => {
);
};
export default SourceHandle;
export default React.memo(SourceHandle);

View File

@@ -3,10 +3,12 @@ import { Flex, Box, IconButton } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useUserStore } from '@/store/user';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import MyIcon from '@/components/Icon';
import Avatar from '@/components/Avatar';
const SliderApps = ({ appId }: { appId: string }) => {
const { t } = useTranslation();
const router = useRouter();
const { myApps, loadMyApps } = useUserStore();
@@ -33,7 +35,7 @@ const SliderApps = ({ appId }: { appId: string }) => {
borderRadius={'50%'}
aria-label={''}
/>
退
{t('chat.Exit Chat')}
</Flex>
<Box mt={5}>
{myApps.map((item) => (

View File

@@ -1,6 +1,11 @@
import type { AppModuleItemType, VariableItemType } from '@/types/app';
import { chatModelList, vectorModelList } from '@/store/static';
import { FlowModuleTypeEnum, SpecialInputKeyEnum } from '@/constants/flow';
import {
FlowInputItemTypeEnum,
FlowModuleTypeEnum,
FlowValueTypeEnum,
SpecialInputKeyEnum
} from '@/constants/flow';
import { SystemInputEnum } from '@/constants/app';
import { TaskResponseKeyEnum } from '@/constants/chat';
import type { SelectedKbType } from '@/types/plugin';
@@ -153,42 +158,60 @@ const chatModelInput = (formData: EditFormType): FlowInputItemType[] => [
{
key: 'model',
value: formData.chatModel.model,
type: 'custom',
label: '对话模型',
connected: true
},
{
key: 'temperature',
value: formData.chatModel.temperature,
type: 'slider',
label: '温度',
connected: true
},
{
key: 'maxToken',
value: formData.chatModel.maxToken,
type: 'custom',
label: '回复上限',
connected: true
},
{
key: 'systemPrompt',
value: formData.chatModel.systemPrompt,
type: 'textarea',
label: '系统提示词',
connected: true
},
{
key: 'limitPrompt',
type: 'textarea',
value: formData.chatModel.limitPrompt,
label: '限定词',
connected: true
},
{
key: 'switch',
type: 'target',
label: '触发器',
connected: formData.kb.list.length > 0
},
{
key: 'quoteQA',
type: 'target',
label: '引用内容',
connected: formData.kb.list.length > 0
},
{
key: 'history',
type: 'target',
label: '聊天记录',
connected: true
},
{
key: 'userChatInput',
type: 'target',
label: '用户问题',
connected: true
}
];
@@ -200,6 +223,8 @@ const welcomeTemplate = (formData: EditFormType): AppModuleItemType[] =>
inputs: [
{
key: 'welcomeText',
type: 'input',
label: '开场白',
value: formData.guide.welcome.text,
connected: true
}
@@ -222,6 +247,8 @@ const variableTemplate = (formData: EditFormType): AppModuleItemType[] =>
{
key: 'variables',
value: formData.variables,
type: 'systemInput',
label: '变量输入',
connected: true
}
],
@@ -240,7 +267,9 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
inputs: [
{
key: 'userChatInput',
connected: true
connected: true,
label: '用户问题',
type: 'target'
}
],
outputs: [
@@ -266,10 +295,14 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
{
key: 'maxContext',
value: 6,
connected: true
connected: true,
type: 'numberInput',
label: '最长记录数'
},
{
key: 'history',
type: 'hidden',
label: '聊天记录',
connected: true
}
],
@@ -312,6 +345,8 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
inputs: [
{
key: 'userChatInput',
label: '用户问题',
type: 'target',
connected: true
}
],
@@ -342,10 +377,14 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
{
key: 'maxContext',
value: 6,
connected: true
connected: true,
type: 'numberInput',
label: '最长记录数'
},
{
key: 'history',
type: 'hidden',
label: '聊天记录',
connected: true
}
],
@@ -372,24 +411,34 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
{
key: 'kbList',
value: formData.kb.list,
type: FlowInputItemTypeEnum.custom,
label: '关联的知识库',
connected: true
},
{
key: 'similarity',
value: formData.kb.searchSimilarity,
type: FlowInputItemTypeEnum.slider,
label: '相似度',
connected: true
},
{
key: 'limit',
value: formData.kb.searchLimit,
type: FlowInputItemTypeEnum.slider,
label: '单次搜索上限',
connected: true
},
{
key: 'switch',
type: FlowInputItemTypeEnum.target,
label: '触发器',
connected: false
},
{
key: 'userChatInput',
type: FlowInputItemTypeEnum.target,
label: '用户问题',
connected: true
}
],
@@ -442,11 +491,16 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
inputs: [
{
key: 'switch',
type: FlowInputItemTypeEnum.target,
label: '触发器',
connected: true
},
{
key: SpecialInputKeyEnum.answerText,
value: formData.kb.searchEmptyText,
type: FlowInputItemTypeEnum.textarea,
valueType: FlowValueTypeEnum.string,
label: '回复的内容',
connected: true
}
],