|
|
@@ -5,9 +5,9 @@ import './style.less';
|
|
|
import {
|
|
|
Button, Input, Form, Divider, Splitter, Select, InputNumber, InputNumberProps,
|
|
|
Radio, Switch, Row, Col, Slider, Space, RadioChangeEvent,
|
|
|
- Spin, message
|
|
|
+ Spin, message, Typography, Tooltip
|
|
|
} from 'antd';
|
|
|
-import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
|
|
|
+import { PlusCircleOutlined, MinusCircleOutlined, ArrowLeftOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
|
|
import { apis } from '@/apis';
|
|
|
import router from '@/router';
|
|
|
import LocalStorage from '@/LocalStorage';
|
|
|
@@ -50,7 +50,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<InputNumber
|
|
|
min={0}
|
|
|
max={1}
|
|
|
- style={{ margin: '0 16px', width: '100px' }}
|
|
|
+ className='form-input-number-small'
|
|
|
step={0.01}
|
|
|
value={topPValue}
|
|
|
onChange={onChange}
|
|
|
@@ -85,7 +85,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<InputNumber
|
|
|
min={0}
|
|
|
max={1}
|
|
|
- style={{ margin: '0 16px', width: '100px' }}
|
|
|
+ className='form-input-number-small'
|
|
|
step={0.01}
|
|
|
value={tempValue}
|
|
|
onChange={onChange}
|
|
|
@@ -422,7 +422,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
name='name'
|
|
|
rules={[{ required: true, message: '问答应用名称不能为空' }]}
|
|
|
>
|
|
|
- <Input placeholder="应用名称" style={{ width: 646, padding: 8 }} />
|
|
|
+ <Input placeholder="请输入问答应用名称" className='form-input-large' />
|
|
|
</FormItem>
|
|
|
|
|
|
<FormItem
|
|
|
@@ -430,8 +430,8 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
name='typeId'
|
|
|
>
|
|
|
<Select
|
|
|
- style={{ width: '300px', height: '48px' }}
|
|
|
- placeholder='请选应用类型'
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
+ placeholder='请选择问答应用类型'
|
|
|
onChange={handleAppChange}
|
|
|
allowClear={true}
|
|
|
>
|
|
|
@@ -453,7 +453,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
rules={[{ required: true, message: '项目类型不能为空' }]}
|
|
|
>
|
|
|
<Select
|
|
|
- style={{ width: '300px', height: '48px' }}
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
placeholder='请选择项目类型'
|
|
|
value={selectedAppProId}
|
|
|
onChange={(value) => setSelectedAppProId(value)}
|
|
|
@@ -475,56 +475,81 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<TextArea
|
|
|
showCount
|
|
|
maxLength={500}
|
|
|
- placeholder="请输入描述"
|
|
|
- style={{ height: 120, resize: 'none', width: 646 }}
|
|
|
+ placeholder="请输入当前应用的描述"
|
|
|
+ className='form-textarea-large'
|
|
|
/>
|
|
|
</FormItem>
|
|
|
|
|
|
- <div>
|
|
|
+ <div className='preset-questions'>
|
|
|
<h4>添加预设问题</h4>
|
|
|
<div>
|
|
|
{
|
|
|
inputs.map(input => (
|
|
|
- <div key={input.id} style={{ paddingTop: '10px' }}>
|
|
|
+ <div key={input.id} className='question-item'>
|
|
|
<label>问题 {input.id}</label>
|
|
|
<Input
|
|
|
- style={{ width: 300, paddingTop: 8, marginLeft: 20 }}
|
|
|
+ className='question-input'
|
|
|
type="text"
|
|
|
value={input.value}
|
|
|
onChange={e => handleChange(input.id, e.target.value)}
|
|
|
/>
|
|
|
- <PlusCircleOutlined style={{ marginLeft: 20 }} onClick={addInput} />
|
|
|
- <MinusCircleOutlined style={{ marginLeft: 20 }} onClick={delInput} />
|
|
|
+ <div className='question-actions'>
|
|
|
+ <PlusCircleOutlined className='question-icon' onClick={addInput} />
|
|
|
+ <MinusCircleOutlined className='question-icon' onClick={delInput} />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
))}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <br />
|
|
|
- <Button type='primary' onClick={() => {
|
|
|
- form.validateFields(['name', 'desc', 'appProId']).then(async (values) => {
|
|
|
- setStep(2);
|
|
|
- setInputs(inputs);
|
|
|
- }).catch((error) => {
|
|
|
- console.error(error);
|
|
|
- });
|
|
|
- }} >
|
|
|
- 下一步
|
|
|
- </Button>
|
|
|
+
|
|
|
+ <div style={{ display: 'flex', gap: '12px', marginTop: '24px', paddingTop: '24px', borderTop: '1px solid #f0f0f0' }}>
|
|
|
+ <Button
|
|
|
+ className='btn-cancel'
|
|
|
+ onClick={() => {
|
|
|
+ router.navigate({ pathname: '/deepseek/questionAnswer' });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 返回
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ type='primary'
|
|
|
+ onClick={() => {
|
|
|
+ form.validateFields(['name', 'desc', 'appProId']).then(async (values) => {
|
|
|
+ setStep(2);
|
|
|
+ setInputs(inputs);
|
|
|
+ }).catch((error) => {
|
|
|
+ console.error(error);
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 下一步
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<div style={{ display: step === 2 ? 'block' : 'none' }} className='questionAnswerInfo-content'>
|
|
|
- <div style={{ paddingBottom: '10px', display: 'flex', justifyContent: 'flex-end' }}>
|
|
|
+ <div className='flex-between padding-bottom-16'>
|
|
|
<div>
|
|
|
<Button
|
|
|
- style={{ background: '#f5f5f5' }}
|
|
|
+ className='btn-back'
|
|
|
+ icon={<ArrowLeftOutlined />}
|
|
|
onClick={() => {
|
|
|
setStep(1);
|
|
|
}}
|
|
|
>
|
|
|
上一步
|
|
|
</Button>
|
|
|
- {
|
|
|
- createFlag &&
|
|
|
+ </div>
|
|
|
+ <div style={{ display: 'flex', gap: '12px' }}>
|
|
|
+ <Button
|
|
|
+ className='btn-cancel'
|
|
|
+ onClick={() => {
|
|
|
+ router.navigate({ pathname: '/deepseek/questionAnswer' });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ {createFlag && (
|
|
|
<Button
|
|
|
type='primary'
|
|
|
onClick={() => {
|
|
|
@@ -618,45 +643,63 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
});
|
|
|
}}
|
|
|
>提交应用</Button>
|
|
|
- }
|
|
|
+ )}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <Splitter style={{ height: '100%', boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)' }}>
|
|
|
- <Splitter.Panel defaultSize="40%">
|
|
|
- <div style={{ width: '100%', height: '100%' }}>
|
|
|
- <h2>Prompt编写</h2>
|
|
|
- <div style={{ paddingTop: '20px' }}>
|
|
|
- <TextArea
|
|
|
- autoSize
|
|
|
- readOnly
|
|
|
- placeholder="编写Prompt过程中可以引入2项变量:{{知识}} 代表知识库中检索到的知识内容, {{用户}}代表用户输入的内容。您可以在编写Prompt过程中将变量拼接在合适的位置。插入:{{知识}} 插入:{{用户}}"
|
|
|
- style={{ width: '100%', height: '300px' }}
|
|
|
- />
|
|
|
+ <div className='section-title'>
|
|
|
+ Prompt编写与参数配置
|
|
|
+ <Tooltip
|
|
|
+ title="Prompt用于对大模型的回复做出一些列指令和约束。这段Prompt不会被用户看到。"
|
|
|
+ placement="right"
|
|
|
+ overlayStyle={{ fontSize: '12px' }}
|
|
|
+ >
|
|
|
+ <InfoCircleOutlined style={{ marginLeft: '8px', color: '#999', fontSize: '14px' }} />
|
|
|
+ </Tooltip>
|
|
|
+ </div>
|
|
|
+ <Splitter style={{ border: '1px solid #f0f0f0', borderRadius: '6px' }}>
|
|
|
+ <Splitter.Panel defaultSize="65%">
|
|
|
+ <div className='prompt'>
|
|
|
+ <div className='prompt-info'>
|
|
|
+ <div className='prompt-info-text'>
|
|
|
+ <Typography.Paragraph style={{ fontSize: '12px', lineHeight: '1.6', color: '#999', margin: 0 }}>
|
|
|
+ 编写Prompt过程中可以引入2项变量:
|
|
|
+ <span className='variable-highlight'>{'{{知识}}'}</span>
|
|
|
+ 代表知识库中检索到的知识内容,
|
|
|
+ <span className='variable-highlight'>{'{{用户}}'}</span>
|
|
|
+ 代表用户输入的内容。您可以在编写Prompt过程中将变量拼接在合适的位置。
|
|
|
+ <br />
|
|
|
+ 插入:
|
|
|
+ <span className='variable-highlight'>{'{{知识}}'}</span>,
|
|
|
+ 插入:
|
|
|
+ <span className='variable-highlight'>{'{{用户}}'}</span>。
|
|
|
+ </Typography.Paragraph>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <Divider plain></Divider>
|
|
|
- <div >
|
|
|
+ <Divider style={{ margin: '0' }} />
|
|
|
+ <div className='prompt-editor-area'>
|
|
|
<FormItem name='prompt'
|
|
|
- initialValue={`你是一位知识检索助手,你必须并且只能从我发送的众多知识片段中寻找能够解决用户输入问题的最优答案,并且在执行任务的过程中严格执行规定的要求。
|
|
|
-
|
|
|
+ initialValue={
|
|
|
+ `你是一位知识检索助手,你必须并且只能从我发送的众多知识片段中寻找能够解决用户输入问题的最优答案,并且在执行任务的过程中严格执行规定的要求。 \n
|
|
|
知识片段如下:
|
|
|
{{知识}}
|
|
|
|
|
|
规定要求:
|
|
|
-- 找到答案就仅使用知识片段中的原文回答用户的提问;
|
|
|
-- 找不到答案就用自身知识并且告诉用户该信息不是来自文档;
|
|
|
+- 找到答案就仅使用知识片段中的原文回答用户的提问;- 找不到答案就用自身知识并且告诉用户该信息不是来自文档;
|
|
|
- 所引用的文本片段中所包含的示意图占位符必须进行返回,占位符格式参考:【示意图序号_编号】
|
|
|
- - 严禁输出任何知识片段中不存在的示意图占位符;
|
|
|
- - 输出的内容必须删除其中包含的任何图注、序号等信息。例如:“进入登录页面(图1.1)”需要从文字中删除图序,回复效果为:“进入登录页面”;“如图所示1.1”,回复效果为:“如图所示”;
|
|
|
-- 格式规范
|
|
|
- - 文档中会出现包含表格的情况,表格是以图片标识符的形式呈现,表格中缺失数据时候返回空单元格;
|
|
|
- - 如果需要用到表格中的数据,以代码块语法输出表格中的数据;
|
|
|
- - 避免使用代码块语法回复信息;
|
|
|
- - 回复的开头语不要输出诸如:“我想”,“我认为”,“think”等相关语义的文本。
|
|
|
+- 严禁输出任何知识片段中不存在的示意图占位符;
|
|
|
+- 输出的内容必须删除其中包含的任何图注、序号等信息。例如:“进入登录页面(图1.1)”需要从文字中删除图序,回复效果为:“进入登录页面”;“如图所示1.1”,回复效果为:“如图所示”;
|
|
|
+
|
|
|
+格式规范:
|
|
|
+- 文档中会出现包含表格的情况,表格是以图片标识符的形式呈现,表格中缺失数据时候返回空单元格;
|
|
|
+- 如果需要用到表格中的数据,以代码块语法输出表格中的数据;
|
|
|
+- 避免使用代码块语法回复信息;
|
|
|
+- 回复的开头语不要输出诸如:“我想”,“我认为”,“think”等相关语义的文本。
|
|
|
|
|
|
严格执行规定要求,不要复述问题,直接开始回答。
|
|
|
|
|
|
用户输入问题:
|
|
|
-{{用户}}`}
|
|
|
+{{用户}}`
|
|
|
+ }
|
|
|
rules={[{ required: true, message: '提示词不能为空' }]}>
|
|
|
<TextArea
|
|
|
placeholder="提示词"
|
|
|
@@ -665,19 +708,15 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
</Splitter.Panel>
|
|
|
- <Splitter.Panel defaultSize="60%">
|
|
|
- <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', background: '#f5f5f5', width: '100%', height: '100%' }}>
|
|
|
- <div style={{ width: '50%', height: '100%' }}>
|
|
|
- <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: '50px', fontSize: '16px' }}>
|
|
|
+ <Splitter.Panel defaultSize="35%">
|
|
|
+ <div className='flex-center-container'>
|
|
|
+ <div className='half-width'>
|
|
|
+ <div className='flex-center-top'>
|
|
|
欢迎使用 {name}
|
|
|
</div>
|
|
|
|
|
|
- <div style={{
|
|
|
- display: 'flex', justifyContent: 'center', alignItems: 'center',
|
|
|
- paddingTop: '20px'
|
|
|
- }}>
|
|
|
+ <div className='flex-center padding-top-20'>
|
|
|
<FormItem
|
|
|
label='引用知识库'
|
|
|
name='knowledge_ids'
|
|
|
@@ -686,7 +725,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
// mode='multiple'
|
|
|
// maxCount={MAX_COUNT}
|
|
|
// suffixIcon={suffix}
|
|
|
- style={{ width: '300px', height: '48px' }}
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
placeholder='请选择知识库'
|
|
|
>
|
|
|
{
|
|
|
@@ -699,7 +738,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
- <div style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
|
|
+ <div className='flex-center'>
|
|
|
<FormItem
|
|
|
label='调用模型'
|
|
|
name="model"
|
|
|
@@ -707,7 +746,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<Select
|
|
|
placeholder='请选择模型'
|
|
|
allowClear={true}
|
|
|
- style={{width: '300px', height: '48px'}}
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
onChange={(value) => {
|
|
|
if (value === 'Qwen3-30B') {
|
|
|
setIsDeepThinkVisible(true);
|
|
|
@@ -722,26 +761,20 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
- <div style={{
|
|
|
- display: isDeepThinkVisible ? 'flex' : 'none',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center'
|
|
|
+ <div className='flex-center' style={{
|
|
|
+ display: isDeepThinkVisible ? 'flex' : 'none'
|
|
|
}}>
|
|
|
<FormItem
|
|
|
label='深度思考'
|
|
|
name='isDeepThink'
|
|
|
rules={[{ required: true, message: '请选择是否深度思考' }]}>
|
|
|
- <Radio.Group buttonStyle="solid" style={{width: '300px'}}>
|
|
|
+ <Radio.Group buttonStyle="solid" className='form-control-width'>
|
|
|
<Radio.Button value='Y'>是</Radio.Button>
|
|
|
<Radio.Button value='N'>否</Radio.Button>
|
|
|
</Radio.Group>
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
- <div style={{
|
|
|
- display: 'flex',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center'
|
|
|
- }}>
|
|
|
+ <div className='flex-center'>
|
|
|
<FormItem
|
|
|
label='max token'
|
|
|
name='max_token'
|
|
|
@@ -754,14 +787,10 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
|
|
|
{
|
|
|
!isVisible &&
|
|
|
- <div style={{
|
|
|
- display: 'flex',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center'
|
|
|
- }}>
|
|
|
+ <div className='flex-center'>
|
|
|
<a onClick={() => {
|
|
|
setIsVisible(!isVisible);
|
|
|
- }} className='questionAnswerInfo-content-title'>
|
|
|
+ }} className='link-more-settings'>
|
|
|
更多设置
|
|
|
</a>
|
|
|
</div>
|
|
|
@@ -772,28 +801,20 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<div style={{display: isVisible ? 'block' : 'none', paddingTop: '20px'}}>
|
|
|
{isVisibleCus &&
|
|
|
<Space style={{width: '100%'}} direction="vertical">
|
|
|
- <div style={{
|
|
|
- display: 'flex',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center'
|
|
|
- }}>
|
|
|
+ <div className='flex-center'>
|
|
|
<FormItem
|
|
|
label='Top-p'
|
|
|
name='topP'
|
|
|
- style={{width: '300px'}}
|
|
|
+ className='form-control-width'
|
|
|
>
|
|
|
<TopPDecimalStep/>
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
- <div style={{
|
|
|
- display: 'flex',
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center'
|
|
|
- }}>
|
|
|
+ <div className='flex-center'>
|
|
|
<FormItem
|
|
|
label='Temperature'
|
|
|
name='temperature'
|
|
|
- style={{width: '300px'}}
|
|
|
+ className='form-control-width'
|
|
|
>
|
|
|
<TempDecimalStep/>
|
|
|
</FormItem>
|
|
|
@@ -811,7 +832,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
name='param_desc'
|
|
|
rules={[{required: true, message: '回答风格不能为空'}]}>
|
|
|
<Radio.Group buttonStyle="solid"
|
|
|
- className='questionAnswerInfo-content-title'>
|
|
|
+ className='form-control-width'>
|
|
|
<Radio.Button onClick={() => {
|
|
|
handleRedioClick('strict')
|
|
|
}} value='strict'>严谨</Radio.Button>
|
|
|
@@ -840,7 +861,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
<FormItem
|
|
|
label='展示引用知识'
|
|
|
name='show_recall_result'
|
|
|
- className='questionAnswerInfo-content-title'>
|
|
|
+ className='form-control-width'>
|
|
|
<Switch onChange={onChangeShow}/>
|
|
|
</FormItem>
|
|
|
</div>
|
|
|
@@ -870,7 +891,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
justifyContent: 'center',
|
|
|
alignItems: 'center'
|
|
|
}}>
|
|
|
- <div className='questionAnswerInfo-content-title'>重排方式</div>
|
|
|
+ <div className='section-title'>重排方式</div>
|
|
|
</div>
|
|
|
<div style={{
|
|
|
display: 'flex',
|
|
|
@@ -881,7 +902,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
label='Rerank模型'
|
|
|
name='rerank_status'
|
|
|
valuePropName='checked'
|
|
|
- className='questionAnswerInfo-content-title'
|
|
|
+ className='form-control-width'
|
|
|
>
|
|
|
<Switch onChange={onChangeModel}/>
|
|
|
</FormItem>
|
|
|
@@ -897,7 +918,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
name='rerank_model_name'
|
|
|
>
|
|
|
<Select
|
|
|
- style={{width: '300px', height: '48px'}}
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
placeholder='请选择模型'
|
|
|
// defaultValue={'rerank'}
|
|
|
>
|
|
|
@@ -916,7 +937,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
name='slice_config_type'
|
|
|
rules={[{required: true, message: '召回方式不能为空'}]}>
|
|
|
<Select
|
|
|
- style={{width: '300px', height: '48px'}}
|
|
|
+ className='questionAnswerInfo-content-title'
|
|
|
placeholder='请选择'
|
|
|
onChange={onChangeCount}>
|
|
|
<Option value="fixed">手动设置</Option>
|
|
|
@@ -951,7 +972,7 @@ const QuestionAnswerInfo: React.FC = () => {
|
|
|
>
|
|
|
<TextArea
|
|
|
rows={4}
|
|
|
- className='questionAnswerInfo-content-title'
|
|
|
+ className='form-textarea-large'
|
|
|
placeholder="请输入内容"
|
|
|
/>
|
|
|
</FormItem>
|