You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import { Collapse } from '@/components/collapse';
  2. import { FormContainer } from '@/components/form-container';
  3. import {
  4. LargeModelFilterFormSchema,
  5. LargeModelFormField,
  6. } from '@/components/large-model-form-field';
  7. import { LlmSettingSchema } from '@/components/llm-setting-items/next';
  8. import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item';
  9. import { SelectWithSearch } from '@/components/originui/select-with-search';
  10. import {
  11. Form,
  12. FormControl,
  13. FormField,
  14. FormItem,
  15. FormLabel,
  16. } from '@/components/ui/form';
  17. import { Input, NumberInput } from '@/components/ui/input';
  18. import { Switch } from '@/components/ui/switch';
  19. import { LlmModelType } from '@/constants/knowledge';
  20. import { useFindLlmByUuid } from '@/hooks/use-llm-request';
  21. import { zodResolver } from '@hookform/resolvers/zod';
  22. import { memo, useEffect, useMemo } from 'react';
  23. import { useForm, useWatch } from 'react-hook-form';
  24. import { useTranslation } from 'react-i18next';
  25. import { z } from 'zod';
  26. import {
  27. AgentExceptionMethod,
  28. NodeHandleId,
  29. VariableType,
  30. initialAgentValues,
  31. } from '../../constant';
  32. import { INextOperatorForm } from '../../interface';
  33. import useGraphStore from '../../store';
  34. import { isBottomSubAgent } from '../../utils';
  35. import { buildOutputList } from '../../utils/build-output-list';
  36. import { DescriptionField } from '../components/description-field';
  37. import { FormWrapper } from '../components/form-wrapper';
  38. import { Output } from '../components/output';
  39. import { PromptEditor } from '../components/prompt-editor';
  40. import { QueryVariable } from '../components/query-variable';
  41. import { AgentTools, Agents } from './agent-tools';
  42. import { useValues } from './use-values';
  43. import { useWatchFormChange } from './use-watch-change';
  44. const FormSchema = z.object({
  45. sys_prompt: z.string(),
  46. description: z.string().optional(),
  47. user_prompt: z.string().optional(),
  48. prompts: z.string().optional(),
  49. // prompts: z
  50. // .array(
  51. // z.object({
  52. // role: z.string(),
  53. // content: z.string(),
  54. // }),
  55. // )
  56. // .optional(),
  57. message_history_window_size: z.coerce.number(),
  58. tools: z
  59. .array(
  60. z.object({
  61. component_name: z.string(),
  62. }),
  63. )
  64. .optional(),
  65. ...LlmSettingSchema,
  66. max_retries: z.coerce.number(),
  67. delay_after_error: z.coerce.number().optional(),
  68. visual_files_var: z.string().optional(),
  69. max_rounds: z.coerce.number().optional(),
  70. exception_method: z.string().optional(),
  71. exception_goto: z.array(z.string()).optional(),
  72. exception_default_value: z.string().optional(),
  73. ...LargeModelFilterFormSchema,
  74. cite: z.boolean().optional(),
  75. });
  76. const outputList = buildOutputList(initialAgentValues.outputs);
  77. function AgentForm({ node }: INextOperatorForm) {
  78. const { t } = useTranslation();
  79. const { edges, deleteEdgesBySourceAndSourceHandle } = useGraphStore(
  80. (state) => state,
  81. );
  82. const defaultValues = useValues(node);
  83. const ExceptionMethodOptions = Object.values(AgentExceptionMethod).map(
  84. (x) => ({
  85. label: t(`flow.${x}`),
  86. value: x,
  87. }),
  88. );
  89. const isSubAgent = useMemo(() => {
  90. return isBottomSubAgent(edges, node?.id);
  91. }, [edges, node?.id]);
  92. const form = useForm<z.infer<typeof FormSchema>>({
  93. defaultValues: defaultValues,
  94. resolver: zodResolver(FormSchema),
  95. });
  96. const llmId = useWatch({ control: form.control, name: 'llm_id' });
  97. const findLlmByUuid = useFindLlmByUuid();
  98. const exceptionMethod = useWatch({
  99. control: form.control,
  100. name: 'exception_method',
  101. });
  102. useEffect(() => {
  103. if (exceptionMethod !== AgentExceptionMethod.Goto) {
  104. if (node?.id) {
  105. deleteEdgesBySourceAndSourceHandle(
  106. node?.id,
  107. NodeHandleId.AgentException,
  108. );
  109. }
  110. }
  111. }, [deleteEdgesBySourceAndSourceHandle, exceptionMethod, node?.id]);
  112. useWatchFormChange(node?.id, form);
  113. return (
  114. <Form {...form}>
  115. <FormWrapper>
  116. <FormContainer>
  117. {isSubAgent && <DescriptionField></DescriptionField>}
  118. <LargeModelFormField></LargeModelFormField>
  119. {findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && (
  120. <QueryVariable
  121. name="visual_files_var"
  122. label="Visual Input File"
  123. type={VariableType.File}
  124. ></QueryVariable>
  125. )}
  126. </FormContainer>
  127. <FormContainer>
  128. <FormField
  129. control={form.control}
  130. name={`sys_prompt`}
  131. render={({ field }) => (
  132. <FormItem className="flex-1">
  133. <FormLabel>System Prompt</FormLabel>
  134. <FormControl>
  135. <PromptEditor
  136. {...field}
  137. placeholder={t('flow.messagePlaceholder')}
  138. showToolbar={false}
  139. ></PromptEditor>
  140. </FormControl>
  141. </FormItem>
  142. )}
  143. />
  144. </FormContainer>
  145. {isSubAgent || (
  146. <FormContainer>
  147. {/* <DynamicPrompt></DynamicPrompt> */}
  148. <FormField
  149. control={form.control}
  150. name={`prompts`}
  151. render={({ field }) => (
  152. <FormItem className="flex-1">
  153. <FormLabel>User Prompt</FormLabel>
  154. <FormControl>
  155. <section>
  156. <PromptEditor
  157. {...field}
  158. showToolbar={false}
  159. ></PromptEditor>
  160. </section>
  161. </FormControl>
  162. </FormItem>
  163. )}
  164. />
  165. </FormContainer>
  166. )}
  167. <FormContainer>
  168. <AgentTools></AgentTools>
  169. <Agents node={node}></Agents>
  170. </FormContainer>
  171. <Collapse title={<div>Advanced Settings</div>}>
  172. <FormContainer>
  173. <MessageHistoryWindowSizeFormField></MessageHistoryWindowSizeFormField>
  174. <FormField
  175. control={form.control}
  176. name={`cite`}
  177. render={({ field }) => (
  178. <FormItem className="flex-1">
  179. <FormLabel tooltip={t('flow.citeTip')}>
  180. {t('flow.cite')}
  181. </FormLabel>
  182. <FormControl>
  183. <Switch
  184. checked={field.value}
  185. onCheckedChange={field.onChange}
  186. ></Switch>
  187. </FormControl>
  188. </FormItem>
  189. )}
  190. />
  191. <FormField
  192. control={form.control}
  193. name={`max_retries`}
  194. render={({ field }) => (
  195. <FormItem className="flex-1">
  196. <FormLabel>Max retries</FormLabel>
  197. <FormControl>
  198. <NumberInput {...field} max={8}></NumberInput>
  199. </FormControl>
  200. </FormItem>
  201. )}
  202. />
  203. <FormField
  204. control={form.control}
  205. name={`delay_after_error`}
  206. render={({ field }) => (
  207. <FormItem className="flex-1">
  208. <FormLabel>Delay after error</FormLabel>
  209. <FormControl>
  210. <NumberInput {...field} max={5} step={0.1}></NumberInput>
  211. </FormControl>
  212. </FormItem>
  213. )}
  214. />
  215. <FormField
  216. control={form.control}
  217. name={`max_rounds`}
  218. render={({ field }) => (
  219. <FormItem className="flex-1">
  220. <FormLabel>Max rounds</FormLabel>
  221. <FormControl>
  222. <NumberInput {...field}></NumberInput>
  223. </FormControl>
  224. </FormItem>
  225. )}
  226. />
  227. <FormField
  228. control={form.control}
  229. name={`exception_method`}
  230. render={({ field }) => (
  231. <FormItem className="flex-1">
  232. <FormLabel>Exception method</FormLabel>
  233. <FormControl>
  234. <SelectWithSearch
  235. {...field}
  236. options={ExceptionMethodOptions}
  237. allowClear
  238. />
  239. </FormControl>
  240. </FormItem>
  241. )}
  242. />
  243. {exceptionMethod === AgentExceptionMethod.Comment && (
  244. <FormField
  245. control={form.control}
  246. name={`exception_default_value`}
  247. render={({ field }) => (
  248. <FormItem className="flex-1">
  249. <FormLabel>Exception default value</FormLabel>
  250. <FormControl>
  251. <Input {...field} />
  252. </FormControl>
  253. </FormItem>
  254. )}
  255. />
  256. )}
  257. </FormContainer>
  258. </Collapse>
  259. <Output list={outputList}></Output>
  260. </FormWrapper>
  261. </Form>
  262. );
  263. }
  264. export default memo(AgentForm);