feat: connect LLM + LoRA tab to backend api
All checks were successful
Build and Deploy Next.js + Nginx Docker Image / build-and-deploy (push) Successful in 2m50s
Build and Deploy Next.js + Nginx Docker Image / deploy (push) Successful in 8s

This commit is contained in:
Hossein Salari 2026-02-26 17:34:37 +03:30
parent 37188ff30a
commit 8dda6b05d7
7 changed files with 178 additions and 188 deletions

2
.env
View File

@ -1 +1 @@
NEXT_PUBLIC_BASE_URL=http://192.168.10.87:8070
NEXT_PUBLIC_BASE_URL=http://192.168.10.87:8070/generative

View File

@ -0,0 +1,49 @@
import { Box, HStack, Image, Text, VStack } from "@chakra-ui/react";
export default function AppHeader() {
return (
<Box
w="100%"
h="92px"
borderBottom="1px solid"
borderColor="gray.200"
bg="#fdfbff"
as={HStack}
alignItems="center"
justifyContent="space-between"
px={"20px"}
zIndex={10}
position="fixed"
top={0}
>
<HStack alignItems={"end"} height={"100%"} py={"10px"}>
<Image
src="/generative-logo.png"
w={"80px"}
h={"70px"}
loading="lazy"
/>
<VStack alignItems={"start"} justifyContent={"end"} height={"100%"}>
<Text fontWeight={"bold"} fontSize={"20px"}>
سامانه تولید محتوای هوشمند
</Text>
<Text>
سامانه جامع تولید محتوا با استفاده از مدلهای زبانی و مولد تصویر و
ویدئو
</Text>
</VStack>
</HStack>
<VStack
w={"fit-content"}
alignItems={"center"}
justifyContent={"center"}
py={"10px"}
>
<Image src="./logob.png" />
<Text fontSize="xs" fontWeight="bold">
موسسه تولید سیستم های خبره و هوشمند اسلامی باقرالعلوم(ع)
</Text>
</VStack>
</Box>
);
}

View File

@ -0,0 +1,33 @@
import { Flex, Icon, Text } from "@chakra-ui/react";
export default function SidebarItem({
icon,
label,
active = false,
setFilters,
name,
}) {
return (
<Flex
align="center"
gap={3}
px={4}
py={3}
borderRadius="lg"
cursor="pointer"
bg={active ? "purple.50" : "transparent"}
color={active ? "purple.600" : "gray.700"}
_hover={{
bg: "purple.50",
color: "purple.600",
}}
transition="all 0.2s"
onClick={(e) => setFilters({ tab_menu: name })}
>
<Icon as={icon} boxSize={5} />
<Text fontSize="md" fontWeight="medium">
{label}
</Text>
</Flex>
);
}

View File

@ -0,0 +1,72 @@
import { VStack } from "@chakra-ui/react";
import SidebarItem from "./SidebarItem";
import { BsChatText } from "react-icons/bs";
import { FiImage } from "react-icons/fi";
import { CiVideoOn } from "react-icons/ci";
export default function SidebarList({ filters, setFilters }) {
return (
<VStack align="stretch" spacing={2}>
{filters?.tab === 0 && (
<>
<SidebarItem
icon={BsChatText}
label="LLM Base"
name={"gemma_base"}
active={filters?.tab_menu == "gemma_base" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={BsChatText}
label="LLM + LoRA"
name={"gemma4b_lora"}
active={filters?.tab_menu == "gemma4b_lora" ? true : false}
filters={filters}
setFilters={setFilters}
/>
</>
)}
{filters?.tab === 1 && (
<>
<SidebarItem
icon={FiImage}
label="SDXL Base"
name={"sdxl"}
active={filters?.tab_menu == "sdxl" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiImage}
label="SDXL + LoRA"
name={"sdxl_lora"}
active={filters?.tab_menu == "sdxl_lora" ? true : false}
filters={filters}
setFilters={setFilters}
/>
</>
)}
{filters?.tab === 2 && (
<>
<SidebarItem
icon={CiVideoOn}
label="CogVideo Base"
name={"cogvideo_base"}
active={filters?.tab_menu == "cogvideo_base" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={CiVideoOn}
label="CogVideo + LoRA"
name={"cogvideo"}
active={filters?.tab_menu == "cogvideo" ? true : false}
filters={filters}
setFilters={setFilters}
/>
</>
)}
</VStack>
);
}

View File

@ -25,6 +25,11 @@ import useSWRMutation from "swr/mutation";
import axiosInstance, { baseUrl } from "@/lib/api";
import { useState } from "react";
const modelsDic = {
gemma_base: "base",
gemma4b_lora: "lora",
};
const postRequest = async (url, { arg }) => {
const response = await axiosInstance.post(baseUrl + url, arg);
return response?.data;
@ -35,9 +40,13 @@ export default function LlmPanel({ filters }) {
const [generatedText, setGeneratedText] = useState("");
const { trigger: triggerGenerateText, isMutating: isGeneratingText } =
useSWRMutation("/content/content/base", postRequest, {
onSuccess: (data) => setGeneratedText(data?.content),
});
useSWRMutation(
`/content/vllm/${modelsDic[filters?.tab_menu]}`,
postRequest,
{
onSuccess: (data) => setGeneratedText(data?.content),
},
);
const onSubmit = (data) => {
triggerGenerateText({

View File

@ -11,7 +11,6 @@ axiosInstance.interceptors.request.use(
async (config) => {
if (keycloak?.authenticated) {
config.headers.Authorization = `Bearer ${keycloak.token}`;
await keycloak.updateToken(30);
}
return config;
},

View File

@ -11,12 +11,8 @@ import {
TabList,
TabPanel,
TabPanels,
Icon,
HStack,
Image,
} from "@chakra-ui/react";
import { FiImage, FiLayers } from "react-icons/fi";
import { CiVideoOn } from "react-icons/ci";
import {
IoDocumentTextOutline,
IoImageOutline,
@ -29,9 +25,11 @@ import {
useQueryParams,
withDefault,
} from "use-query-params";
import { BsChatText } from "react-icons/bs";
import { AiOutlinePoweroff } from "react-icons/ai";
import keycloak from "@/lib/keycloak";
import AppHeader from "@/components/layout/AppHeader";
import SidebarList from "@/components/layout/SidebarList";
import { useEffect } from "react";
export default function Home() {
const [filters, setFilters] = useQueryParams({
@ -40,6 +38,12 @@ export default function Home() {
model_name: withDefault(NumberParam, 0),
});
useEffect(() => {
if (filters?.tab == 0) setFilters({ tab_menu: "gemma_base" });
else if (filters?.tab == 1) setFilters({ tab_menu: "sdxl" });
else if (filters?.tab == 2) setFilters({ tab_menu: "cogvideo_base" });
}, [filters?.tab]);
return (
<Flex direction={"column"} minH="100vh" bg="gray.50" dir="rtl">
{/* Header */}
@ -83,112 +87,10 @@ export default function Home() {
<TabPanels>
<TabPanel>
<VStack align="stretch" spacing={2}>
<SidebarItem
icon={BsChatText}
label="LLM Base"
name={"gemma_base"}
active={filters?.tab_menu == "gemma_base" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiImage}
label="LLM + LoRA"
name={"llm"}
active={filters?.tab_menu == "llm" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="SDXL + LoRA"
name={"sdxl_lora"}
active={filters?.tab_menu == "sdxl_lora" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="SDXL"
name={"sdxl"}
active={filters?.tab_menu == "sdxl" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={CiVideoOn}
label="CogVideo + LoRA"
name={"cogvideo"}
active={filters?.tab_menu == "cogvideo" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="CogVideo Base"
name={"cogvideo_base"}
active={
filters?.tab_menu == "cogvideo_base" ? true : false
}
filters={filters}
setFilters={setFilters}
/>
</VStack>
<SidebarList filters={filters} setFilters={setFilters} />
</TabPanel>
<TabPanel>
<VStack align="stretch" spacing={2}>
<SidebarItem
icon={BsChatText}
label="LLM Base"
name={"gemma_base"}
active={filters?.tab_menu == "gemma_base" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiImage}
label="LLM + LoRA"
name={"llm"}
active={filters?.tab_menu == "llm" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="SDXL + LoRA"
name={"sdxl_lora"}
active={filters?.tab_menu == "sdxl_lora" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="SDXL"
name={"sdxl"}
active={filters?.tab_menu == "sdxl" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={CiVideoOn}
label="CogVideo + LoRA"
name={"cogvideo"}
active={filters?.tab_menu == "cogvideo" ? true : false}
filters={filters}
setFilters={setFilters}
/>
<SidebarItem
icon={FiLayers}
label="CogVideo Base"
name={"cogvideo_base"}
active={
filters?.tab_menu == "cogvideo_base" ? true : false
}
filters={filters}
setFilters={setFilters}
/>
</VStack>
<SidebarList filters={filters} setFilters={setFilters} />
</TabPanel>
</TabPanels>
</Tabs>
@ -290,77 +192,3 @@ export default function Home() {
</Flex>
);
}
function AppHeader() {
return (
<Box
w="100%"
h="92px"
borderBottom="1px solid"
borderColor="gray.200"
bg="#fdfbff"
as={HStack}
alignItems="center"
justifyContent="space-between"
px={"20px"}
zIndex={10}
position="fixed"
top={0}
>
<HStack alignItems={"end"} height={"100%"} py={"10px"}>
<Image
src="/generative-logo.png"
w={"80px"}
h={"70px"}
loading="lazy"
/>
<VStack alignItems={"start"} justifyContent={"end"} height={"100%"}>
<Text fontWeight={"bold"} fontSize={"20px"}>
سامانه تولید محتوای هوشمند
</Text>
<Text>
سامانه جامع تولید محتوا با استفاده از مدلهای زبانی و مولد تصویر و
ویدئو
</Text>
</VStack>
</HStack>
<VStack
w={"fit-content"}
alignItems={"center"}
justifyContent={"center"}
py={"10px"}
>
<Image src="./logob.png" />
<Text fontSize="xs" fontWeight="bold">
موسسه تولید سیستم های خبره و هوشمند اسلامی باقرالعلوم(ع)
</Text>
</VStack>
</Box>
);
}
function SidebarItem({ icon, label, active = false, setFilters, name }) {
return (
<Flex
align="center"
gap={3}
px={4}
py={3}
borderRadius="lg"
cursor="pointer"
bg={active ? "purple.50" : "transparent"}
color={active ? "purple.600" : "gray.700"}
_hover={{
bg: "purple.50",
color: "purple.600",
}}
transition="all 0.2s"
onClick={(e) => setFilters({ tab_menu: name })}
>
<Icon as={icon} boxSize={5} />
<Text fontSize="md" fontWeight="medium">
{label}
</Text>
</Flex>
);
}