diff --git a/react/src/components/lablupTalkativotUI/ChatUIModal.tsx b/react/src/components/lablupTalkativotUI/ChatUIModal.tsx index 9387de53c..4ee1e5286 100644 --- a/react/src/components/lablupTalkativotUI/ChatUIModal.tsx +++ b/react/src/components/lablupTalkativotUI/ChatUIModal.tsx @@ -1,25 +1,29 @@ import { useTanQuery } from '../../hooks/reactQueryAlias'; import Flex from '../Flex'; import LLMChatCard from './LLMChatCard'; +import { ChatUIModalFragment$key } from './__generated__/ChatUIModalFragment.graphql'; import { Alert, Modal, ModalProps, Skeleton, theme } from 'antd'; +import graphql from 'babel-plugin-relay/macro'; import _ from 'lodash'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useFragment } from 'react-relay'; interface ChatUIBasicProps { - endpoint?: string; + endpointFrgmt: ChatUIModalFragment$key | null | undefined; basePath?: string; // models?: GetProp; } interface ChatUIModalProps extends ModalProps, ChatUIBasicProps {} const ChatUIModal: React.FC = ({ + endpointFrgmt = null, basePath, - endpoint, // models, ...props }) => { const { token } = theme.useToken(); + return ( = ({ style={{ maxWidth: token.screenLGMax }} > - + ); }; const EndpointChatContent: React.FC = ({ + endpointFrgmt, basePath = 'v1', - endpoint, }) => { const { t } = useTranslation(); + const endpoint = useFragment( + graphql` + fragment ChatUIModalFragment on Endpoint { + endpoint_id + url + } + `, + endpointFrgmt, + ); const { data: modelsResult, // error, @@ -56,11 +72,11 @@ const EndpointChatContent: React.FC = ({ } = useTanQuery<{ data: Array; }>({ - queryKey: ['models', endpoint], + queryKey: ['models', endpoint?.url], queryFn: () => { - return fetch(new URL(basePath + '/models', endpoint).toString()).then( - (res) => res.json(), - ); + return fetch( + new URL(basePath + '/models', endpoint?.url || '').toString(), + ).then((res) => res.json()); }, }); @@ -68,7 +84,8 @@ const EndpointChatContent: React.FC = ({ ) : ( ({ id: m.id, name: m.id, diff --git a/react/src/components/lablupTalkativotUI/EndpointLLMChatCard.tsx b/react/src/components/lablupTalkativotUI/EndpointLLMChatCard.tsx index 49b4ab258..db716d1e1 100644 --- a/react/src/components/lablupTalkativotUI/EndpointLLMChatCard.tsx +++ b/react/src/components/lablupTalkativotUI/EndpointLLMChatCard.tsx @@ -20,6 +20,7 @@ const chatSubmitKeyInfoState = atom<{ id: string; key: string } | undefined>( interface EndpointLLMChatCardProps extends CardProps { basePath?: string; closable?: boolean; + defaultModelId?: string; defaultEndpoint?: EndpointLLMChatCard_endpoint$key; fetchKey?: string; isSynchronous?: boolean; @@ -30,6 +31,7 @@ interface EndpointLLMChatCardProps extends CardProps { const EndpointLLMChatCard: React.FC = ({ basePath = 'v1', closable, + defaultModelId, defaultEndpoint, fetchKey, isSynchronous, @@ -118,7 +120,12 @@ const EndpointLLMChatCard: React.FC = ({ popupMatchSelectWidth={false} /> } - modelId={modelsResult?.data?.[0]?.id ?? 'custom'} + modelId={ + defaultModelId && + _.includes(_.map(modelsResult?.data, 'id'), defaultModelId) + ? defaultModelId + : (modelsResult?.data?.[0]?.id ?? 'custom') + } extra={ closable ? ( ; modelId?: string; agentId?: string; + endpointId?: string; baseURL?: string; apiKey?: string; headers?: Record | Headers; @@ -57,6 +60,7 @@ export interface LLMChatCardProps extends CardProps { const LLMChatCard: React.FC = ({ models = [], + endpointId, baseURL, headers, credentials, @@ -71,6 +75,8 @@ const LLMChatCard: React.FC = ({ onSubmitChange, ...cardProps }) => { + const webuiNavigate = useWebUINavigate(); + const [modelId, setModelId] = useControllableValue(cardProps, { valuePropName: 'modelId', trigger: 'onModelChange', @@ -157,6 +163,19 @@ const LLMChatCard: React.FC = ({ }, [submitKey]); const items: MenuProps['items'] = [ + { + key: 'compare', + label: t('chatui.CompareWithOtherModels'), + icon: , + onClick: () => { + webuiNavigate( + `/serving?tab=chatting&endpointId=${endpointId}&modelId=${modelId}`, + ); + }, + }, + { + type: 'divider', + }, { key: 'clear', danger: true, diff --git a/react/src/components/lablupTalkativotUI/LLMPlaygroundPage.tsx b/react/src/components/lablupTalkativotUI/LLMPlaygroundPage.tsx index 8e99c9fe8..c99a5bedf 100644 --- a/react/src/components/lablupTalkativotUI/LLMPlaygroundPage.tsx +++ b/react/src/components/lablupTalkativotUI/LLMPlaygroundPage.tsx @@ -9,6 +9,7 @@ import _ from 'lodash'; import React, { Suspense, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLazyLoadQuery } from 'react-relay'; +import { StringParam, useQueryParam } from 'use-query-params'; interface LLMPlaygroundPageProps {} @@ -20,9 +21,20 @@ const LLMPlaygroundPage: React.FC = ({ ...props }) => { const [isSynchronous, setSynchronous] = useState(false); - const { endpoint_list } = useLazyLoadQuery( + const [endpointId] = useQueryParam('endpointId', StringParam); + const [modelId] = useQueryParam('modelId', StringParam); + const isEmptyEndpointId = !endpointId; + + const { endpoint, endpoint_list } = useLazyLoadQuery( graphql` - query LLMPlaygroundPageQuery { + query LLMPlaygroundPageQuery( + $endpointId: UUID! + $isEmptyEndpointId: Boolean! + ) { + endpoint(endpoint_id: $endpointId) + @skipOnClient(if: $isEmptyEndpointId) { + ...EndpointLLMChatCard_endpoint + } endpoint_list(limit: 1, offset: 0) { items { ...EndpointLLMChatCard_endpoint @@ -30,7 +42,10 @@ const LLMPlaygroundPage: React.FC = ({ ...props }) => { } } `, - {}, + { + endpointId: endpointId || '', + isEmptyEndpointId: isEmptyEndpointId, + }, ); return ( <> @@ -96,7 +111,14 @@ const LLMPlaygroundPage: React.FC = ({ ...props }) => { key={getKey(index)} > { diff --git a/react/src/pages/EndpointDetailPage.tsx b/react/src/pages/EndpointDetailPage.tsx index 0f4c5f4f7..e22cf1dff 100644 --- a/react/src/pages/EndpointDetailPage.tsx +++ b/react/src/pages/EndpointDetailPage.tsx @@ -182,6 +182,7 @@ const EndpointDetailPage: React.FC = () => { created_user_email @since(version: "23.09.8") ...EndpointOwnerInfoFragment ...EndpointStatusTagFragment + ...ChatUIModalFragment } endpoint_token_list( offset: $tokenListOffset @@ -705,7 +706,7 @@ const EndpointDetailPage: React.FC = () => { endpoint_id={endpoint?.endpoint_id || ''} > { setOpenChatModal(false); diff --git a/resources/i18n/de.json b/resources/i18n/de.json index 169c6abe3..ab434cd33 100644 --- a/resources/i18n/de.json +++ b/resources/i18n/de.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Chatsitzung löschen", "DeleteChattingSessionDescription": "Sie sind dabei, dieses Thema zu löschen. \nEinmal gelöscht, kann es nicht wiederhergestellt werden. \nBitte gehen Sie vorsichtig vor.", "SelectEndpoint": "Wählen Sie Endpunkt aus", - "SyncInput": "Eingang synchronisieren" + "SyncInput": "Eingang synchronisieren", + "CompareWithOtherModels": "Vergleichen Sie mit anderen Modellen" } } diff --git a/resources/i18n/el.json b/resources/i18n/el.json index c8fe4c54f..f7fb6d467 100644 --- a/resources/i18n/el.json +++ b/resources/i18n/el.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Διαγραφή συνεδρίας συνομιλίας", "DeleteChattingSessionDescription": "Πρόκειται να διαγράψετε αυτό το θέμα. \nΑφού διαγραφεί, δεν μπορεί να ανακτηθεί. \nΠαρακαλούμε προχωρήστε με προσοχή.", "SelectEndpoint": "Επιλέξτε Τελικό σημείο", - "SyncInput": "Συγχρονισμός εισόδου" + "SyncInput": "Συγχρονισμός εισόδου", + "CompareWithOtherModels": "Συγκρίνετε με άλλα μοντέλα" } } diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 9268d6b11..3f8b25dbd 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -1710,6 +1710,7 @@ "DeleteChatSession": "", "DeleteChattingSession": "Delete chatting session", "DeleteChattingSessionDescription": "You are about to delete this topic. Once deleted, it cannot be recovered. Please proceed with caution.", - "SyncInput": "Sync input" + "SyncInput": "Sync input", + "CompareWithOtherModels": "Compare with other models" } } diff --git a/resources/i18n/es.json b/resources/i18n/es.json index 72a9ede9b..0f9f09fa8 100644 --- a/resources/i18n/es.json +++ b/resources/i18n/es.json @@ -1709,6 +1709,7 @@ "DeleteChattingSession": "Eliminar sesión de chat", "DeleteChattingSessionDescription": "Estás a punto de eliminar este tema. \nUna vez eliminado, no se puede recuperar. \nProceda con precaución.", "SelectEndpoint": "Seleccionar punto final", - "SyncInput": "Entrada de sincronización" + "SyncInput": "Entrada de sincronización", + "CompareWithOtherModels": "Comparar con otros modelos" } } diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json index 8dfd0e711..a5cbb0ca9 100644 --- a/resources/i18n/fi.json +++ b/resources/i18n/fi.json @@ -1705,6 +1705,7 @@ "DeleteChattingSessionDescription": "Olet poistamassa tätä aihetta. \nKun se on poistettu, sitä ei voi palauttaa. \nOle hyvä ja jatka varoen.", "DeleteChatHistory": "Poista keskusteluhistoria", "SelectModel": "Valitse Malli", - "SyncInput": "Synkronoi sisääntulo" + "SyncInput": "Synkronoi sisääntulo", + "CompareWithOtherModels": "Vertaa muihin malleihin" } } diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json index 7e8024d3d..dbe747c5d 100644 --- a/resources/i18n/fr.json +++ b/resources/i18n/fr.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Supprimer la session de discussion", "DeleteChattingSessionDescription": "Vous êtes sur le point de supprimer ce sujet. \nUne fois supprimé, il ne peut pas être récupéré. \nVeuillez procéder avec prudence.", "SelectEndpoint": "Sélectionnez le point de terminaison", - "SyncInput": "Entrée de synchronisation" + "SyncInput": "Entrée de synchronisation", + "CompareWithOtherModels": "Comparez avec d'autres modèles" } } diff --git a/resources/i18n/id.json b/resources/i18n/id.json index 295fc7a75..91145d192 100644 --- a/resources/i18n/id.json +++ b/resources/i18n/id.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Hapus sesi obrolan", "DeleteChattingSessionDescription": "Anda akan menghapus topik ini. \nSetelah dihapus, itu tidak dapat dipulihkan. \nSilakan lanjutkan dengan hati-hati.", "SelectEndpoint": "Pilih Titik Akhir", - "SyncInput": "Sinkronkan masukan" + "SyncInput": "Sinkronkan masukan", + "CompareWithOtherModels": "Bandingkan dengan model lain" } } diff --git a/resources/i18n/it.json b/resources/i18n/it.json index 176df16ef..c10b6150e 100644 --- a/resources/i18n/it.json +++ b/resources/i18n/it.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Elimina la sessione di chat", "DeleteChattingSessionDescription": "Stai per eliminare questo argomento. \nUna volta eliminato, non può essere recuperato. \nSi prega di procedere con cautela.", "SelectEndpoint": "Seleziona punto finale", - "SyncInput": "Ingresso sincronizzato" + "SyncInput": "Ingresso sincronizzato", + "CompareWithOtherModels": "Confronta con altri modelli" } } diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json index daa555f70..3242f6338 100644 --- a/resources/i18n/ja.json +++ b/resources/i18n/ja.json @@ -1706,6 +1706,7 @@ "DeleteChattingSession": "チャットセッションを削除する", "DeleteChattingSessionDescription": "このトピックを削除しようとしています。\n一度削除すると復元することはできません。\n慎重に進めてください。", "SelectEndpoint": "エンドポイントの選択", - "SyncInput": "同期入力" + "SyncInput": "同期入力", + "CompareWithOtherModels": "他モデルとの比較" } } diff --git a/resources/i18n/ko.json b/resources/i18n/ko.json index 94206f42c..47d78d605 100644 --- a/resources/i18n/ko.json +++ b/resources/i18n/ko.json @@ -1709,6 +1709,7 @@ "DeleteChattingSession": "채팅 세션 삭제", "DeleteChattingSessionDescription": "이 주제를 삭제하려고 합니다. \n삭제한 후에는 복구할 수 없습니다. \n주의해서 진행하시기 바랍니다.", "SelectEndpoint": "엔드포인트 선택", - "SyncInput": "입력 연동" + "SyncInput": "입력 연동", + "CompareWithOtherModels": "다른 모델과 비교하기" } } diff --git a/resources/i18n/mn.json b/resources/i18n/mn.json index e668faa40..5cc83e7e1 100644 --- a/resources/i18n/mn.json +++ b/resources/i18n/mn.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Чатлах сессийг устгах", "DeleteChattingSessionDescription": "Та энэ сэдвийг устгах гэж байна. \nУстгасны дараа сэргээх боломжгүй. \nБолгоомжтой үргэлжлүүлнэ үү.", "SelectEndpoint": "Төгсгөлийн цэгийг сонгоно уу", - "SyncInput": "Синкийн оролт" + "SyncInput": "Синкийн оролт", + "CompareWithOtherModels": "Бусад загваруудтай харьцуул" } } diff --git a/resources/i18n/ms.json b/resources/i18n/ms.json index 3ee7a7520..c5238e7cf 100644 --- a/resources/i18n/ms.json +++ b/resources/i18n/ms.json @@ -1706,6 +1706,7 @@ "DeleteChattingSession": "Padamkan sesi berbual", "DeleteChattingSessionDescription": "Anda akan memadamkan topik ini. \nSetelah dipadam, ia tidak boleh dipulihkan. \nSila teruskan dengan berhati-hati.", "SelectEndpoint": "Pilih Titik Akhir", - "SyncInput": "Input penyegerakan" + "SyncInput": "Input penyegerakan", + "CompareWithOtherModels": "Bandingkan dengan model lain" } } diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json index 4d31922f8..f3b73d731 100644 --- a/resources/i18n/pl.json +++ b/resources/i18n/pl.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Usuń sesję czatu", "DeleteChattingSessionDescription": "Zamierzasz usunąć ten temat. \nRaz usuniętego nie można odzyskać. \nProszę postępować ostrożnie.", "SelectEndpoint": "Wybierz Punkt końcowy", - "SyncInput": "Synchronizuj wejście" + "SyncInput": "Synchronizuj wejście", + "CompareWithOtherModels": "Porównaj z innymi modelami" } } diff --git a/resources/i18n/pt-BR.json b/resources/i18n/pt-BR.json index f903be097..d72e0a7d8 100644 --- a/resources/i18n/pt-BR.json +++ b/resources/i18n/pt-BR.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Excluir sessão de bate-papo", "DeleteChattingSessionDescription": "Você está prestes a excluir este tópico. \nUma vez excluído, ele não pode ser recuperado. \nPor favor, proceda com cautela.", "SelectEndpoint": "Selecione o ponto final", - "SyncInput": "Entrada de sincronização" + "SyncInput": "Entrada de sincronização", + "CompareWithOtherModels": "Compare com outros modelos" } } diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json index 269e02935..74b8857f7 100644 --- a/resources/i18n/pt.json +++ b/resources/i18n/pt.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Excluir sessão de bate-papo", "DeleteChattingSessionDescription": "Você está prestes a excluir este tópico. \nUma vez excluído, ele não pode ser recuperado. \nPor favor, proceda com cautela.", "SelectEndpoint": "Selecione o ponto final", - "SyncInput": "Entrada de sincronização" + "SyncInput": "Entrada de sincronização", + "CompareWithOtherModels": "Compare com outros modelos" } } diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json index afb5ba658..8197b82cc 100644 --- a/resources/i18n/ru.json +++ b/resources/i18n/ru.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Удалить сеанс чата", "DeleteChattingSessionDescription": "Вы собираетесь удалить эту тему. \nПосле удаления его невозможно восстановить. \nПожалуйста, действуйте осторожно.", "SelectEndpoint": "Выберите конечную точку", - "SyncInput": "Вход синхронизации" + "SyncInput": "Вход синхронизации", + "CompareWithOtherModels": "Сравнить с другими моделями" } } diff --git a/resources/i18n/th.json b/resources/i18n/th.json index af24ccb5c..5ab63e476 100644 --- a/resources/i18n/th.json +++ b/resources/i18n/th.json @@ -1692,6 +1692,7 @@ "DeleteChatSession": "ลบเซสชันการแชท", "DeleteChattingSession": "ลบเซสชันการแชท", "DeleteChattingSessionDescription": "คุณกำลังจะลบหัวข้อนี้ เมื่อลบแล้วจะไม่สามารถกู้คืนได้ กรุณาดำเนินการด้วยความระมัดระวัง", - "SyncInput": "ซิงค์อินพุต" + "SyncInput": "ซิงค์อินพุต", + "CompareWithOtherModels": "เปรียบเทียบกับรุ่นอื่นๆ" } } diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json index 4d65b2c7f..7ec29d4cf 100644 --- a/resources/i18n/tr.json +++ b/resources/i18n/tr.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Sohbet oturumunu sil", "DeleteChattingSessionDescription": "Bu konuyu silmek üzeresiniz. \nBir kere silindikten sonra geri getirilemez. \nLütfen dikkatli bir şekilde ilerleyin.", "SelectEndpoint": "Uç Noktayı Seçin", - "SyncInput": "Senkronizasyon girişi" + "SyncInput": "Senkronizasyon girişi", + "CompareWithOtherModels": "Diğer modellerle karşılaştırın" } } diff --git a/resources/i18n/vi.json b/resources/i18n/vi.json index 6d518b95f..0d544cc96 100644 --- a/resources/i18n/vi.json +++ b/resources/i18n/vi.json @@ -1707,6 +1707,7 @@ "DeleteChattingSession": "Xóa phiên trò chuyện", "DeleteChattingSessionDescription": "Bạn sắp xóa chủ đề này. \nMột khi đã xóa, nó không thể được phục hồi. \nHãy tiến hành thận trọng.", "SelectEndpoint": "Chọn điểm cuối", - "SyncInput": "Đồng bộ hóa đầu vào" + "SyncInput": "Đồng bộ hóa đầu vào", + "CompareWithOtherModels": "So sánh với các mô hình khác" } } diff --git a/resources/i18n/zh-CN.json b/resources/i18n/zh-CN.json index 0831bd26b..64c11c0b8 100644 --- a/resources/i18n/zh-CN.json +++ b/resources/i18n/zh-CN.json @@ -1708,6 +1708,7 @@ "DeleteChattingSession": "删除聊天会话", "DeleteChattingSessionDescription": "您即将删除该主题。\n一旦删除,就无法恢复。\n请谨慎行事。", "SelectEndpoint": "选择端点", - "SyncInput": "同步输入" + "SyncInput": "同步输入", + "CompareWithOtherModels": "与其他型号比较" } } diff --git a/resources/i18n/zh-TW.json b/resources/i18n/zh-TW.json index f310bd527..d2cca58fb 100644 --- a/resources/i18n/zh-TW.json +++ b/resources/i18n/zh-TW.json @@ -1706,6 +1706,7 @@ "DeleteChattingSession": "刪除聊天會話", "DeleteChattingSessionDescription": "您即將刪除該主題。\n一旦刪除,就無法恢復。\n請謹慎行事。", "SelectEndpoint": "選擇端點", - "SyncInput": "同步輸入" + "SyncInput": "同步輸入", + "CompareWithOtherModels": "與其他型號比較" } }