+ {typeof predictedPrice === 'string' && (
+
+
+
+
+ {Math.ceil(Number(predictedPrice))}
+
+
+
+ )}
{typeVersions['image'] &&
(typeVersions['image'].length === 0 ||
typeVersions['image'].includes(currentVersion)) && (
@@ -0,0 +1 @@
+export { usePredictPrice } from './use-predict-price'
@@ -0,0 +1,68 @@
+import { useEffect, useRef, useState } from 'react'
+import { debounce } from 'lodash'
+
+import { predictPrice } from '#/shared/api/models/predict-price'
+
+interface UsePredictPriceParams {
+ modelSlug: string
+ content: string
+ fileExists: boolean
+ info: Record
+ token?: string
+ enabled?: boolean
+}
+
+export function usePredictPrice({
+ modelSlug,
+ content,
+ fileExists,
+ info,
+ token,
+ enabled = true,
+}: UsePredictPriceParams) {
+ const [price, setPrice] = useState(null)
+
+ const debouncedPredictRef = useRef(
+ debounce(
+ async (
+ slug: string,
+ text: string,
+ hasFile: boolean,
+ params: Record,
+ accessToken?: string
+ ) => {
+ try {
+ const result = await predictPrice(
+ {
+ model_slug: slug,
+ content: text,
+ file_exists: hasFile,
+ info: params,
+ },
+ accessToken
+ )
+ setPrice(typeof result.price === 'string' ? result.price : null)
+ } catch {
+ setPrice(null)
+ }
+ },
+ 500
+ )
+ )
+
+ useEffect(() => {
+ if (!enabled || !modelSlug || !token) {
+ setPrice(null)
+ return
+ }
+
+ const debouncedPredict = debouncedPredictRef.current
+ debouncedPredict(modelSlug, content, fileExists, info, token)
+
+ return () => {
+ debouncedPredict.cancel()
+ }
+ }, [modelSlug, content, fileExists, info, token, enabled])
+
+ return price
+}
@@ -1,11 +1,6 @@
.wrapModelTitle {
- margin-bottom: 20px;
- margin-top: 15px;
- // width: max-content;
- width: 100% !important;
@media (max-width: 768px) {
margin: 0;
- margin-top: 15px;
}
.bigTitle {
min-width: max-content !important;
@@ -27,12 +27,6 @@ export default function Title(props: TitleProps) {
-
- {props.title}
-
{props.rightSlot}
@@ -0,0 +1,31 @@
+import axios from 'axios'
+
+import { API_URL } from '#/shared/lib/constants'
+
+export interface PredictPriceRequest {
+ model_slug: string
+ content: string
+ file_exists: boolean
+ info: Record
+}
+
+export interface PredictPriceResponse {
+ price: string | null
+}
+
+export async function predictPrice(
+ data: PredictPriceRequest,
+ token?: string
+): Promise {
+ const { data: result } = await axios.post(
+ API_URL + '/ml_model/predict-price/',
+ data,
+ {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': 'application/json',
+ },
+ }
+ )
+ return result as PredictPriceResponse
+}
@@ -16,16 +16,31 @@
}
}
+.staticTabsWrapper {
+ display: flex;
+ align-items: center;
+ width: calc(24.5% + 2px);
+ margin-left: auto;
+ margin-right: calc(3%);
+ margin-top: 0;
+}
+
.header {
- width: 70%;
- margin-bottom: 50px;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ gap: 22px;
+ margin: 14px 0;
+
+ > *:first-child {
+ min-width: 200px;
+ }
@media screen and (max-width: 768px) {
width: 100%;
- margin-bottom: 0px;
+ gap: 12px;
}
}
-
@keyframes fadein {
0% {
opacity: 0;
@@ -41,16 +56,12 @@
.icon {
}
+
.tags {
- min-width: 100%;
display: flex;
gap: 8px;
align-items: center;
justify-content: flex-end;
-
- @media screen and (max-width: 768px) {
- justify-content: flex-start;
- }
}
.tag {
@@ -16,6 +16,7 @@ import { useImagesBotFilters } from '#/features/image-bot-filters'
import { useImagesUniqInput } from '#/features/image-bot-input'
import { useMediaBotPagination } from '#/features/image-bot-pagination'
import { ModelInput } from '#/features/model-input'
+import { usePredictPrice } from '#/features/predict-price/model/use-predict-price'
import Title from '#/features/title/title'
import { NextPageWithLayout } from '#/pages/_app'
import { DrawerCustom, Loader } from '#/shared'
@@ -123,6 +124,20 @@ const AudioModelPage: NextPageWithLayout = () => {
})
}, [botParams?.inputs, version])
+ const predictPriceInfo = useMemo(
+ () => ({ ...(includeParams || {}), ...(version ? { version } : {}) }),
+ [includeParams, version]
+ )
+
+ const predictedPrice = usePredictPrice({
+ modelSlug: modelType,
+ content: prompt,
+ fileExists: !!image,
+ info: predictPriceInfo,
+ token: session?.access,
+ enabled: !!modelType && !!session?.access && scope === 'playground',
+ })
+
return (
<>
@@ -133,8 +148,8 @@ const AudioModelPage: NextPageWithLayout = () => {
title={botParams ? botParams.title : 'Загрузка...'}
type={'Аудио'}
linkBack={'/audio'}
- rightSlot={
-
+ />
+
{botParams &&
botParams.tags.map((tag, index) => (
@@ -144,9 +159,18 @@ const AudioModelPage: NextPageWithLayout = () => {
))}
- }
- />
+ {desktop && (
+
+
+ )}
+
+ {!desktop && (
+
+
+
+ )}
+
{
sendMessage={onCreateImage}
unpinImage={() => setImage(null)}
viewMobileSettings={() => setOpenFiltersMobile(true)}
+ predictedPrice={predictedPrice}
/>
)}
@@ -294,6 +319,7 @@ const AudioModelPage: NextPageWithLayout = () => {
sendMessage={onCreateImage}
unpinImage={() => setImage(null)}
viewMobileSettings={() => setOpenFiltersMobile(true)}
+ predictedPrice={predictedPrice}
/>
)}
{isProgressVisible && (
@@ -312,11 +338,6 @@ const AudioModelPage: NextPageWithLayout = () => {
-
-
-
{desktop && (
{botParams?.versions && botParams.versions.length !== 0 ? (
@@ -17,6 +17,7 @@ import { TutorialContext } from '#/features/tutorial-context/tutorial-context'
import { NextPageWithLayout } from '#/pages/_app'
import { DrawerCustom, useModel } from '#/shared'
import model_api from '#/shared/api/models/api'
+import { usePredictPrice } from '#/features/predict-price/model/use-predict-price'
import { getDeviceType, getOs } from '#/shared/lib/helpers'
import { useShowDataStore } from '#/shared/lib/hooks/use-show-data'
import { SvgIcon } from '#/shared/ui/svg'
@@ -37,6 +38,7 @@ const Page: NextPageWithLayout = () => {
const [params, setParams] = React.useState(false)
const [file, setFile] = React.useState(null)
+ const [inputContent, setInputContent] = React.useState('')
const { showMessage } = useShowDataStore()
const [scope, setScope] = React.useState<'playground' | 'api'>('playground')
@@ -199,6 +201,20 @@ const Page: NextPageWithLayout = () => {
})
}, [botParams?.inputs, version])
+ const predictPriceInfo = useMemo(
+ () => ({ ...(includeParams || {}), ...(version ? { version } : {}) }),
+ [includeParams, version]
+ )
+
+ const predictedPrice = usePredictPrice({
+ modelSlug: modelType,
+ content: inputContent,
+ fileExists: !!file,
+ info: predictPriceInfo,
+ token: data?.access,
+ enabled: !!modelType && !!data?.access && scope === 'playground',
+ })
+
return (
<>
@@ -208,23 +224,36 @@ const Page: NextPageWithLayout = () => {
- {botParams &&
- botParams.tags.map((tag, index) => (
-
-
- {tag.title}
-
- ))}
-
- }
type={'Чат-боты'}
linkBack={'/chat-bot'}
/>
-
+
+ {botParams &&
+ botParams.tags.map((tag, index) => (
+
+
+ {tag.title}
+
+ ))}
+
+ {desktop && }
+
+ {desktop && (
+
+
+
+ )}
+
+ {!desktop && (
+