From 32349481ef4da339fbeb2e246da71eb6eda185c4 Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 19 Aug 2025 09:40:01 +0800 Subject: [PATCH] Feat: Allow agent operators to select speech-to-text models #3221 (#9534) ### What problem does this PR solve? Feat: Allow agent operators to select speech-to-text models #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/components/large-model-form-field.tsx | 9 +++++--- web/src/components/llm-select/next.tsx | 8 +++---- web/src/components/message-item/index.less | 2 +- web/src/components/message-item/index.tsx | 8 ++++--- web/src/hooks/logic-hooks.ts | 22 +++++++++++------- web/src/locales/en.ts | 3 +++ web/src/locales/zh.ts | 2 ++ web/src/pages/agent/form/agent-form/index.tsx | 2 +- .../chat/app-settings/chat-settings.tsx | 23 +++++++++++-------- .../chat/chat-box/single-chat-box.tsx | 6 ++--- web/src/pages/next-chats/chat/index.tsx | 2 +- web/src/pages/next-chats/chat/sessions.tsx | 5 +++- 12 files changed, 57 insertions(+), 35 deletions(-) diff --git a/web/src/components/large-model-form-field.tsx b/web/src/components/large-model-form-field.tsx index d81229cb2..b8322e043 100644 --- a/web/src/components/large-model-form-field.tsx +++ b/web/src/components/large-model-form-field.tsx @@ -38,9 +38,12 @@ export const LargeModelFilterFormSchema = { llm_filter: z.string().optional(), }; -type LargeModelFormFieldProps = Pick; +type LargeModelFormFieldProps = Pick< + NextInnerLLMSelectProps, + 'showSpeech2TextModel' +>; export function LargeModelFormField({ - showTTSModel, + showSpeech2TextModel: showTTSModel, }: LargeModelFormFieldProps) { const form = useFormContext(); const { t } = useTranslation(); @@ -91,7 +94,7 @@ export function LargeModelFormField({ diff --git a/web/src/components/llm-select/next.tsx b/web/src/components/llm-select/next.tsx index 935af5df9..6c5e25724 100644 --- a/web/src/components/llm-select/next.tsx +++ b/web/src/components/llm-select/next.tsx @@ -13,18 +13,18 @@ export interface NextInnerLLMSelectProps { onChange?: (value: string) => void; disabled?: boolean; filter?: string; - showTTSModel?: boolean; + showSpeech2TextModel?: boolean; } const NextInnerLLMSelect = forwardRef< React.ElementRef, NextInnerLLMSelectProps ->(({ value, disabled, filter, showTTSModel = false }, ref) => { +>(({ value, disabled, filter, showSpeech2TextModel = false }, ref) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const ttsModel = useMemo(() => { - return showTTSModel ? [LlmModelType.TTS] : []; - }, [showTTSModel]); + return showSpeech2TextModel ? [LlmModelType.Speech2text] : []; + }, [showSpeech2TextModel]); const modelTypes = useMemo(() => { if (filter === LlmModelType.Chat) { diff --git a/web/src/components/message-item/index.less b/web/src/components/message-item/index.less index a4812bd61..3d36d7ca8 100644 --- a/web/src/components/message-item/index.less +++ b/web/src/components/message-item/index.less @@ -24,7 +24,7 @@ .messageText { .chunkText(); .messageTextBase(); - background-color: #e6f4ff; + // background-color: #e6f4ff; word-break: break-word; } .messageTextDark { diff --git a/web/src/components/message-item/index.tsx b/web/src/components/message-item/index.tsx index 936eba59f..6a9432465 100644 --- a/web/src/components/message-item/index.tsx +++ b/web/src/components/message-item/index.tsx @@ -9,6 +9,7 @@ import { useFetchDocumentThumbnailsByIds, } from '@/hooks/document-hooks'; import { IRegenerateMessage, IRemoveMessageById } from '@/hooks/logic-hooks'; +import { cn } from '@/lib/utils'; import { IMessage } from '@/pages/chat/interface'; import MarkdownContent from '@/pages/chat/markdown-content'; import { Avatar, Flex, Space } from 'antd'; @@ -129,13 +130,14 @@ const MessageItem = ({ {/* {isAssistant ? '' : nickname} */}
container.removeEventListener('scroll', handleScroll); }, [containerRef, checkIfUserAtBottom]); + // Imperative scroll function + const scrollToBottom = useCallback(() => { + if (containerRef?.current) { + const container = containerRef.current; + container.scrollTo({ + top: container.scrollHeight - container.clientHeight, + behavior: 'smooth', + }); + } + }, [containerRef]); + useEffect(() => { if (!messages) return; if (!containerRef?.current) return; requestAnimationFrame(() => { setTimeout(() => { if (isAtBottomRef.current) { - ref.current?.scrollIntoView({ behavior: 'smooth' }); + scrollToBottom(); } - }, 30); + }, 100); }); - }, [messages, containerRef]); - - // Imperative scroll function - const scrollToBottom = useCallback(() => { - ref.current?.scrollIntoView({ behavior: 'smooth' }); - }, []); + }, [messages, containerRef, scrollToBottom]); return { scrollRef: ref, isAtBottom, scrollToBottom }; }; diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 3e855bdae..72d43f655 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -5,6 +5,7 @@ export default { deleteModalTitle: 'Are you sure to delete this item?', ok: 'Yes', cancel: 'No', + no: 'No', total: 'Total', rename: 'Rename', name: 'Name', @@ -575,6 +576,8 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s automatic: 'Automatic', manual: 'Manual', }, + cancel: 'Cancel', + chatSetting: 'Chat setting', }, setting: { profile: 'Profile', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 0aa38a7e6..da53c5209 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -569,6 +569,8 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 automatic: '自动', manual: '手动', }, + cancel: '取消', + chatSetting: '聊天设置', }, setting: { profile: '概要', diff --git a/web/src/pages/agent/form/agent-form/index.tsx b/web/src/pages/agent/form/agent-form/index.tsx index 089f4e5f5..2a9a9a42f 100644 --- a/web/src/pages/agent/form/agent-form/index.tsx +++ b/web/src/pages/agent/form/agent-form/index.tsx @@ -128,7 +128,7 @@ function AgentForm({ node }: INextOperatorForm) { {isSubAgent && } - + {findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && ( ; @@ -89,25 +91,26 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) { return (
- Chat Settings + {t('chat.chatSetting')}
-
+
- - Update - +
+ + + {t('common.save')} + +
diff --git a/web/src/pages/next-chats/chat/chat-box/single-chat-box.tsx b/web/src/pages/next-chats/chat/chat-box/single-chat-box.tsx index 6b0a10b28..de6406a67 100644 --- a/web/src/pages/next-chats/chat/chat-box/single-chat-box.tsx +++ b/web/src/pages/next-chats/chat/chat-box/single-chat-box.tsx @@ -23,7 +23,7 @@ interface IProps { export function SingleChatBox({ controller }: IProps) { const { value, - // scrollRef, + scrollRef, messageContainerRef, sendLoading, derivedMessages, @@ -47,7 +47,7 @@ export function SingleChatBox({ controller }: IProps) { return (
-
+
{derivedMessages?.map((message, i) => { return ( - {/*
*/} +
-
+
- Chat Settings + {t('chat.chatSetting')}