Feat: Chat without KB. #5216 (#5217)

### What problem does this PR solve?
Feat: Chat without KB. #5216

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2025-02-21 12:24:13 +08:00 committed by GitHub
parent f5d63bb7df
commit 46ff897107
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 57 additions and 23 deletions

View File

@ -9,7 +9,15 @@ import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { FormControl, FormField, FormItem, FormLabel } from './ui/form'; import { FormControl, FormField, FormItem, FormLabel } from './ui/form';
import { MultiSelect } from './ui/multi-select'; import { MultiSelect } from './ui/multi-select';
const KnowledgeBaseItem = () => { interface KnowledgeBaseItemProps {
required?: boolean;
onChange?(): void;
}
const KnowledgeBaseItem = ({
required = true,
onChange,
}: KnowledgeBaseItemProps) => {
const { t } = useTranslate('chat'); const { t } = useTranslate('chat');
const { list: knowledgeList } = useFetchKnowledgeList(true); const { list: knowledgeList } = useFetchKnowledgeList(true);
@ -35,7 +43,7 @@ const KnowledgeBaseItem = () => {
tooltip={t('knowledgeBasesTip')} tooltip={t('knowledgeBasesTip')}
rules={[ rules={[
{ {
required: true, required,
message: t('knowledgeBasesMessage'), message: t('knowledgeBasesMessage'),
type: 'array', type: 'array',
}, },
@ -45,6 +53,7 @@ const KnowledgeBaseItem = () => {
mode="multiple" mode="multiple"
options={knowledgeOptions} options={knowledgeOptions}
placeholder={t('knowledgeBasesMessage')} placeholder={t('knowledgeBasesMessage')}
onChange={onChange}
></Select> ></Select>
</Form.Item> </Form.Item>
); );

View File

@ -420,6 +420,7 @@ This procedure will improve precision of retrieval by adding more information to
language: 'Language', language: 'Language',
emptyResponse: 'Empty response', emptyResponse: 'Empty response',
emptyResponseTip: `Set this as a response if no results are retrieved from the knowledge bases for your query, or leave this field blank to allow the LLM to improvise when nothing is found.`, emptyResponseTip: `Set this as a response if no results are retrieved from the knowledge bases for your query, or leave this field blank to allow the LLM to improvise when nothing is found.`,
emptyResponseMessage: `Empty response will be triggered when nothing relevant is retrieved from knowledge bases. Erase 'Empty response' since none of knowledge base is selected.`,
setAnOpener: 'Opening greeting', setAnOpener: 'Opening greeting',
setAnOpenerInitial: `Hi! I'm your assistant, what can I do for you?`, setAnOpenerInitial: `Hi! I'm your assistant, what can I do for you?`,
setAnOpenerTip: 'Set an opening greeting for users.', setAnOpenerTip: 'Set an opening greeting for users.',

View File

@ -402,6 +402,7 @@ export default {
language: '語言', language: '語言',
emptyResponse: '空回复', emptyResponse: '空回复',
emptyResponseTip: `如果在知識庫中沒有檢索到用戶的問題,它將使用它作為答案。如果您希望 LLM 在未檢索到任何內容時提出自己的意見,請將此留空。`, emptyResponseTip: `如果在知識庫中沒有檢索到用戶的問題,它將使用它作為答案。如果您希望 LLM 在未檢索到任何內容時提出自己的意見,請將此留空。`,
emptyResponseMessage: `當知識庫中沒有檢索到任何相關內容時,將觸發空響應。由於未選擇任何知識庫,因此刪除“空響應”。`,
setAnOpener: '設置開場白', setAnOpener: '設置開場白',
setAnOpenerInitial: `你好!我是你的助理,有什麼可以幫到你的嗎?`, setAnOpenerInitial: `你好!我是你的助理,有什麼可以幫到你的嗎?`,
setAnOpenerTip: '您想如何歡迎您的客戶?', setAnOpenerTip: '您想如何歡迎您的客戶?',

View File

@ -419,6 +419,7 @@ General实体和关系提取提示来自 GitHub - microsoft/graphrag基于
language: '语言', language: '语言',
emptyResponse: '空回复', emptyResponse: '空回复',
emptyResponseTip: `如果在知识库中没有检索到用户的问题,它将使用它作为答案。 如果您希望 LLM 在未检索到任何内容时提出自己的意见,请将此留空。`, emptyResponseTip: `如果在知识库中没有检索到用户的问题,它将使用它作为答案。 如果您希望 LLM 在未检索到任何内容时提出自己的意见,请将此留空。`,
emptyResponseMessage: `当知识库中未检索到任何相关信息时,将触发空响应。由于未选择任何知识库,因此请清除“空响应”。`,
setAnOpener: '设置开场白', setAnOpener: '设置开场白',
setAnOpenerInitial: `你好! 我是你的助理,有什么可以帮到你的吗?`, setAnOpenerInitial: `你好! 我是你的助理,有什么可以帮到你的吗?`,
setAnOpenerTip: '您想如何欢迎您的客户?', setAnOpenerTip: '您想如何欢迎您的客户?',

View File

@ -27,7 +27,7 @@ export default function AgentTemplates() {
back={navigateToAgentList} back={navigateToAgentList}
title={t('flow.createGraph')} title={t('flow.createGraph')}
></PageHeader> ></PageHeader>
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8 max-h-[84vh] overflow-auto px-8"> <div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8 max-h-[94vh] overflow-auto px-8">
{list?.map((x) => { {list?.map((x) => {
return ( return (
<TemplateCard <TemplateCard

View File

@ -1,18 +1,40 @@
import { PlusOutlined } from '@ant-design/icons';
import { Form, Input, message, Select, Switch, Upload } from 'antd';
import classNames from 'classnames';
import { ISegmentedContentProps } from '../interface';
import KnowledgeBaseItem from '@/components/knowledge-base-item'; import KnowledgeBaseItem from '@/components/knowledge-base-item';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { useFetchTenantInfo } from '@/hooks/user-setting-hooks'; import { useFetchTenantInfo } from '@/hooks/user-setting-hooks';
import { PlusOutlined } from '@ant-design/icons';
import { Form, Input, message, Select, Switch, Upload } from 'antd';
import classNames from 'classnames';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { ISegmentedContentProps } from '../interface';
import styles from './index.less'; import styles from './index.less';
const AssistantSetting = ({ show, form }: ISegmentedContentProps) => { const emptyResponseField = ['prompt_config', 'empty_response'];
const AssistantSetting = ({
show,
form,
setHasError,
}: ISegmentedContentProps) => {
const { t } = useTranslate('chat'); const { t } = useTranslate('chat');
const { data } = useFetchTenantInfo(true); const { data } = useFetchTenantInfo(true);
const handleChange = useCallback(() => {
const kbIds = form.getFieldValue('kb_ids');
const emptyResponse = form.getFieldValue(emptyResponseField);
const required =
emptyResponse && ((Array.isArray(kbIds) && kbIds.length === 0) || !kbIds);
setHasError(required);
form.setFields([
{
name: emptyResponseField,
errors: required ? [t('emptyResponseMessage')] : [],
},
]);
}, [form, setHasError, t]);
const normFile = (e: any) => { const normFile = (e: any) => {
if (Array.isArray(e)) { if (Array.isArray(e)) {
return e; return e;
@ -31,7 +53,7 @@ const AssistantSetting = ({ show, form }: ISegmentedContentProps) => {
[data, form], [data, form],
); );
const uploadButtion = ( const uploadButton = (
<button style={{ border: 0, background: 'none' }} type="button"> <button style={{ border: 0, background: 'none' }} type="button">
<PlusOutlined /> <PlusOutlined />
<div style={{ marginTop: 8 }}>{t('upload', { keyPrefix: 'common' })}</div> <div style={{ marginTop: 8 }}>{t('upload', { keyPrefix: 'common' })}</div>
@ -66,7 +88,7 @@ const AssistantSetting = ({ show, form }: ISegmentedContentProps) => {
beforeUpload={() => false} beforeUpload={() => false}
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }} showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
> >
{show ? uploadButtion : null} {show ? uploadButton : null}
</Upload> </Upload>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@ -84,11 +106,11 @@ const AssistantSetting = ({ show, form }: ISegmentedContentProps) => {
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name={['prompt_config', 'empty_response']} name={emptyResponseField}
label={t('emptyResponse')} label={t('emptyResponse')}
tooltip={t('emptyResponseTip')} tooltip={t('emptyResponseTip')}
> >
<Input placeholder="" /> <Input placeholder="" onChange={handleChange} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name={['prompt_config', 'prologue']} name={['prompt_config', 'prologue']}
@ -116,15 +138,6 @@ const AssistantSetting = ({ show, form }: ISegmentedContentProps) => {
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
{/* <Form.Item
label={t('selfRag')}
valuePropName="checked"
name={['prompt_config', 'self_rag']}
tooltip={t('selfRagTip')}
initialValue={false}
>
<Switch />
</Form.Item> */}
<Form.Item <Form.Item
label={t('tts')} label={t('tts')}
valuePropName="checked" valuePropName="checked"
@ -134,7 +147,10 @@ const AssistantSetting = ({ show, form }: ISegmentedContentProps) => {
> >
<Switch onChange={handleTtsChange} /> <Switch onChange={handleTtsChange} />
</Form.Item> </Form.Item>
<KnowledgeBaseItem></KnowledgeBaseItem> <KnowledgeBaseItem
required={false}
onChange={handleChange}
></KnowledgeBaseItem>
</section> </section>
); );
}; };

View File

@ -64,6 +64,7 @@ const ChatConfigurationModal = ({
clearDialog, clearDialog,
}: IProps) => { }: IProps) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [hasError, setHasError] = useState(false);
const [value, setValue] = useState<ConfigurationSegmented>( const [value, setValue] = useState<ConfigurationSegmented>(
ConfigurationSegmented.AssistantSetting, ConfigurationSegmented.AssistantSetting,
@ -74,6 +75,9 @@ const ChatConfigurationModal = ({
const handleOk = async () => { const handleOk = async () => {
const values = await form.validateFields(); const values = await form.validateFields();
if (hasError) {
return;
}
const nextValues: any = removeUselessFieldsFromValues( const nextValues: any = removeUselessFieldsFromValues(
values, values,
'llm_setting.', 'llm_setting.',
@ -173,6 +177,7 @@ const ChatConfigurationModal = ({
key={key} key={key}
show={key === value} show={key === value}
form={form} form={form}
setHasError={setHasError}
{...(key === ConfigurationSegmented.ModelSetting {...(key === ConfigurationSegmented.ModelSetting
? { initialLlmSetting: initialDialog.llm_setting, visible } ? { initialLlmSetting: initialDialog.llm_setting, visible }
: {})} : {})}

View File

@ -4,6 +4,7 @@ import { FormInstance } from 'antd';
export interface ISegmentedContentProps { export interface ISegmentedContentProps {
show: boolean; show: boolean;
form: FormInstance; form: FormInstance;
setHasError: (hasError: boolean) => void;
} }
export interface IVariable { export interface IVariable {