DetailsCard.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { apiInterceptors, getAppStrategyValues } from '@/client/api';
  2. import MarkDownContext from '@/new-components/common/MarkdownContext';
  3. import { IResource } from '@/types/app';
  4. import { ExclamationCircleOutlined } from '@ant-design/icons';
  5. import { useRequest } from 'ahooks';
  6. import { Form, Modal, Select } from 'antd';
  7. import cls from 'classnames';
  8. import React, { useEffect, useMemo, useRef, useState } from 'react';
  9. import { useTranslation } from 'react-i18next';
  10. import { v4 as uuid } from 'uuid';
  11. import ResourcesCard from './ResourcesCard';
  12. type PromptSelectType = {
  13. promptList: Record<string, any>[];
  14. value?: string;
  15. onChange?: (value: string) => void;
  16. };
  17. // 自定义prompt控件
  18. const PromptSelect: React.FC<PromptSelectType> = ({ value, onChange, promptList }) => {
  19. const [showPrompt, setShowPrompt] = useState<boolean>(false);
  20. const [curPrompt, setCurPrompt] = useState<Record<string, any>>();
  21. const { t } = useTranslation();
  22. useEffect(() => {
  23. if (value) {
  24. const filterPrompt = promptList?.filter(item => item.prompt_code === value)[0];
  25. setCurPrompt(filterPrompt);
  26. }
  27. }, [promptList, value]);
  28. return (
  29. <div className='w-2/5 flex items-center gap-2'>
  30. <Select
  31. className='w-1/2'
  32. placeholder={t('please_select_prompt')}
  33. options={promptList}
  34. fieldNames={{ label: 'prompt_name', value: 'prompt_code' }}
  35. onChange={value => {
  36. const filterPrompt = promptList?.filter(item => item.prompt_code === value)[0];
  37. setCurPrompt(filterPrompt);
  38. onChange?.(value);
  39. }}
  40. value={value}
  41. allowClear
  42. showSearch
  43. />
  44. {curPrompt && (
  45. <span className='text-sm text-blue-500 cursor-pointer' onClick={() => setShowPrompt(true)}>
  46. <ExclamationCircleOutlined className='mr-1' />
  47. {t('View_details')}
  48. </span>
  49. )}
  50. <Modal
  51. title={`Prompt ${t('details')}`}
  52. open={showPrompt}
  53. footer={false}
  54. width={'60%'}
  55. onCancel={() => setShowPrompt(false)}
  56. >
  57. <MarkDownContext>{curPrompt?.content}</MarkDownContext>
  58. </Modal>
  59. </div>
  60. );
  61. };
  62. const DetailsCard: React.FC<{
  63. name: string;
  64. initValue: any;
  65. modelStrategyOptions: any[];
  66. resourceTypeOptions: Record<string, any>[];
  67. updateData: (data: any) => void;
  68. classNames?: string;
  69. promptList: Record<string, any>[];
  70. }> = ({ name, initValue, modelStrategyOptions, resourceTypeOptions, updateData, classNames, promptList }) => {
  71. const { t } = useTranslation();
  72. const [form] = Form.useForm();
  73. const promptTemplate = Form.useWatch('prompt_template', form);
  74. const strategy = Form.useWatch('llm_strategy', form);
  75. const strategyValue = Form.useWatch('llm_strategy_value', form);
  76. // const [curPrompt, setCurPrompt] = useState<Record<string, any>>();
  77. // const [showPrompt, setShowPrompt] = useState<boolean>(false);
  78. const initVal = useMemo(() => {
  79. return initValue?.find((item: any) => item.agent_name === name) || [];
  80. }, [initValue, name]);
  81. const resourcesRef = useRef<IResource[]>([]);
  82. // 获取模型策略参数列表
  83. const { run, loading, data } = useRequest(
  84. async () => {
  85. const [, res] = await apiInterceptors(getAppStrategyValues('priority'));
  86. return (
  87. res?.map(item => {
  88. return {
  89. label: item,
  90. value: item,
  91. };
  92. }) ?? []
  93. );
  94. },
  95. {
  96. manual: true,
  97. },
  98. );
  99. // 选择模型策略为priority获取参数
  100. useEffect(() => {
  101. if (strategy === 'priority') {
  102. run();
  103. }
  104. }, [run, strategy]);
  105. // 数据实时返回消费组件
  106. useEffect(() => {
  107. const rawVal = form.getFieldsValue();
  108. updateData({
  109. agent_name: name,
  110. ...rawVal,
  111. llm_strategy_value: rawVal?.llm_strategy_value?.join(','),
  112. resources: resourcesRef.current,
  113. });
  114. }, [form, loading, name, promptTemplate, strategy, strategyValue, updateData]);
  115. return (
  116. <div className={cls(classNames)}>
  117. <Form
  118. style={{ width: '100%' }}
  119. labelCol={{ span: 4 }}
  120. form={form}
  121. initialValues={{
  122. llm_strategy: 'default',
  123. ...initVal,
  124. llm_strategy_value: initVal?.llm_strategy_value?.split(','),
  125. }}
  126. >
  127. <Form.Item label={t('Prompt')} name='prompt_template'>
  128. <PromptSelect promptList={promptList} />
  129. </Form.Item>
  130. <Form.Item label={t('LLM_strategy')} required name='llm_strategy'>
  131. <Select
  132. className='w-1/5'
  133. placeholder={t('please_select_LLM_strategy')}
  134. options={modelStrategyOptions}
  135. allowClear
  136. />
  137. </Form.Item>
  138. {strategy === 'priority' && (
  139. <Form.Item label={t('LLM_strategy_value')} required name='llm_strategy_value'>
  140. <Select
  141. mode='multiple'
  142. className='w-2/5'
  143. placeholder={t('please_select_LLM_strategy_value')}
  144. options={data}
  145. allowClear
  146. />
  147. </Form.Item>
  148. )}
  149. <Form.Item label={t('available_resources')} name='resources'>
  150. <ResourcesCard
  151. resourceTypeOptions={resourceTypeOptions}
  152. initValue={initVal?.resources?.map((res: any) => {
  153. return {
  154. ...res,
  155. uid: uuid(),
  156. };
  157. })}
  158. updateData={data => {
  159. resourcesRef.current = data?.[1];
  160. updateData({
  161. agent_name: name,
  162. resources: resourcesRef.current,
  163. });
  164. }}
  165. name={name}
  166. />
  167. </Form.Item>
  168. </Form>
  169. </div>
  170. );
  171. };
  172. export default DetailsCard;