feat: Add Chat LLM functionality with message input and display components
This commit is contained in:
+1
-1
@@ -21,4 +21,4 @@ app.add_middleware(
|
|||||||
|
|
||||||
|
|
||||||
# Incluye las rutas de tu API
|
# Incluye las rutas de tu API
|
||||||
app.include_router(router)
|
app.include_router(router, prefix="/api/v1", tags=["v1"])
|
||||||
@@ -7,6 +7,6 @@ from backend.domains.text_manager import text_manager_endpoint_v1
|
|||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
router.include_router(ping_endpoint_v1.router, prefix="/api/v1/ping")
|
router.include_router(ping_endpoint_v1.router, prefix="/ping")
|
||||||
router.include_router(text_manager_endpoint_v1.router, prefix="/api/v1/text_manager")
|
router.include_router(text_manager_endpoint_v1.router, prefix="/text_manager")
|
||||||
router.include_router(charts.router, prefix="/api/v1/charts")
|
router.include_router(charts.router, prefix="/charts")
|
||||||
|
|||||||
+11
-1
@@ -7,7 +7,7 @@ import { Biblioteca } from './domains/TextEditor/Biblioteca';
|
|||||||
import { VisualizacionesRandom } from './domains/Experiments/Visualizaciones_Random';
|
import { VisualizacionesRandom } from './domains/Experiments/Visualizaciones_Random';
|
||||||
import { Camara_noir } from './domains/CamaraNoir/Camaras_noir';
|
import { Camara_noir } from './domains/CamaraNoir/Camaras_noir';
|
||||||
import EditorTest from "./domains/TextEditor/Editor_Test";
|
import EditorTest from "./domains/TextEditor/Editor_Test";
|
||||||
|
import { ChatPage } from './domains/Llms/Chat/ChatPage';
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
|
||||||
@@ -33,6 +33,16 @@ const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Chat LLM
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/llms/chat',
|
||||||
|
element: <ChatPage />,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// CamaraNoir
|
// CamaraNoir
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Textarea, Button, Group } from "@mantine/core";
|
||||||
|
|
||||||
|
export function ChatInput({ onSend }: { onSend: (text: string) => void }) {
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
|
||||||
|
const handleSend = () => {
|
||||||
|
if (!text.trim()) return;
|
||||||
|
onSend(text.trim());
|
||||||
|
setText("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Group>
|
||||||
|
<Textarea
|
||||||
|
value={text}
|
||||||
|
onChange={(e) => setText(e.currentTarget.value)}
|
||||||
|
autosize
|
||||||
|
minRows={1}
|
||||||
|
maxRows={4}
|
||||||
|
placeholder="Escribe tu mensaje..."
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Button onClick={handleSend}>Enviar</Button>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Container, Stack, Paper, ScrollArea, Title } from "@mantine/core";
|
||||||
|
import { ChatInput } from "./ChatInput";
|
||||||
|
import { MessageList } from "./MessageList";
|
||||||
|
import { AppShellWithMenu } from "../../FitzStudio/Appshell/Appshell";
|
||||||
|
|
||||||
|
export function ChatPage() {
|
||||||
|
const [messages, setMessages] = useState([
|
||||||
|
{ sender: "bot", content: "Hola, ¿en qué puedo ayudarte hoy?" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const handleSend = async (content: string) => {
|
||||||
|
const newMessages = [...messages, { sender: "user", content }];
|
||||||
|
setMessages(newMessages);
|
||||||
|
|
||||||
|
const response = await fetch("/api/chat", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ messages: newMessages }),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
setMessages([...newMessages, { sender: "bot", content: data.reply }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppShellWithMenu>
|
||||||
|
<Container size="sm" p="md">
|
||||||
|
<Stack>
|
||||||
|
<Title order={2}>Chat LLM</Title>
|
||||||
|
<Paper shadow="xs" p="md" withBorder>
|
||||||
|
<ScrollArea h={400}>
|
||||||
|
<MessageList messages={messages} />
|
||||||
|
</ScrollArea>
|
||||||
|
</Paper>
|
||||||
|
<ChatInput onSend={handleSend} />
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
</AppShellWithMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Paper, Text, useMantineTheme, useMantineColorScheme } from "@mantine/core";
|
||||||
|
|
||||||
|
export function MessageBubble({ sender, content }: { sender: string; content: string }) {
|
||||||
|
const theme = useMantineTheme();
|
||||||
|
const { colorScheme } = useMantineColorScheme();
|
||||||
|
const isUser = sender === "user";
|
||||||
|
|
||||||
|
const userBg = theme.colors[theme.primaryColor][0];
|
||||||
|
const botBg = colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0];
|
||||||
|
const userTextColor = theme.colors[theme.primaryColor][9];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
p="sm"
|
||||||
|
radius="md"
|
||||||
|
withBorder
|
||||||
|
style={{
|
||||||
|
alignSelf: isUser ? "flex-end" : "flex-start",
|
||||||
|
backgroundColor: isUser ? userBg : botBg,
|
||||||
|
maxWidth: "80%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text size="sm" c={isUser ? userTextColor : undefined}>
|
||||||
|
{content}
|
||||||
|
</Text>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Stack } from "@mantine/core";
|
||||||
|
import { MessageBubble } from "./MessageBubble";
|
||||||
|
|
||||||
|
export function MessageList({ messages }: { messages: { sender: string; content: string }[] }) {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
{messages.map((msg, i) => (
|
||||||
|
<MessageBubble key={i} sender={msg.sender} content={msg.content} />
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user