@roadiehq/rag-ai
Version:
132 lines (129 loc) • 5.19 kB
JavaScript
import React, { useState, useCallback } from 'react';
import { makeStyles, DialogTitle, Typography, IconButton, DialogContent, Box, Grid } from '@material-ui/core';
import { useHotkeys } from 'react-hotkeys-hook';
import CloseIcon from '@material-ui/icons/Close';
import { QuestionBox } from './QuestionBox.esm.js';
import { ResultRenderer } from './ResultRenderer.esm.js';
import { EmbeddingsView } from './EmbeddingsView.esm.js';
import Dialog from '@material-ui/core/Dialog';
import { ragAiApiRef } from '../../api/ragApi.esm.js';
import 'eventsource-parser/stream';
import { useApi } from '@backstage/core-plugin-api';
import { Thinking } from './Thinking.esm.js';
import { WarningPanel } from '@backstage/core-components';
const useStyles = makeStyles((theme) => ({
dialogTitle: {
gap: theme.spacing(1),
display: "grid",
alignItems: "center",
gridTemplateColumns: "1fr auto",
"&> button": {
marginTop: theme.spacing(1)
}
},
filter: {
"& + &": {
marginTop: theme.spacing(2.5)
}
},
filters: {
padding: theme.spacing(2),
marginTop: theme.spacing(2)
},
input: {
flex: 1
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
dialogActionsContainer: { padding: theme.spacing(1, 3) },
viewResultsLink: { verticalAlign: "0.5em" }
}));
const ControlledRagModal = ({
title = "AI Assistant",
hotkey = "ctrl+comma",
open,
setOpen
}) => {
const classes = useStyles();
const [thinking, setThinking] = useState(false);
const [questionResult, setQuestionResult] = useState("");
const [embeddings, setEmbeddings] = useState([]);
const [warning, setWarning] = useState();
const ragApi = useApi(ragAiApiRef);
const askLlm = useCallback(
async (question, source) => {
setThinking(true);
setQuestionResult("");
setWarning(void 0);
setEmbeddings([]);
for await (const chunk of ragApi.ask(question, source)) {
switch (chunk.event) {
case "response": {
setQuestionResult((value) => value + chunk.data);
break;
}
case "embeddings": {
setEmbeddings(JSON.parse(chunk.data));
break;
}
case "error": {
setWarning(chunk.data);
break;
}
case "usage": {
break;
}
default:
throw new Error(`Unknown event type: ${chunk.event}`);
}
}
setThinking(false);
},
[ragApi]
);
useHotkeys(hotkey, () => setOpen(true), []);
return /* @__PURE__ */ React.createElement(
Dialog,
{
open,
onClose: () => {
setOpen(false);
setThinking(false);
setQuestionResult("");
setEmbeddings([]);
},
fullWidth: true,
maxWidth: "lg"
},
/* @__PURE__ */ React.createElement(DialogTitle, null, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, title), /* @__PURE__ */ React.createElement(
IconButton,
{
"aria-label": "close",
className: classes.closeButton,
onClick: () => setOpen(false)
},
/* @__PURE__ */ React.createElement(CloseIcon, null)
)),
/* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Box, { className: classes.dialogTitle }, /* @__PURE__ */ React.createElement(
QuestionBox,
{
onSubmit: askLlm,
fullWidth: true,
onClear: () => {
setQuestionResult("");
setEmbeddings([]);
}
}
)), warning && /* @__PURE__ */ React.createElement(WarningPanel, { severity: "warning", message: warning }), thinking && !questionResult && !warning ? /* @__PURE__ */ React.createElement(Box, { p: 6, display: "flex", justifyContent: "center", alignItems: "center" }, /* @__PURE__ */ React.createElement(Thinking, null)) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { py: 3 }, /* @__PURE__ */ React.createElement(Grid, { container: true }, questionResult && /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Response")), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(ResultRenderer, { result: questionResult })))), /* @__PURE__ */ React.createElement(Box, { py: 3 }, /* @__PURE__ */ React.createElement(Grid, { container: true }, embeddings && embeddings.length > 0 && /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Additional Information")), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(EmbeddingsView, { embeddings }))))))
);
};
const UncontrolledRagModal = (props) => {
const [open, setOpen] = useState(false);
return /* @__PURE__ */ React.createElement(ControlledRagModal, { open, setOpen, ...props });
};
export { ControlledRagModal, UncontrolledRagModal };
//# sourceMappingURL=RagModal.esm.js.map