選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

prompt-engine.tsx 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import SimilaritySlider from '@/components/similarity-slider';
  2. import { DeleteOutlined, QuestionCircleOutlined } from '@ant-design/icons';
  3. import {
  4. Button,
  5. Col,
  6. Divider,
  7. Form,
  8. Input,
  9. Row,
  10. Switch,
  11. Table,
  12. TableProps,
  13. Tooltip,
  14. } from 'antd';
  15. import classNames from 'classnames';
  16. import {
  17. ForwardedRef,
  18. forwardRef,
  19. useEffect,
  20. useImperativeHandle,
  21. useState,
  22. } from 'react';
  23. import { v4 as uuid } from 'uuid';
  24. import {
  25. VariableTableDataType as DataType,
  26. IPromptConfigParameters,
  27. ISegmentedContentProps,
  28. } from '../interface';
  29. import { EditableCell, EditableRow } from './editable-cell';
  30. import Rerank from '@/components/rerank';
  31. import TopNItem from '@/components/top-n-item';
  32. import { useTranslate } from '@/hooks/common-hooks';
  33. import { useSelectPromptConfigParameters } from '../hooks';
  34. import styles from './index.less';
  35. const PromptEngine = (
  36. { show }: ISegmentedContentProps,
  37. ref: ForwardedRef<Array<IPromptConfigParameters>>,
  38. ) => {
  39. const [dataSource, setDataSource] = useState<DataType[]>([]);
  40. const parameters = useSelectPromptConfigParameters();
  41. const { t } = useTranslate('chat');
  42. const components = {
  43. body: {
  44. row: EditableRow,
  45. cell: EditableCell,
  46. },
  47. };
  48. const handleRemove = (key: string) => () => {
  49. const newData = dataSource.filter((item) => item.key !== key);
  50. setDataSource(newData);
  51. };
  52. const handleSave = (row: DataType) => {
  53. const newData = [...dataSource];
  54. const index = newData.findIndex((item) => row.key === item.key);
  55. const item = newData[index];
  56. newData.splice(index, 1, {
  57. ...item,
  58. ...row,
  59. });
  60. setDataSource(newData);
  61. };
  62. const handleAdd = () => {
  63. setDataSource((state) => [
  64. ...state,
  65. {
  66. key: uuid(),
  67. variable: '',
  68. optional: true,
  69. },
  70. ]);
  71. };
  72. const handleOptionalChange = (row: DataType) => (checked: boolean) => {
  73. const newData = [...dataSource];
  74. const index = newData.findIndex((item) => row.key === item.key);
  75. const item = newData[index];
  76. newData.splice(index, 1, {
  77. ...item,
  78. optional: checked,
  79. });
  80. setDataSource(newData);
  81. };
  82. useImperativeHandle(
  83. ref,
  84. () => {
  85. return dataSource
  86. .filter((x) => x.variable.trim() !== '')
  87. .map((x) => ({ key: x.variable, optional: x.optional }));
  88. },
  89. [dataSource],
  90. );
  91. const columns: TableProps<DataType>['columns'] = [
  92. {
  93. title: t('key'),
  94. dataIndex: 'variable',
  95. key: 'variable',
  96. onCell: (record: DataType) => ({
  97. record,
  98. editable: true,
  99. dataIndex: 'variable',
  100. title: 'key',
  101. handleSave,
  102. }),
  103. },
  104. {
  105. title: t('optional'),
  106. dataIndex: 'optional',
  107. key: 'optional',
  108. width: 40,
  109. align: 'center',
  110. render(text, record) {
  111. return (
  112. <Switch
  113. size="small"
  114. checked={text}
  115. onChange={handleOptionalChange(record)}
  116. />
  117. );
  118. },
  119. },
  120. {
  121. title: t('operation'),
  122. dataIndex: 'operation',
  123. width: 30,
  124. key: 'operation',
  125. align: 'center',
  126. render(_, record) {
  127. return <DeleteOutlined onClick={handleRemove(record.key)} />;
  128. },
  129. },
  130. ];
  131. useEffect(() => {
  132. setDataSource(parameters);
  133. }, [parameters]);
  134. return (
  135. <section
  136. className={classNames({
  137. [styles.segmentedHidden]: !show,
  138. })}
  139. >
  140. <Form.Item
  141. label={t('system')}
  142. rules={[{ required: true, message: t('systemMessage') }]}
  143. tooltip={t('systemTip')}
  144. name={['prompt_config', 'system']}
  145. initialValue={t('systemInitialValue')}
  146. >
  147. <Input.TextArea autoSize={{ maxRows: 8, minRows: 5 }} />
  148. </Form.Item>
  149. <Divider></Divider>
  150. <SimilaritySlider isTooltipShown></SimilaritySlider>
  151. <TopNItem></TopNItem>
  152. <Form.Item
  153. label={t('multiTurn')}
  154. tooltip={t('multiTurnTip')}
  155. name={['prompt_config', 'refine_multiturn']}
  156. initialValue={true}
  157. >
  158. <Switch></Switch>
  159. </Form.Item>
  160. <Rerank></Rerank>
  161. <section className={classNames(styles.variableContainer)}>
  162. <Row align={'middle'} justify="end">
  163. <Col span={9} className={styles.variableAlign}>
  164. <label className={styles.variableLabel}>
  165. {t('variable')}
  166. <Tooltip title={t('variableTip')}>
  167. <QuestionCircleOutlined className={styles.variableIcon} />
  168. </Tooltip>
  169. </label>
  170. </Col>
  171. <Col span={15} className={styles.variableAlign}>
  172. <Button size="small" onClick={handleAdd}>
  173. {t('add')}
  174. </Button>
  175. </Col>
  176. </Row>
  177. {dataSource.length > 0 && (
  178. <Row>
  179. <Col span={7}> </Col>
  180. <Col span={17}>
  181. <Table
  182. dataSource={dataSource}
  183. columns={columns}
  184. rowKey={'key'}
  185. className={styles.variableTable}
  186. components={components}
  187. rowClassName={() => styles.editableRow}
  188. />
  189. </Col>
  190. </Row>
  191. )}
  192. </section>
  193. </section>
  194. );
  195. };
  196. export default forwardRef(PromptEngine);