From ba35f2d33966e0ea6b1b0f55adaadf8fa9875bd5 Mon Sep 17 00:00:00 2001 From: "Yeoh, Hoong Tee" Date: Tue, 16 Jul 2024 13:07:58 +0530 Subject: [PATCH 01/14] CodeGen: Manifest to deploy CodeGen with ReactUI into Kubernetes Include manifest to deploy CodeGen pipeline with ReactUI into Kubernetes. Include as well README file for the steps. Signed-off-by: Yeoh, Hoong Tee --- .../kubernetes/manifests/xeon/ui/README.md | 36 +++ .../manifests/xeon/ui/react-codegen.yaml | 280 ++++++++++++++++++ 2 files changed, 316 insertions(+) create mode 100644 CodeGen/kubernetes/manifests/xeon/ui/README.md create mode 100644 CodeGen/kubernetes/manifests/xeon/ui/react-codegen.yaml diff --git a/CodeGen/kubernetes/manifests/xeon/ui/README.md b/CodeGen/kubernetes/manifests/xeon/ui/README.md new file mode 100644 index 0000000000..abe6bc822a --- /dev/null +++ b/CodeGen/kubernetes/manifests/xeon/ui/README.md @@ -0,0 +1,36 @@ +# Deploy CodeGen with ReactUI + +The README provides a step-by-step guide on how to deploy CodeGen with ReactUI, a popular React-based user interface library in Kubernetes cluster. + +You can use react-codegen.yaml to deploy CodeGen with reactUI. +``` +kubectl apply -f react-codegen.yaml +``` + +## Prerequisites for Deploying CodeGen with ReactUI: +Before deploying the react-codegen.yaml file, ensure that you have the following prerequisites in place: + +1. Kubernetes installation: Make sure that you have Kubernetes installed. +2. Configuration Values: Set the following values in react-codegen.yaml before proceeding with the deployment: + #### a. HUGGINGFACEHUB_API_TOKEN (Your HuggingFace token to download your desired model from HuggingFace): + ``` + # You may set the HUGGINGFACEHUB_API_TOKEN via method: + export HUGGINGFACEHUB_API_TOKEN="YourOwnToken" + cd GenAIExamples/CodeGen/kubernetes/manifests/xeon/ui/ + sed -i "s/insert-your-huggingface-token-here/${HUGGINGFACEHUB_API_TOKEN}/g" react-codegen.yaml + ``` + #### b. Set the proxies based on your network configuration + ``` + # Look for http_proxy, https_proxy, no_proxy key and fill up the value with your proxy configuration. + ``` +3. MODEL_ID and model-volume (OPTIONAL): You may as well customize the "MODEL_ID" to use different model and model-volume for the volume to be mounted. +4. After completing these, you can proceed with the deployment of the react-codegen.yaml file. + +## Verify Services: +Make sure all the pods are running, you should see total of 4 pods running: +1. codegen +2. codegen-llm-uservice +3. codegen-react-ui +4. codegen-tgi + +You may open up the UI by using the codegen-react-ui endpoint in the browser. \ No newline at end of file diff --git a/CodeGen/kubernetes/manifests/xeon/ui/react-codegen.yaml b/CodeGen/kubernetes/manifests/xeon/ui/react-codegen.yaml new file mode 100644 index 0000000000..9062f6b738 --- /dev/null +++ b/CodeGen/kubernetes/manifests/xeon/ui/react-codegen.yaml @@ -0,0 +1,280 @@ +--- +# Source: codegen/charts/llm-uservice/charts/tgi/templates/service.yaml +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: v1 +kind: Service +metadata: + name: codegen-tgi + labels: + helm.sh/chart: tgi-0.1.0 + app.kubernetes.io/name: tgi + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.4" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: tgi + selector: + app.kubernetes.io/name: tgi + app.kubernetes.io/instance: codegen +--- +apiVersion: v1 +kind: Service +metadata: + name: codegen-llm-uservice + labels: + helm.sh/chart: llm-uservice-0.1.0 + app.kubernetes.io/name: llm-uservice + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + name: llm-uservice + selector: + app.kubernetes.io/name: llm-uservice + app.kubernetes.io/instance: codegen +--- +apiVersion: v1 +kind: Service +metadata: + name: codegen + labels: + helm.sh/chart: codegen-0.1.0 + app.kubernetes.io/name: codegen + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - port: 7778 + targetPort: 7778 + protocol: TCP + name: codegen + selector: + app.kubernetes.io/name: codegen + app.kubernetes.io/instance: codegen +--- +apiVersion: v1 +kind: Service +metadata: + name: codegen-react-ui + labels: + helm.sh/chart: codegen-react-ui-0.1.0 + app.kubernetes.io/name: react-ui + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: react-ui + selector: + app.kubernetes.io/name: react-ui + app.kubernetes.io/instance: codegen +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: codegen-tgi + labels: + helm.sh/chart: tgi-0.1.0 + app.kubernetes.io/name: tgi + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.4" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: tgi + app.kubernetes.io/instance: codegen + template: + metadata: + labels: + app.kubernetes.io/name: tgi + app.kubernetes.io/instance: codegen + spec: + securityContext: {} + containers: + - name: tgi + env: + - name: MODEL_ID + value: ise-uiuc/Magicoder-S-DS-6.7B + - name: PORT + value: "80" + - name: http_proxy + value: + - name: https_proxy + value: + - name: no_proxy + value: + securityContext: {} + image: "ghcr.io/huggingface/text-generation-inference:1.4" + imagePullPolicy: IfNotPresent + volumeMounts: + - mountPath: /data + name: model-volume + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: {} + volumes: + - name: model-volume + hostPath: + path: /mnt + type: Directory +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: codegen-llm-uservice + labels: + helm.sh/chart: llm-uservice-0.1.0 + app.kubernetes.io/name: llm-uservice + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: llm-uservice + app.kubernetes.io/instance: codegen + template: + metadata: + labels: + app.kubernetes.io/name: llm-uservice + app.kubernetes.io/instance: codegen + spec: + securityContext: {} + containers: + - name: codegen + env: + - name: TGI_LLM_ENDPOINT + value: "http://codegen-tgi:80" + - name: HUGGINGFACEHUB_API_TOKEN + value: "insert-your-huggingface-token-here" + - name: http_proxy + value: + - name: https_proxy + value: + - name: no_proxy + value: + securityContext: {} + image: "opea/llm-tgi:latest" + imagePullPolicy: IfNotPresent + ports: + - name: llm-uservice + containerPort: 9000 + protocol: TCP + startupProbe: + exec: + command: + - curl + - http://codegen-tgi:80 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 120 + resources: {} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: codegen + labels: + helm.sh/chart: codegen-0.1.0 + app.kubernetes.io/name: codegen + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: codegen + app.kubernetes.io/instance: codegen + template: + metadata: + labels: + app.kubernetes.io/name: codegen + app.kubernetes.io/instance: codegen + spec: + securityContext: null + containers: + - name: codegen + env: + - name: LLM_SERVICE_HOST_IP + value: codegen-llm-uservice + - name: http_proxy + value: + - name: https_proxy + value: + - name: no_proxy + value: + securityContext: null + image: "opea/codegen:latest" + imagePullPolicy: IfNotPresent + ports: + - name: codegen + containerPort: 7778 + protocol: TCP + resources: null +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: codegen-react-ui + labels: + helm.sh/chart: codegen-react-ui-0.1.0 + app.kubernetes.io/name: react-ui + app.kubernetes.io/instance: codegen + app.kubernetes.io/version: "1.0.0" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: react-ui + app.kubernetes.io/instance: codegen + template: + metadata: + labels: + app.kubernetes.io/name: react-ui + app.kubernetes.io/instance: codegen + spec: + securityContext: null + containers: + - name: codegen-react-ui + env: + - name: BASIC_URL + value: "http://codegen:7778/v1/codegen" + - name: http_proxy + value: + - name: https_proxy + value: + - name: no_proxy + value: + securityContext: null + image: "opea/codegen-react-ui:latest" + imagePullPolicy: IfNotPresent + ports: + - name: react-ui + containerPort: 80 + protocol: TCP + resources: null \ No newline at end of file From e580026d56ff8f4c7aa9e6b77e6a4dc684207007 Mon Sep 17 00:00:00 2001 From: jaswanth8888 Date: Thu, 18 Jul 2024 11:32:06 +0530 Subject: [PATCH 02/14] code-gen-react-ui Signed-off-by: jaswanth8888 --- .github/workflows/scripts/build_push.sh | 3 + CodeGen/docker/ui/docker/Dockerfile.react | 20 +++ CodeGen/docker/ui/react/.env | 2 + CodeGen/docker/ui/react/.eslintrc.cjs | 11 ++ CodeGen/docker/ui/react/.gitignore | 24 ++++ CodeGen/docker/ui/react/README.md | 25 ++++ CodeGen/docker/ui/react/index.html | 18 +++ CodeGen/docker/ui/react/nginx.conf | 20 +++ CodeGen/docker/ui/react/package.json | 51 +++++++ CodeGen/docker/ui/react/postcss.config.cjs | 14 ++ CodeGen/docker/ui/react/public/vite.svg | 1 + CodeGen/docker/ui/react/src/App.scss | 42 ++++++ CodeGen/docker/ui/react/src/App.tsx | 32 +++++ .../ui/react/src/__tests__/util.test.ts | 14 ++ .../ui/react/src/assets/opea-icon-black.svg | 39 +++++ .../ui/react/src/assets/opea-icon-color.svg | 40 ++++++ CodeGen/docker/ui/react/src/assets/react.svg | 1 + CodeGen/docker/ui/react/src/common/client.ts | 8 ++ CodeGen/docker/ui/react/src/common/util.ts | 12 ++ .../react/src/components/CodeGen/CodeGen.tsx | 135 ++++++++++++++++++ .../components/CodeGen/codeGen.module.scss | 59 ++++++++ .../Message/conversationMessage.module.scss | 15 ++ .../Message/conversationMessage.tsx | 56 ++++++++ .../Shared/CodeRender/CodeRender.tsx | 52 +++++++ .../Shared/CodeRender/codeRender.module.scss | 23 +++ .../components/Shared/Markdown/Markdown.tsx | 62 ++++++++ .../Shared/Markdown/markdown.module.scss | 14 ++ .../components/sidebar/sidebar.module.scss | 84 +++++++++++ .../react/src/components/sidebar/sidebar.tsx | 58 ++++++++ CodeGen/docker/ui/react/src/config.ts | 4 + CodeGen/docker/ui/react/src/index.scss | 20 +++ CodeGen/docker/ui/react/src/main.tsx | 13 ++ .../react/src/styles/components/_context.scss | 0 .../react/src/styles/components/_sidebar.scss | 8 ++ .../react/src/styles/components/content.scss | 5 + .../src/styles/components/context.module.scss | 66 +++++++++ .../ui/react/src/styles/layout/_basics.scss | 7 + .../ui/react/src/styles/layout/_flex.scss | 6 + .../docker/ui/react/src/styles/styles.scss | 5 + CodeGen/docker/ui/react/src/vite-env.d.ts | 4 + CodeGen/docker/ui/react/tsconfig.json | 23 +++ CodeGen/docker/ui/react/tsconfig.node.json | 11 ++ CodeGen/docker/ui/react/vite.config.ts | 27 ++++ CodeGen/docker/xeon/docker_compose.yaml | 18 +++ 44 files changed, 1152 insertions(+) create mode 100644 CodeGen/docker/ui/docker/Dockerfile.react create mode 100644 CodeGen/docker/ui/react/.env create mode 100644 CodeGen/docker/ui/react/.eslintrc.cjs create mode 100644 CodeGen/docker/ui/react/.gitignore create mode 100644 CodeGen/docker/ui/react/README.md create mode 100644 CodeGen/docker/ui/react/index.html create mode 100644 CodeGen/docker/ui/react/nginx.conf create mode 100644 CodeGen/docker/ui/react/package.json create mode 100644 CodeGen/docker/ui/react/postcss.config.cjs create mode 100644 CodeGen/docker/ui/react/public/vite.svg create mode 100644 CodeGen/docker/ui/react/src/App.scss create mode 100644 CodeGen/docker/ui/react/src/App.tsx create mode 100644 CodeGen/docker/ui/react/src/__tests__/util.test.ts create mode 100644 CodeGen/docker/ui/react/src/assets/opea-icon-black.svg create mode 100644 CodeGen/docker/ui/react/src/assets/opea-icon-color.svg create mode 100644 CodeGen/docker/ui/react/src/assets/react.svg create mode 100644 CodeGen/docker/ui/react/src/common/client.ts create mode 100644 CodeGen/docker/ui/react/src/common/util.ts create mode 100644 CodeGen/docker/ui/react/src/components/CodeGen/CodeGen.tsx create mode 100644 CodeGen/docker/ui/react/src/components/CodeGen/codeGen.module.scss create mode 100644 CodeGen/docker/ui/react/src/components/Message/conversationMessage.module.scss create mode 100644 CodeGen/docker/ui/react/src/components/Message/conversationMessage.tsx create mode 100644 CodeGen/docker/ui/react/src/components/Shared/CodeRender/CodeRender.tsx create mode 100644 CodeGen/docker/ui/react/src/components/Shared/CodeRender/codeRender.module.scss create mode 100644 CodeGen/docker/ui/react/src/components/Shared/Markdown/Markdown.tsx create mode 100644 CodeGen/docker/ui/react/src/components/Shared/Markdown/markdown.module.scss create mode 100644 CodeGen/docker/ui/react/src/components/sidebar/sidebar.module.scss create mode 100644 CodeGen/docker/ui/react/src/components/sidebar/sidebar.tsx create mode 100644 CodeGen/docker/ui/react/src/config.ts create mode 100644 CodeGen/docker/ui/react/src/index.scss create mode 100644 CodeGen/docker/ui/react/src/main.tsx create mode 100644 CodeGen/docker/ui/react/src/styles/components/_context.scss create mode 100644 CodeGen/docker/ui/react/src/styles/components/_sidebar.scss create mode 100644 CodeGen/docker/ui/react/src/styles/components/content.scss create mode 100644 CodeGen/docker/ui/react/src/styles/components/context.module.scss create mode 100644 CodeGen/docker/ui/react/src/styles/layout/_basics.scss create mode 100644 CodeGen/docker/ui/react/src/styles/layout/_flex.scss create mode 100644 CodeGen/docker/ui/react/src/styles/styles.scss create mode 100644 CodeGen/docker/ui/react/src/vite-env.d.ts create mode 100644 CodeGen/docker/ui/react/tsconfig.json create mode 100644 CodeGen/docker/ui/react/tsconfig.node.json create mode 100644 CodeGen/docker/ui/react/vite.config.ts diff --git a/.github/workflows/scripts/build_push.sh b/.github/workflows/scripts/build_push.sh index 466463a27f..929e8a6293 100755 --- a/.github/workflows/scripts/build_push.sh +++ b/.github/workflows/scripts/build_push.sh @@ -54,6 +54,9 @@ for MEGA_SVC in $1; do docker_build ${IMAGE_NAME}-ui docker/Dockerfile if [ "$MEGA_SVC" == "ChatQnA" ];then docker_build ${IMAGE_NAME}-conversation-ui docker/Dockerfile.react + fi + if [ "$MEGA_SVC" == "CodeGen" ];then + docker_build ${IMAGE_NAME}-react-ui docker/Dockerfile.react fi ;; "VisualQnA") diff --git a/CodeGen/docker/ui/docker/Dockerfile.react b/CodeGen/docker/ui/docker/Dockerfile.react new file mode 100644 index 0000000000..0aa1f5bfa4 --- /dev/null +++ b/CodeGen/docker/ui/docker/Dockerfile.react @@ -0,0 +1,20 @@ +FROM node as vite-app + +COPY . /usr/app +WORKDIR /usr/app/react + +ARG BACKEND_SERVICE_ENDPOINT +ENV VITE_CODE_GEN_URL=$BACKEND_SERVICE_ENDPOINT + +RUN ["npm", "install"] +RUN ["npm", "run", "build"] + + +FROM nginx:alpine +EXPOSE 80 + + +COPY --from=vite-app /usr/app/react/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=vite-app /usr/app/react/dist /usr/share/nginx/html + +ENTRYPOINT ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/CodeGen/docker/ui/react/.env b/CodeGen/docker/ui/react/.env new file mode 100644 index 0000000000..e5d52f4213 --- /dev/null +++ b/CodeGen/docker/ui/react/.env @@ -0,0 +1,2 @@ +VITE_BACKEND_SERVICE_ENDPOINT=http://backend_address:8888/v1/chatqna +VITE_DATA_PREP_SERVICE_URL=http://backend_address:6007/v1/dataprep \ No newline at end of file diff --git a/CodeGen/docker/ui/react/.eslintrc.cjs b/CodeGen/docker/ui/react/.eslintrc.cjs new file mode 100644 index 0000000000..78174f6836 --- /dev/null +++ b/CodeGen/docker/ui/react/.eslintrc.cjs @@ -0,0 +1,11 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + }, +}; diff --git a/CodeGen/docker/ui/react/.gitignore b/CodeGen/docker/ui/react/.gitignore new file mode 100644 index 0000000000..a547bf36d8 --- /dev/null +++ b/CodeGen/docker/ui/react/.gitignore @@ -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? diff --git a/CodeGen/docker/ui/react/README.md b/CodeGen/docker/ui/react/README.md new file mode 100644 index 0000000000..5a9b072871 --- /dev/null +++ b/CodeGen/docker/ui/react/README.md @@ -0,0 +1,25 @@ +

Code Gen

+ +### 📸 Project Screenshots + +![project-screenshot](../../../assets/img/codegen_ui_react.png) + +

🧐 Features

+ +Here're some of the project's features: + +- Generate code: generate the corresponding code based on the current user's input. + +

🛠️ Get it Running:

+ +1. Clone the repo. + +2. cd command to the current folder. + +3. Modify the required .env variables. + ``` + VITE_CODE_GEN_URL = '' + ``` +4. Execute `npm install` to install the corresponding dependencies. + +5. Execute `npm run dev` in both environments diff --git a/CodeGen/docker/ui/react/index.html b/CodeGen/docker/ui/react/index.html new file mode 100644 index 0000000000..fbe87e0fd5 --- /dev/null +++ b/CodeGen/docker/ui/react/index.html @@ -0,0 +1,18 @@ + + + + + + + + + Conversations UI + + +
+ + + diff --git a/CodeGen/docker/ui/react/nginx.conf b/CodeGen/docker/ui/react/nginx.conf new file mode 100644 index 0000000000..00433fcda7 --- /dev/null +++ b/CodeGen/docker/ui/react/nginx.conf @@ -0,0 +1,20 @@ +server { + listen 80; + + gzip on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types font/woff2 text/css application/javascript application/json application/font-woff application/font-tff image/gif image/png image/svg+xml application/octet-stream; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html =404; + + location ~* \.(gif|jpe?g|png|webp|ico|svg|css|js|mp4|woff2)$ { + expires 1d; + } + } +} \ No newline at end of file diff --git a/CodeGen/docker/ui/react/package.json b/CodeGen/docker/ui/react/package.json new file mode 100644 index 0000000000..4b2097ece8 --- /dev/null +++ b/CodeGen/docker/ui/react/package.json @@ -0,0 +1,51 @@ +{ + "name": "ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "@mantine/core": "^7.10.0", + "@mantine/hooks": "^7.10.0", + "@mantine/notifications": "^7.10.2", + "@microsoft/fetch-event-source": "^2.0.1", + "@reduxjs/toolkit": "^2.2.5", + "@tabler/icons-react": "^3.5.0", + "axios": "^1.7.2", + "luxon": "^3.4.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^9.0.1", + "react-syntax-highlighter": "^15.5.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0" + }, + "devDependencies": { + "@testing-library/react": "^16.0.0", + "@types/luxon": "^3.4.2", + "@types/node": "^20.12.12", + "@types/react": "^18.2.66", + "@types/react-dom": "^18.2.22", + "@types/react-syntax-highlighter": "^15.5.13", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/parser": "^7.2.0", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.6", + "jsdom": "^24.1.0", + "postcss": "^8.4.38", + "postcss-preset-mantine": "^1.15.0", + "postcss-simple-vars": "^7.0.1", + "sass": "1.64.2", + "typescript": "^5.2.2", + "vite": "^5.2.13", + "vitest": "^1.6.0" + } +} diff --git a/CodeGen/docker/ui/react/postcss.config.cjs b/CodeGen/docker/ui/react/postcss.config.cjs new file mode 100644 index 0000000000..e817f567be --- /dev/null +++ b/CodeGen/docker/ui/react/postcss.config.cjs @@ -0,0 +1,14 @@ +module.exports = { + plugins: { + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; diff --git a/CodeGen/docker/ui/react/public/vite.svg b/CodeGen/docker/ui/react/public/vite.svg new file mode 100644 index 0000000000..e7b8dfb1b2 --- /dev/null +++ b/CodeGen/docker/ui/react/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CodeGen/docker/ui/react/src/App.scss b/CodeGen/docker/ui/react/src/App.scss new file mode 100644 index 0000000000..187764a179 --- /dev/null +++ b/CodeGen/docker/ui/react/src/App.scss @@ -0,0 +1,42 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +@import "./styles/styles"; + +.root { + @include flex(row, nowrap, flex-start, flex-start); +} + +.layout-wrapper { + @include absolutes; + + display: grid; + + width: 100%; + height: 100%; + + grid-template-columns: 80px auto; + grid-template-rows: 1fr; +} + +/* ===== Scrollbar CSS ===== */ +/* Firefox */ +* { + scrollbar-width: thin; + scrollbar-color: #d6d6d6 #ffffff; +} + +/* Chrome, Edge, and Safari */ +*::-webkit-scrollbar { + width: 8px; +} + +*::-webkit-scrollbar-track { + background: #ffffff; +} + +*::-webkit-scrollbar-thumb { + background-color: #d6d6d6; + border-radius: 16px; + border: 4px double #dedede; +} diff --git a/CodeGen/docker/ui/react/src/App.tsx b/CodeGen/docker/ui/react/src/App.tsx new file mode 100644 index 0000000000..90f3cfb8a8 --- /dev/null +++ b/CodeGen/docker/ui/react/src/App.tsx @@ -0,0 +1,32 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +import "./App.scss" +import { MantineProvider } from "@mantine/core" +import '@mantine/notifications/styles.css'; +import { SideNavbar, SidebarNavList } from "./components/sidebar/sidebar" +import { IconMessages } from "@tabler/icons-react" +import { Notifications } from '@mantine/notifications'; +import CodeGen from "./components/CodeGen/CodeGen"; + +const title = "Code Gen" +const navList: SidebarNavList = [ + { icon: IconMessages, label: title } +] + +function App() { + + return ( + + +
+ +
+ +
+
+
+ ) +} + +export default App diff --git a/CodeGen/docker/ui/react/src/__tests__/util.test.ts b/CodeGen/docker/ui/react/src/__tests__/util.test.ts new file mode 100644 index 0000000000..e67ba2c86a --- /dev/null +++ b/CodeGen/docker/ui/react/src/__tests__/util.test.ts @@ -0,0 +1,14 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +import { describe, expect, test } from "vitest"; +import { getCurrentTimeStamp, uuidv4 } from "../common/util"; + +describe("unit tests", () => { + test("check UUID is of length 36", () => { + expect(uuidv4()).toHaveLength(36); + }); + test("check TimeStamp generated is of unix", () => { + expect(getCurrentTimeStamp()).toBe(Math.floor(Date.now() / 1000)); + }); +}); diff --git a/CodeGen/docker/ui/react/src/assets/opea-icon-black.svg b/CodeGen/docker/ui/react/src/assets/opea-icon-black.svg new file mode 100644 index 0000000000..5c96dc7622 --- /dev/null +++ b/CodeGen/docker/ui/react/src/assets/opea-icon-black.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CodeGen/docker/ui/react/src/assets/opea-icon-color.svg b/CodeGen/docker/ui/react/src/assets/opea-icon-color.svg new file mode 100644 index 0000000000..790151171e --- /dev/null +++ b/CodeGen/docker/ui/react/src/assets/opea-icon-color.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CodeGen/docker/ui/react/src/assets/react.svg b/CodeGen/docker/ui/react/src/assets/react.svg new file mode 100644 index 0000000000..6c87de9bb3 --- /dev/null +++ b/CodeGen/docker/ui/react/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CodeGen/docker/ui/react/src/common/client.ts b/CodeGen/docker/ui/react/src/common/client.ts new file mode 100644 index 0000000000..7512f73e33 --- /dev/null +++ b/CodeGen/docker/ui/react/src/common/client.ts @@ -0,0 +1,8 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +import axios from "axios"; + +//add iterceptors to add any request headers + +export default axios; diff --git a/CodeGen/docker/ui/react/src/common/util.ts b/CodeGen/docker/ui/react/src/common/util.ts new file mode 100644 index 0000000000..df65b2d8e0 --- /dev/null +++ b/CodeGen/docker/ui/react/src/common/util.ts @@ -0,0 +1,12 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +export const getCurrentTimeStamp = () => { + return Math.floor(Date.now() / 1000); +}; + +export const uuidv4 = () => { + return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => + (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))).toString(16), + ); +}; diff --git a/CodeGen/docker/ui/react/src/components/CodeGen/CodeGen.tsx b/CodeGen/docker/ui/react/src/components/CodeGen/CodeGen.tsx new file mode 100644 index 0000000000..8d35d89ab0 --- /dev/null +++ b/CodeGen/docker/ui/react/src/components/CodeGen/CodeGen.tsx @@ -0,0 +1,135 @@ +// Copyright (C) 2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +import { KeyboardEventHandler, SyntheticEvent, useEffect, useRef, useState } from 'react' +import styleClasses from "./codeGen.module.scss" +import { ActionIcon, Textarea, Title, rem } from '@mantine/core' +import { IconArrowRight } from '@tabler/icons-react' +import { ConversationMessage } from '../Message/conversationMessage' +import { fetchEventSource } from '@microsoft/fetch-event-source' +import { CODE_GEN_URL } from '../../config' + + + +const CodeGen = () => { + const [prompt, setPrompt] = useState("") + const [submittedPrompt, setSubmittedPrompt] = useState("") + const [response,setResponse] = useState(""); + const promptInputRef = useRef(null) + const scrollViewport = useRef(null) + + const toSend = "Enter" + + const handleSubmit = async () => { + setResponse("") + setSubmittedPrompt(prompt) + const body = { + messages:prompt + } + fetchEventSource(CODE_GEN_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Accept":"*/*" + }, + body: JSON.stringify(body), + openWhenHidden: true, + async onopen(response) { + if (response.ok) { + return; + } else if (response.status >= 400 && response.status < 500 && response.status !== 429) { + const e = await response.json(); + console.log(e); + throw Error(e.error.message); + } else { + console.log("error", response); + } + }, + onmessage(msg) { + if (msg?.data != "[DONE]") { + try { + const match = msg.data.match(/b'([^']*)'/); + if (match && match[1] != "") { + const extractedText = match[1].replace(/\\n/g, "\n"); + setResponse(prev=>prev+extractedText); + } + } catch (e) { + console.log("something wrong in msg", e); + throw e; + } + } + }, + onerror(err) { + console.log("error", err); + setResponse("") + throw err; + }, + onclose() { + setPrompt("") + }, + }); + + } + + const scrollToBottom = () => { + scrollViewport.current!.scrollTo({ top: scrollViewport.current!.scrollHeight }) + } + + useEffect(() => { + scrollToBottom() + }, [response]) + + const handleKeyDown: KeyboardEventHandler = (event) => { + if (!event.shiftKey && event.key === toSend) { + handleSubmit() + setTimeout(() => { + setPrompt("") + }, 1) + } + } + + const handleChange = (event: SyntheticEvent) => { + event.preventDefault() + setPrompt((event.target as HTMLTextAreaElement).value) + } + return ( +
+
+
+
+ CodeGen +
+ +
+ {submittedPrompt && ( + + )} + {response && ( + + )} +
+ +
+