Add Vision demo side by side UI (#70)
* Add Vision demo side by side UI Signed-off-by: lvliang-intel <liang1.lv@intel.com>
This commit is contained in:
34
ChatQnA/ui_side_by_side/.eslintrc.cjs
Normal file
34
ChatQnA/ui_side_by_side/.eslintrc.cjs
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2024 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:react-hooks/recommended",
|
||||
],
|
||||
ignorePatterns: ["dist", ".eslintrc.cjs"],
|
||||
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
|
||||
settings: { react: { version: "18.2" } },
|
||||
plugins: ["react-refresh", "simple-import-sort"],
|
||||
rules: {
|
||||
"react/jsx-no-target-blank": "off",
|
||||
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
},
|
||||
};
|
||||
24
ChatQnA/ui_side_by_side/.gitignore
vendored
Normal file
24
ChatQnA/ui_side_by_side/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
8
ChatQnA/ui_side_by_side/.prettierrc
Normal file
8
ChatQnA/ui_side_by_side/.prettierrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"endOfLine": "lf",
|
||||
"printWidth": 100
|
||||
}
|
||||
68
ChatQnA/ui_side_by_side/README.md
Normal file
68
ChatQnA/ui_side_by_side/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# LLM Chatbot GUI
|
||||
|
||||
## 📸 Project Screenshots
|
||||
|
||||

|
||||

|
||||
|
||||
## Requirements
|
||||
|
||||
- [Node.js](https://nodejs.org/) version v18.0.0 or higher
|
||||
- [npm](https://www.npmjs.com/) version 9.6.5 or higher
|
||||
|
||||
To check if both were successfully installed run the following commands:
|
||||
|
||||
```bash
|
||||
node --version
|
||||
```
|
||||
|
||||
```bash
|
||||
npm --version
|
||||
```
|
||||
|
||||
_`--version` option can be replaced with `-v` shorthand_
|
||||
|
||||
## Setup
|
||||
|
||||
### Environment variables
|
||||
|
||||
Create `.env` file in this folder. It has to contain the following variables that represent corresponding endpoints
|
||||
for communication with **without RAG** and **with RAG** backend:
|
||||
|
||||
```
|
||||
VITE_WITH_RAG_BASE_URL = 'http://<ip-address>:<port>/v1/rag'
|
||||
VITE_WITHOUT_RAG_BASE_URL = 'http://<ip-address>:<port>/v1/rag'
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## Start GUI
|
||||
|
||||
Execute the following command to start GUI:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
By default, UI will run on `http://localhost:5147`.
|
||||
The port and IP address that the UI will be served on can be changed by modifying npm `dev` script
|
||||
in `package.json`.
|
||||
|
||||
The following example presents how to change port and IP address by setting corresponding options: `--port`
|
||||
and `--host`.
|
||||
|
||||
```json
|
||||
"dev": "vite dev --port 9090 --host 0.0.0.0",
|
||||
```
|
||||
|
||||
This also can be set via CLI by adding `-- --port <port> --host <ip>` :
|
||||
|
||||
```bash
|
||||
npm run dev -- --port 9090 --host 0.0.0.0
|
||||
```
|
||||
|
||||
In case of any configuring issues please refer to https://vitejs.dev/config/server-options.
|
||||
29
ChatQnA/ui_side_by_side/index.html
Normal file
29
ChatQnA/ui_side_by_side/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!--
|
||||
Copyright (c) 2024 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html data-theme="dark" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link href="" rel="icon" type="image/svg+xml" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
<title>Enhancing Generative AI – Business Relevant Results with RAG</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="/src/main.jsx" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
6563
ChatQnA/ui_side_by_side/package-lock.json
generated
Normal file
6563
ChatQnA/ui_side_by_side/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
ChatQnA/ui_side_by_side/package.json
Normal file
42
ChatQnA/ui_side_by_side/package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "llm-chatbot",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource/roboto": "^5.0.12",
|
||||
"@mui/icons-material": "^5.15.14",
|
||||
"@mui/material": "^5.15.14",
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"sse.js": "^2.4.1",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.64",
|
||||
"@types/react-dom": "^18.2.21",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"eslint-plugin-simple-import-sort": "^12.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sass": "^1.71.1",
|
||||
"vite": "^5.1.6"
|
||||
}
|
||||
}
|
||||
24
ChatQnA/ui_side_by_side/src/App.css
Normal file
24
ChatQnA/ui_side_by_side/src/App.css
Normal file
@@ -0,0 +1,24 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
/* Uncomment the following line to disable whether the user can select and copy text */
|
||||
/*user-select: none;*/
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
font-family: "IntelOneText", sans-serif !important;
|
||||
|
||||
@media screen and (min-width: 2500px) {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 2500px) {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1366px) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
25
ChatQnA/ui_side_by_side/src/App.jsx
Normal file
25
ChatQnA/ui_side_by_side/src/App.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useEffect } from "react";
|
||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||
|
||||
import AppHeader from "./layout/app-header/AppHeader";
|
||||
import ChatPage from "./pages/chat/ChatPage";
|
||||
import TelemetryPage from "./pages/telemetry/TelemetryPage";
|
||||
|
||||
const App = () => {
|
||||
useEffect(() => {
|
||||
localStorage.clear();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<AppHeader />
|
||||
<Routes>
|
||||
<Route path="/" element={<Navigate to="/chat" />} />
|
||||
<Route path="chat" element={<ChatPage />} />
|
||||
<Route path="telemetry" element={<TelemetryPage />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Do not edit this file manually! This file is generated automatically from the @spark-design/tokens package.*/
|
||||
|
||||
@font-face {
|
||||
font-family: IntelOneDisplay;
|
||||
src:
|
||||
url("intelone-display-font-family-medium.woff2") format("woff2"),
|
||||
url("intelone-display-font-family-medium.woff") format("woff"),
|
||||
url("intelone-display-font-family-medium.otf") format("opentype"),
|
||||
url("intelone-display-font-family-medium.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneDisplay;
|
||||
src:
|
||||
url("intelone-display-font-family-regular.woff2") format("woff2"),
|
||||
url("intelone-display-font-family-regular.woff") format("woff"),
|
||||
url("intelone-display-font-family-regular.otf") format("opentype"),
|
||||
url("intelone-display-font-family-regular.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneDisplay;
|
||||
src:
|
||||
url("intelone-display-font-family-light.woff2") format("woff2"),
|
||||
url("intelone-display-font-family-light.woff") format("woff"),
|
||||
url("intelone-display-font-family-light.otf") format("opentype"),
|
||||
url("intelone-display-font-family-light.ttf") format("truetype");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneDisplay;
|
||||
src:
|
||||
url("intelone-display-font-family-bold.woff2") format("woff2"),
|
||||
url("intelone-display-font-family-bold.woff") format("woff"),
|
||||
url("intelone-display-font-family-bold.otf") format("opentype"),
|
||||
url("intelone-display-font-family-bold.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,82 @@
|
||||
/* Do not edit this file manually! This file is generated automatically from the @spark-design/tokens package.*/
|
||||
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-regular.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-regular.woff") format("woff"),
|
||||
url("intelone-mono-font-family-regular.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-regular.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-italic.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-italic.woff") format("woff"),
|
||||
url("intelone-mono-font-family-italic.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-italic.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-medium.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-medium.woff") format("woff"),
|
||||
url("intelone-mono-font-family-medium.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-medium.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-mediumitalic.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-mediumitalic.woff") format("woff"),
|
||||
url("intelone-mono-font-family-mediumitalic.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-mediumitalic.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-light.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-light.woff") format("woff"),
|
||||
url("intelone-mono-font-family-light.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-light.ttf") format("truetype");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-lightitalic.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-lightitalic.woff") format("woff"),
|
||||
url("intelone-mono-font-family-lightitalic.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-lightitalic.ttf") format("truetype");
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-bold.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-bold.woff") format("woff"),
|
||||
url("intelone-mono-font-family-bold.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-bold.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneMono;
|
||||
src:
|
||||
url("intelone-mono-font-family-bolditalic.woff2") format("woff2"),
|
||||
url("intelone-mono-font-family-bolditalic.woff") format("woff"),
|
||||
url("intelone-mono-font-family-bolditalic.otf") format("opentype"),
|
||||
url("intelone-mono-font-family-bolditalic.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,82 @@
|
||||
/* Do not edit this file manually! This file is generated automatically from the @spark-design/tokens package.*/
|
||||
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-regular.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-regular.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-regular.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-regular.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-italic.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-italic.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-italic.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-italic.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-medium.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-medium.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-medium.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-medium.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-mediumitalic.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-mediumitalic.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-mediumitalic.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-mediumitalic.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-light.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-light.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-light.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-light.ttf") format("truetype");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-lightitalic.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-lightitalic.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-lightitalic.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-lightitalic.ttf") format("truetype");
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-bold.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-bold.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-bold.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-bold.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: IntelOneText;
|
||||
src:
|
||||
url("intelone-bodytext-font-family-bolditalic.woff2") format("woff2"),
|
||||
url("intelone-bodytext-font-family-bolditalic.woff") format("woff"),
|
||||
url("intelone-bodytext-font-family-bolditalic.otf") format("opentype"),
|
||||
url("intelone-bodytext-font-family-bolditalic.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ChatQnA/ui_side_by_side/src/assets/images/intel-gaudi-badge.png
Normal file
BIN
ChatQnA/ui_side_by_side/src/assets/images/intel-gaudi-badge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
BIN
ChatQnA/ui_side_by_side/src/assets/images/intel-xeon-badge.png
Normal file
BIN
ChatQnA/ui_side_by_side/src/assets/images/intel-xeon-badge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 516 KiB |
1
ChatQnA/ui_side_by_side/src/assets/images/redis.svg
Normal file
1
ChatQnA/ui_side_by_side/src/assets/images/redis.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.5 KiB |
3
ChatQnA/ui_side_by_side/src/index.css
Normal file
3
ChatQnA/ui_side_by_side/src/index.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@import "./assets/fonts/intel-one-display/intel-one-display.css";
|
||||
@import "./assets/fonts/intel-one-text/intel-one-text.css";
|
||||
@import "./assets/fonts/intel-one-mono/intel-one-mono.css";
|
||||
18
ChatQnA/ui_side_by_side/src/layout/app-header/AppHeader.jsx
Normal file
18
ChatQnA/ui_side_by_side/src/layout/app-header/AppHeader.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import "./app-header.scss";
|
||||
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
const AppHeader = () => {
|
||||
return (
|
||||
<header className="app-header">
|
||||
<img alt="Intel Logo" className="intel-logo" />
|
||||
<h3 className="app-title">Enhancing Generative AI – Business Relevant Results with RAG</h3>
|
||||
<nav>
|
||||
<NavLink to="/chat">Chat</NavLink>
|
||||
<NavLink to="/telemetry">Telemetry</NavLink>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppHeader;
|
||||
@@ -0,0 +1,47 @@
|
||||
.app-header {
|
||||
display: inline-flex;
|
||||
inline-size: 100%;
|
||||
block-size: 3rem;
|
||||
line-height: 3rem;
|
||||
color: #ffffff;
|
||||
background-color: #1f2029;
|
||||
align-items: center;
|
||||
padding-block: 0.5rem;
|
||||
|
||||
& .intel-logo {
|
||||
height: 1rem;
|
||||
padding-inline: 1.75rem;
|
||||
content: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzIiIGhlaWdodD0iMjgiIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA3MiAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCiAgPHRpdGxlPkludGVsPC90aXRsZT4NCiAgPHBhdGggZmlsbD0idmFyKC0tc3BhcmstY29sb3ItZW5lcmd5LWJsdWUsICMwMEM3RkQpIiBkPSJNNS4yMi4zOEgwdjUuMjRoNS4yMlYuMzhaIi8+DQogIDxwYXRoIGZpbGw9InZhcigtLXNwYXJrLWNvbG9yLXdoaXRlLCB2YXIoLS1zcGFyay1jb2xvci13aGl0ZSwgI2ZmZmZmZikpIiBkPSJNNS4wOCAyNy42MlY4Ljc4SC4xNHYxOC44NGg0Ljk0Wm0zMi44LjE5VjIzLjJjLS43MyAwLTEuMzMtLjA1LTEuOC0uMTItLjUtLjA4LS45LS4yNS0xLjE1LS41MmEyLjA2IDIuMDYgMCAwIDEtLjUyLTEuMTMgMTIuMSAxMi4xIDAgMCAxLS4xMi0xLjgxdi02LjZoMy41OFY4Ljc5SDM0LjNWMS40NmgtNC45NHYxOC4yYzAgMS41My4xMyAyLjg0LjQgMy44OS4yNiAxLjAyLjcgMS44NiAxLjMxIDIuNWE1LjI3IDUuMjcgMCAwIDAgMi40MSAxLjM2YzEgLjI3IDIuMjcuNDEgMy43Ny40MWguNjN2LS4wMVptMjguMzQtLjE5VjBoLTQuOTV2MjcuNjJoNC45NVpNMjQuNTggMTAuNjRjLTEuMzctMS40OS0zLjMtMi4yNC01Ljc2LTIuMjQtMS4xOCAwLTIuMjcuMjUtMy4yNC43M2E3LjEgNy4xIDAgMCAwLTIuNDUgMmwtLjI4LjM2di0yLjdINy45N3YxOC44M2g0LjkxVjE3LjU5di43LS4zNGMuMDYtMS43Ny40OS0zLjA3IDEuMzEtMy45YTQuMjcgNC4yNyAwIDAgMSAzLjE0LTEuMzVjMS40MyAwIDIuNTEuNDQgMy4yNCAxLjMuNy44NCAxLjA2IDIuMDYgMS4wNyAzLjYxdjEwLjAxaDVWMTYuOTNjMC0yLjY5LS43LTQuOC0yLjA2LTYuMjlabTM0LjEyIDcuNTNjMC0xLjM1LS4yNS0yLjYzLS43Mi0zLjgxYTEwLjAyIDEwLjAyIDAgMCAwLTItMy4xMiA4Ljk0IDguOTQgMCAwIDAtMy4wNS0yLjA5QTEwLjEgMTAuMSAwIDAgMCA0OSA4LjRhOS42IDkuNiAwIDAgMC0zLjgxLjc3IDkuOTQgOS45NCAwIDAgMC0zLjEgMi4xIDkuOCA5LjggMCAwIDAtMi4wOSAzLjEgOS41IDkuNSAwIDAgMC0uNzcgMy44MmMwIDEuMzUuMjQgMi42NC43NCAzLjgyYTkuMzMgOS4zMyAwIDAgMCAyLjAzIDMuMSA5LjQ1IDkuNDUgMCAwIDAgMy4xNCAyLjFjMS4yMi41MiAyLjU4Ljc3IDQuMDIuNzcgNC4xOSAwIDYuOC0xLjkxIDguMzYtMy43bC0zLjU2LTIuNzJhNi41IDYuNSAwIDAgMS00Ljc2IDIuMWMtMS40IDAtMi41NS0uMzMtMy40MS0uOTZBNC44MiA0LjgyIDAgMCAxIDQ0IDIwLjFsLS4wNS0uMThoMTQuNzR2LTEuNzRabS0xNC43MS0xLjczYzAtMS4zOCAxLjU4LTMuNzkgNC45OC0zLjc5IDMuNCAwIDQuOTggMi40IDQuOTggMy43OGwtOS45Ni4wMVoiLz4NCiAgPHBhdGggZmlsbD0idmFyKC0tc3BhcmstY29sb3Itd2hpdGUsIHZhcigtLXNwYXJrLWNvbG9yLXdoaXRlLCAjZmZmZmZmKSkiIGQ9Ik03MS44NSAyNS4yNGEyIDIgMCAwIDAtLjM5LS41OCAxLjgxIDEuODEgMCAwIDAtLjU4LS4zOSAxLjgxIDEuODEgMCAwIDAtMS40MyAwIDIgMiAwIDAgMC0uNTguNCAxLjgxIDEuODEgMCAwIDAtLjM5LjU3IDEuODIgMS44MiAwIDAgMCAwIDEuNDQgMS44IDEuOCAwIDAgMCAuOTcuOTcgMS44MSAxLjgxIDAgMCAwIDEuNDMgMCAxLjgzIDEuODMgMCAwIDAgLjk3LS45NyAxLjgyIDEuODIgMCAwIDAgMC0xLjQ0Wm0tLjMgMS4zMWExLjUyIDEuNTIgMCAwIDEtMS40LjkzYy0uMiAwLS40LS4wNC0uNTgtLjExYTEuNTEgMS41MSAwIDAgMS0uNDktLjMzIDEuNTcgMS41NyAwIDAgMS0uMzItLjQ5IDEuNTYgMS41NiAwIDAgMSAwLTEuMTggMS41MSAxLjUxIDAgMCAxIDEuNC0uOTMgMS41MyAxLjUzIDAgMCAxIDEuNC45MyAxLjU2IDEuNTYgMCAwIDEgMCAxLjE4Wm0tMS4wMy0uNDRhLjY2LjY2IDAgMCAwIC4zNS0uMTZjLjEtLjEuMTQtLjIzLjE0LS40MWEuNi42IDAgMCAwLS4xOC0uNDdjLS4xMS0uMS0uMy0uMTUtLjU2LS4xNWgtLjh2Mi4xaC4zN3YtLjg2aC4yOWwuNTIuODZoLjRsLS41My0uOTFabS0uMjEtLjNoLS40N3YtLjU5aC40N2EuMzUuMzUgMCAwIDEgLjI3LjEyLjI2LjI2IDAgMCAxIC4wNC4xNmMwIC4wNiAwIC4xMi0uMDQuMTYtLjAzLjA0LS4wNi4wNy0uMTIuMDgtLjA0LjA1LS4xLjA2LS4xNS4wNloiLz4NCjwvc3ZnPg0K);
|
||||
}
|
||||
|
||||
& .app-title {
|
||||
padding-inline: 1.5rem;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 300;
|
||||
line-height: 2.125rem;
|
||||
height: 100%;
|
||||
border-left: 0.25rem solid #00c7fd;
|
||||
}
|
||||
|
||||
& > nav {
|
||||
margin-left: auto;
|
||||
padding-right: 6rem;
|
||||
|
||||
& a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
padding-inline: 1rem;
|
||||
padding-block: 0.85rem;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
background-color: #242528;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.active {
|
||||
box-shadow: inset 0 -0.125rem #00c7fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
ChatQnA/ui_side_by_side/src/main.jsx
Normal file
29
ChatQnA/ui_side_by_side/src/main.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import "./index.css";
|
||||
import "@fontsource/roboto/300.css";
|
||||
import "@fontsource/roboto/400.css";
|
||||
import "@fontsource/roboto/500.css";
|
||||
import "@fontsource/roboto/700.css";
|
||||
import "./App.css";
|
||||
|
||||
import { createTheme, ThemeProvider } from "@mui/material/styles";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
|
||||
import App from "./App";
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
},
|
||||
typography: {
|
||||
fontFamily: ["IntelOneText", "IntelOneDisplay", "sans-serif"],
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
323
ChatQnA/ui_side_by_side/src/pages/chat/ChatPage.jsx
Normal file
323
ChatQnA/ui_side_by_side/src/pages/chat/ChatPage.jsx
Normal file
@@ -0,0 +1,323 @@
|
||||
import "./chat-page.scss";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { SSE } from "sse.js";
|
||||
|
||||
import ResultsService from "../../service/ResultsService";
|
||||
import PromptInput from "./components/prompt-input/PromptInput";
|
||||
import ResultsCards from "./components/results-cards/ResultsCards";
|
||||
import UploadFileDrawer from "./components/upload/UploadFileDrawer";
|
||||
import UploadNotification from "./components/upload-notification/UploadNotification";
|
||||
|
||||
const { VITE_WITH_RAG_BASE_URL, VITE_WITHOUT_RAG_BASE_URL } = import.meta.env;
|
||||
|
||||
const RESULTS_DATA_LOCAL_STORAGE_KEY = "resultsData";
|
||||
|
||||
const resultsDataInitialState = {
|
||||
withoutRAG: [],
|
||||
withRAG: [],
|
||||
};
|
||||
|
||||
const ChatPage = () => {
|
||||
const [resultsData, setResultsData] = useState(resultsDataInitialState);
|
||||
const [resultsLoading, setResultsLoading] = useState({
|
||||
withoutRAG: false,
|
||||
withRAG: false,
|
||||
});
|
||||
const withRAGAnswer = useRef("");
|
||||
const withoutRAGAnswer = useRef("");
|
||||
const [isPromptInputDisabled, setIsPromptInputDisabled] = useState(false);
|
||||
const [showUploadFileDrawer, setShowUploadFileDrawer] = useState(false);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [notification, setNotification] = useState({
|
||||
open: false,
|
||||
message: <span></span>,
|
||||
severity: "success",
|
||||
});
|
||||
const [isClearChatHistoryBtnDisabled, setIsClearChatHistoryBtnDisabled] = useState(true);
|
||||
const isMounted = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const storedResultsData = JSON.parse(localStorage.getItem(RESULTS_DATA_LOCAL_STORAGE_KEY));
|
||||
if (storedResultsData) {
|
||||
setResultsData(storedResultsData);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isMounted.current) {
|
||||
window.localStorage.setItem(RESULTS_DATA_LOCAL_STORAGE_KEY, JSON.stringify(resultsData));
|
||||
} else {
|
||||
isMounted.current = true;
|
||||
}
|
||||
}, [resultsData]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsPromptInputDisabled(Object.values(resultsLoading).some((value) => value));
|
||||
if (!resultsLoading.withRAG) {
|
||||
withRAGAnswer.current = "";
|
||||
}
|
||||
if (!resultsLoading.withoutRAG) {
|
||||
withoutRAGAnswer.current = "";
|
||||
}
|
||||
}, [resultsLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsClearChatHistoryBtnDisabled(
|
||||
Object.values(resultsLoading).some((value) => value) ||
|
||||
Object.values(resultsData).every((arr) => arr.length === 0)
|
||||
);
|
||||
}, [resultsData, resultsLoading]);
|
||||
|
||||
const onConfirmPrompt = (prompt) => {
|
||||
localStorage.setItem("latency_without_rag", null);
|
||||
localStorage.setItem("llm_token_latency_without_rag", null);
|
||||
localStorage.setItem("latency_with_rag", null);
|
||||
localStorage.setItem("llm_token_latency_with_rag", null);
|
||||
localStorage.setItem("retriver_latency", null);
|
||||
localStorage.setItem("input_token_size_without_rag", null);
|
||||
localStorage.setItem("output_token_size_without_rag", null);
|
||||
localStorage.setItem("first_token_latency_without_rag", null);
|
||||
localStorage.setItem("input_token_size_with_rag", null);
|
||||
localStorage.setItem("output_token_size_with_rag", null);
|
||||
localStorage.setItem("first_token_latency_with_rag", null);
|
||||
|
||||
setResultsLoading({
|
||||
withoutRAG: true,
|
||||
withRAG: true,
|
||||
});
|
||||
setIsPromptInputDisabled(true);
|
||||
|
||||
setResultsData((prevState) => ({
|
||||
withoutRAG: [
|
||||
...prevState.withoutRAG,
|
||||
{
|
||||
question: prompt,
|
||||
answer: "",
|
||||
sources: [],
|
||||
},
|
||||
],
|
||||
withRAG: [
|
||||
...prevState.withRAG,
|
||||
{
|
||||
question: prompt,
|
||||
answer: "",
|
||||
sources: [],
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
const urlWithoutRAG = VITE_WITHOUT_RAG_BASE_URL + "/chat_stream";
|
||||
const urlWithRAG = VITE_WITH_RAG_BASE_URL + "/chat_stream";
|
||||
|
||||
const payload = {
|
||||
query: prompt,
|
||||
knowledge_base_id: "default",
|
||||
};
|
||||
|
||||
const eventSourceWithRAG = new SSE(urlWithRAG, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
payload: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
const eventSourceWithoutRAG = new SSE(urlWithoutRAG, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
payload: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
eventSourceWithRAG.addEventListener("readystatechange", function (e) {
|
||||
if (e.readyState === 2) {
|
||||
setResultsLoading((prevState) => ({
|
||||
...prevState,
|
||||
withRAG: false,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
eventSourceWithRAG.addEventListener("message", function (e) {
|
||||
const currentMsgData = e.data;
|
||||
if (currentMsgData !== "") {
|
||||
const response = JSON.parse(e.data);
|
||||
withRAGAnswer.current = response.streamed_text;
|
||||
const sources = Object.values(response.document_metadata).filter((url) => url !== null);
|
||||
setResultsData((prevState) => {
|
||||
const currentPrompt = prevState.withRAG[prevState.withRAG.length - 1];
|
||||
currentPrompt.answer = withRAGAnswer.current;
|
||||
if (sources.length > 0) {
|
||||
currentPrompt.sources = sources;
|
||||
}
|
||||
return {
|
||||
...prevState,
|
||||
withRAG: [...prevState.withRAG.slice(0, -1), currentPrompt],
|
||||
};
|
||||
});
|
||||
|
||||
// with rag metrics
|
||||
const {
|
||||
llm_e2e_latency,
|
||||
llm_token_latency,
|
||||
input_token_size,
|
||||
output_token_size,
|
||||
first_token_latency,
|
||||
retriver_latency,
|
||||
} = response;
|
||||
localStorage.setItem("latency_with_rag", llm_e2e_latency);
|
||||
localStorage.setItem("llm_token_latency_with_rag", llm_token_latency);
|
||||
localStorage.setItem("input_token_size_with_rag", input_token_size);
|
||||
localStorage.setItem("output_token_size_with_rag", output_token_size);
|
||||
localStorage.setItem("first_token_latency_with_rag", first_token_latency);
|
||||
localStorage.setItem("retriver_latency", retriver_latency);
|
||||
}
|
||||
});
|
||||
eventSourceWithRAG.stream();
|
||||
|
||||
eventSourceWithoutRAG.addEventListener("readystatechange", function (e) {
|
||||
if (e.readyState === 2) {
|
||||
setResultsLoading((prevState) => ({
|
||||
...prevState,
|
||||
withoutRAG: false,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
eventSourceWithoutRAG.addEventListener("message", function (e) {
|
||||
const currentMsgData = e.data;
|
||||
if (currentMsgData !== "") {
|
||||
const response = JSON.parse(e.data);
|
||||
withoutRAGAnswer.current = response.streamed_text;
|
||||
setResultsData((prevState) => {
|
||||
const currentPrompt = prevState.withoutRAG[prevState.withoutRAG.length - 1];
|
||||
currentPrompt.answer = withoutRAGAnswer.current;
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
withoutRAG: [...prevState.withoutRAG.slice(0, -1), currentPrompt],
|
||||
};
|
||||
});
|
||||
|
||||
// without rag metrics
|
||||
const {
|
||||
llm_e2e_latency,
|
||||
llm_token_latency,
|
||||
input_token_size,
|
||||
output_token_size,
|
||||
first_token_latency,
|
||||
} = response;
|
||||
localStorage.setItem("latency_without_rag", llm_e2e_latency);
|
||||
localStorage.setItem("llm_token_latency_without_rag", llm_token_latency);
|
||||
localStorage.setItem("input_token_size_without_rag", input_token_size);
|
||||
localStorage.setItem("output_token_size_without_rag", output_token_size);
|
||||
localStorage.setItem("first_token_latency_without_rag", first_token_latency);
|
||||
}
|
||||
});
|
||||
eventSourceWithoutRAG.stream();
|
||||
};
|
||||
|
||||
const clearChatHistory = () => {
|
||||
setResultsData(resultsDataInitialState);
|
||||
};
|
||||
|
||||
const onUploadBtnClick = () => {
|
||||
setShowUploadFileDrawer(true);
|
||||
};
|
||||
|
||||
const onUploadFileDrawerClose = () => {
|
||||
setShowUploadFileDrawer(false);
|
||||
};
|
||||
|
||||
const onConfirmUpload = async (file) => {
|
||||
onUploadFileDrawerClose();
|
||||
if (file instanceof File) {
|
||||
setIsUploading(true);
|
||||
try {
|
||||
const response = await ResultsService.uploadFile(file, file.name);
|
||||
if (response.ok) {
|
||||
setNotification({
|
||||
severity: "success",
|
||||
message: (
|
||||
<span>
|
||||
Your file <b>({file.name})</b> has been successfully uploaded
|
||||
</span>
|
||||
),
|
||||
open: true,
|
||||
});
|
||||
} else {
|
||||
throw response;
|
||||
}
|
||||
} catch (error) {
|
||||
const { status, statusText } = error;
|
||||
setNotification({
|
||||
severity: "error",
|
||||
message: (
|
||||
<span>
|
||||
{statusText} ({status}) when uploading your file <b>({file.name})</b>
|
||||
</span>
|
||||
),
|
||||
open: true,
|
||||
});
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(file)) {
|
||||
setIsUploading(true);
|
||||
try {
|
||||
const response = await ResultsService.uploadFileLink(file);
|
||||
if (response.ok) {
|
||||
setNotification({
|
||||
severity: "success",
|
||||
message: <span>Your {file.length} file links have been successfully uploaded</span>,
|
||||
open: true,
|
||||
});
|
||||
} else {
|
||||
throw response;
|
||||
}
|
||||
} catch (error) {
|
||||
const { status, statusText } = error;
|
||||
setNotification({
|
||||
severity: "error",
|
||||
message: (
|
||||
<span>
|
||||
{statusText} ({status}) when uploading your file link <b>({file})</b>
|
||||
</span>
|
||||
),
|
||||
open: true,
|
||||
});
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onNotificationClose = () => {
|
||||
setNotification((prevState) => ({
|
||||
...prevState,
|
||||
open: false,
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="chat-page">
|
||||
<PromptInput
|
||||
isDisabled={isPromptInputDisabled}
|
||||
isClearChatHistoryBtnDisabled={isClearChatHistoryBtnDisabled}
|
||||
isUploading={isUploading}
|
||||
onConfirmPrompt={onConfirmPrompt}
|
||||
onUploadBtnClick={onUploadBtnClick}
|
||||
onClearChatBtnClick={clearChatHistory}
|
||||
/>
|
||||
<ResultsCards data={resultsData} />
|
||||
<UploadFileDrawer
|
||||
onConfirmUpload={onConfirmUpload}
|
||||
onUploadFileDrawerClose={onUploadFileDrawerClose}
|
||||
show={showUploadFileDrawer}
|
||||
/>
|
||||
<UploadNotification notification={notification} onNotificationClose={onNotificationClose} />
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatPage;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user