├── .github ├── ISSUE_TEMPLATE │ ├── 1-feature_request.md │ └── 2-bug_report.md ├── pull_request_template.md └── workflows │ ├── bandit.yml │ ├── build-installer.yml │ ├── eslint-prettier.yml │ ├── ruff.yml │ └── trivy.yml ├── .gitignore ├── .idea └── .gitignore ├── 3rdpartynoticeslicenses.txt ├── AI Playground Users Guide.pdf ├── AI Playground Users Guide_v1.21b.pdf ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── LlamaCPP ├── .gitignore ├── llama_adapter.py ├── llama_cpp_backend.py ├── llama_cpp_embeddings.py ├── llama_web_api.py └── requirements.txt ├── OpenVINO ├── .gitignore ├── openvino_adapter.py ├── openvino_backend.py ├── openvino_embeddings.py ├── openvino_web_api.py └── requirements.txt ├── Port-OV-Models.md ├── SECURITY.md ├── WebUI ├── .editorconfig ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── app.ico ├── build │ ├── README.md │ ├── build-config.json │ ├── installSection.nsh │ ├── installUtil.nsh │ ├── installer.nsh │ ├── license.rtf │ ├── scripts │ │ ├── check-i18n.js │ │ ├── fetch-python-package-resources.js │ │ ├── install-full-python-env.js │ │ ├── patch-nsis-template.js │ │ ├── prepare-python-env.js │ │ └── provide-electron-build-resources.js │ └── settings.json ├── components.json ├── electron │ ├── electron-env.d.ts │ ├── logging │ │ └── logger.ts │ ├── main.ts │ ├── pathsManager.ts │ ├── preload.ts │ ├── subprocesses │ │ ├── aiBackendService.ts │ │ ├── apiServiceRegistry.ts │ │ ├── comfyUIBackendService.ts │ │ ├── deviceArch.ts │ │ ├── langchain.ts │ │ ├── llamaCppBackendService.ts │ │ ├── mediaServer.ts │ │ ├── openVINOBackendService.ts │ │ ├── osProcessHelper.ts │ │ ├── service.ts │ │ └── updateIntelWorkflows.ts │ ├── test │ │ └── subprocesses │ │ │ ├── deviceArch.test.ts │ │ │ └── service.test.ts │ └── util.ts ├── eslint.config.ts ├── external │ ├── model_config.dev.json │ ├── model_config.json │ ├── settings-dev.json │ └── workflows │ │ ├── Colorize.json │ │ ├── CopyFace.json │ │ ├── FaceSwapHD.json │ │ ├── LTX-Video_9.5_Start-End.json │ │ ├── LTX-Video_9.5_T2V-v2.json │ │ ├── LTX-Video_9.6_I2V.json │ │ ├── Line2ImageHD-Fast.json │ │ ├── Line2ImageHD-Quality.json │ │ ├── fluxQ4.json │ │ └── fluxQ8.json ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── public │ ├── A1111.png │ ├── AI_Playground.png │ ├── ComfyUI.png │ ├── Fooocus.png │ ├── Intel_Insiders.png │ ├── SDNext.png │ └── TechCraftVideos.png ├── src │ ├── App.vue │ ├── assets │ │ ├── css │ │ │ ├── compontents.css │ │ │ ├── index.css │ │ │ ├── main.css │ │ │ ├── pc.css │ │ │ ├── svg.css │ │ │ ├── theme.css │ │ │ └── vertical.css │ │ ├── fonts │ │ │ ├── intelone-display-bold.woff2 │ │ │ ├── intelone-display-light.woff2 │ │ │ ├── intelone-display-medium.woff2 │ │ │ └── intelone-display-regular.woff2 │ │ ├── i18n │ │ │ ├── de.json │ │ │ ├── en-US.json │ │ │ ├── es.json │ │ │ ├── id.json │ │ │ ├── it.json │ │ │ ├── ja.json │ │ │ ├── ko.json │ │ │ ├── pl.json │ │ │ ├── th.json │ │ │ ├── tr.json │ │ │ ├── vi.json │ │ │ ├── zh-CN.json │ │ │ └── zh-TW.json │ │ ├── image │ │ │ ├── arc-graphics-environments-3color-pattern-full.jpg │ │ │ ├── arc_graphics_badge.png │ │ │ ├── core_ultra_badge.png │ │ │ └── nsfw_result_detected.png │ │ ├── js │ │ │ ├── clientAPI.ts │ │ │ ├── const.ts │ │ │ ├── markdownParser.ts │ │ │ ├── sseProcessor.ts │ │ │ ├── store │ │ │ │ ├── backendServices.ts │ │ │ │ ├── comfyUi.ts │ │ │ │ ├── conversations.ts │ │ │ │ ├── globalSetup.ts │ │ │ │ ├── i18n.ts │ │ │ │ ├── imageGeneration.ts │ │ │ │ ├── models.ts │ │ │ │ ├── stableDiffusion.ts │ │ │ │ ├── textInference.ts │ │ │ │ └── theme.ts │ │ │ ├── toast.ts │ │ │ └── util.ts │ │ └── svg │ │ │ ├── add-box.svg │ │ │ ├── add.svg │ │ │ ├── ai-icon.svg │ │ │ ├── aipg.svg │ │ │ ├── arrow-down.svg │ │ │ ├── arrow-right.svg │ │ │ ├── arrow-up.svg │ │ │ ├── audio.svg │ │ │ ├── broom.svg │ │ │ ├── check.svg │ │ │ ├── clear.svg │ │ │ ├── close.svg │ │ │ ├── collapse.svg │ │ │ ├── copy.svg │ │ │ ├── delete.svg │ │ │ ├── dice.svg │ │ │ ├── download-cloud.svg │ │ │ ├── download.svg │ │ │ ├── easer.svg │ │ │ ├── expand.svg │ │ │ ├── folder.svg │ │ │ ├── fullscreen-exit.svg │ │ │ ├── fullscreen.svg │ │ │ ├── generate-add.svg │ │ │ ├── hide-history.svg │ │ │ ├── history.svg │ │ │ ├── info.svg │ │ │ ├── intel.svg │ │ │ ├── loading.svg │ │ │ ├── md.svg │ │ │ ├── mini.svg │ │ │ ├── outpaint-bg.svg │ │ │ ├── outpaint-dir.svg │ │ │ ├── pdf.svg │ │ │ ├── pen.svg │ │ │ ├── ppt.svg │ │ │ ├── queue.svg │ │ │ ├── radio-checked.svg │ │ │ ├── rag-off.svg │ │ │ ├── rag-on.svg │ │ │ ├── refresh.svg │ │ │ ├── reset.svg │ │ │ ├── right-arrow.svg │ │ │ ├── right.svg │ │ │ ├── setup.svg │ │ │ ├── slide-bar.svg │ │ │ ├── stop.svg │ │ │ ├── tab-active-first.svg │ │ │ ├── tab-active.svg │ │ │ ├── toggle.svg │ │ │ ├── transfer.svg │ │ │ ├── txt.svg │ │ │ ├── uncheck.svg │ │ │ ├── upload.svg │ │ │ ├── user-icon.svg │ │ │ ├── video.svg │ │ │ ├── warning-triangle.svg │ │ │ ├── word.svg │ │ │ ├── zoom-in.svg │ │ │ └── zoom-out.svg │ ├── auto-import.d.ts │ ├── components │ │ ├── AddLLMDialog.vue │ │ ├── BackendOptions.vue │ │ ├── Checkbox.vue │ │ ├── ComfyUIDownloadDialog.vue │ │ ├── DownloadDialog.vue │ │ ├── DropDownNew.vue │ │ ├── DropSelector.vue │ │ ├── FolderSelector.vue │ │ ├── ImagePromptOptions.vue │ │ ├── InfoTable.vue │ │ ├── InpaintMask.vue │ │ ├── InpaintOptions.vue │ │ ├── InstallationManagement.vue │ │ ├── LanguageSelector.vue │ │ ├── LoadingBar.vue │ │ ├── ModelDropDownItem.vue │ │ ├── OutpaintOptions.vue │ │ ├── ProgressBar.vue │ │ ├── Radio.vue │ │ ├── RadioBlock.vue │ │ ├── Rag.vue │ │ ├── RandomNumber.vue │ │ ├── SettingsBasic.vue │ │ ├── SettingsImageComfyDynamic.vue │ │ ├── SettingsImageGeneration.vue │ │ ├── SettingsImageWorkflowSelector.vue │ │ ├── SettingsModel.vue │ │ ├── SlideBar.vue │ │ ├── TextToImage.vue │ │ ├── UpscaleOptions.vue │ │ ├── VerticalSlideBar.vue │ │ ├── WarningDialog.vue │ │ └── ui │ │ │ ├── aipgInput │ │ │ ├── Input.vue │ │ │ └── index.ts │ │ │ ├── alert-dialog │ │ │ ├── AlertDialog.vue │ │ │ ├── AlertDialogAction.vue │ │ │ ├── AlertDialogCancel.vue │ │ │ ├── AlertDialogContent.vue │ │ │ ├── AlertDialogDescription.vue │ │ │ ├── AlertDialogFooter.vue │ │ │ ├── AlertDialogHeader.vue │ │ │ ├── AlertDialogTitle.vue │ │ │ ├── AlertDialogTrigger.vue │ │ │ └── index.ts │ │ │ ├── button │ │ │ ├── Button.vue │ │ │ └── index.ts │ │ │ ├── collapsible │ │ │ ├── Collapsible.vue │ │ │ ├── CollapsibleContent.vue │ │ │ ├── CollapsibleTrigger.vue │ │ │ └── index.ts │ │ │ ├── dialog │ │ │ ├── Dialog.vue │ │ │ ├── DialogClose.vue │ │ │ ├── DialogContent.vue │ │ │ ├── DialogDescription.vue │ │ │ ├── DialogFooter.vue │ │ │ ├── DialogHeader.vue │ │ │ ├── DialogScrollContent.vue │ │ │ ├── DialogTitle.vue │ │ │ ├── DialogTrigger.vue │ │ │ └── index.ts │ │ │ ├── dropdown-menu │ │ │ ├── DropdownMenu.vue │ │ │ ├── DropdownMenuCheckboxItem.vue │ │ │ ├── DropdownMenuContent.vue │ │ │ ├── DropdownMenuGroup.vue │ │ │ ├── DropdownMenuItem.vue │ │ │ ├── DropdownMenuLabel.vue │ │ │ ├── DropdownMenuRadioGroup.vue │ │ │ ├── DropdownMenuRadioItem.vue │ │ │ ├── DropdownMenuSeparator.vue │ │ │ ├── DropdownMenuShortcut.vue │ │ │ ├── DropdownMenuSub.vue │ │ │ ├── DropdownMenuSubContent.vue │ │ │ ├── DropdownMenuSubTrigger.vue │ │ │ ├── DropdownMenuTrigger.vue │ │ │ └── index.ts │ │ │ ├── form │ │ │ ├── FormControl.vue │ │ │ ├── FormDescription.vue │ │ │ ├── FormItem.vue │ │ │ ├── FormLabel.vue │ │ │ ├── FormMessage.vue │ │ │ ├── index.ts │ │ │ ├── injectionKeys.ts │ │ │ └── useFormField.ts │ │ │ ├── input │ │ │ ├── Input.vue │ │ │ └── index.ts │ │ │ ├── label │ │ │ ├── Label.vue │ │ │ └── index.ts │ │ │ ├── loadImage │ │ │ ├── LoadImage.vue │ │ │ └── index.ts │ │ │ └── slider │ │ │ ├── ResolutionPicker.vue │ │ │ └── index.ts │ ├── env.d.ts │ ├── lib │ │ └── utils.ts │ ├── main.ts │ ├── toast.d.ts │ ├── views │ │ ├── Answer.vue │ │ ├── AppSettings.vue │ │ ├── Create.vue │ │ ├── Enhance.vue │ │ └── LearnMore.vue │ └── vite-env.d.ts ├── tailwind.config.cjs ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── vitest.config.ts ├── backend-shared ├── .gitignore ├── __init__.py ├── adapter.py ├── config.py ├── interface.py ├── interface_adapter.py ├── params.py └── utils.py ├── device-service ├── xpu-smi.exe └── xpum.dll ├── docs └── arc42 │ ├── AI-PG_ComponentView.svg │ ├── AI-PG_ContextView.svg │ ├── AI-PG_views.drawio │ └── arc42_doc.md ├── notices-disclaimers.md ├── readme.md ├── service ├── .gitignore ├── aipg_utils.py ├── attention.py ├── build_dowloader.bat ├── comfyui_downloader.py ├── downloader.py ├── exceptions.py ├── file_downloader.py ├── inpaint_utils.py ├── ipex_embedding.py ├── lama.py ├── llm_adapter.py ├── llm_biz.py ├── main.py ├── model_config.json ├── model_download_adpater.py ├── model_downloader.py ├── models │ └── stable_diffusion │ │ ├── ESRGAN │ │ └── RealESRGAN_x2plus.pth │ │ └── preview │ │ ├── madebyollin---taesd │ │ ├── config.json │ │ ├── diffusion_pytorch_model.safetensors │ │ ├── taesd_decoder.safetensors │ │ └── taesd_encoder.safetensors │ │ └── madebyollin---taesdxl │ │ ├── config.json │ │ ├── diffusion_pytorch_model.safetensors │ │ ├── taesdxl_decoder.safetensors │ │ └── taesdxl_encoder.safetensors ├── outpaint_utils.py ├── paint_biz.py ├── rag.py ├── real_esrgan_patch.py ├── realesrgan.py ├── requirements-ipex-llm.txt ├── requirements-xpu.txt ├── requirements.txt ├── schedulers_util.py ├── sd_adapter.py ├── service_adapter.py ├── service_config.py ├── static │ └── assets │ │ ├── aipg.png │ │ ├── history.css │ │ ├── history.js │ │ └── history_template.html ├── tests │ └── test_api.py ├── tools │ ├── ls_level_zero.cpp │ ├── ls_level_zero.exe │ └── move_model_files.py ├── web_api.py └── web_request_bodies.py └── workflows-document.md /.github/ISSUE_TEMPLATE/1-feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Is your feature request related to a problem? Please describe. 11 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | ## Describe the solution you'd like 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | ## Describe alternatives you've considered 19 | 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | ## Additional context 23 | 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | ## To Reproduce 15 | 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | ## Expected behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ## Screenshots 27 | 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | ## Environment (please complete the following information): 31 | 32 | - OS: [e.g. Windows11] 33 | - GPU: [e.g. Intel Arc A770 16G] 34 | - CPU: [e.g. i9-13900] 35 | - Version: [e.g. v1.01b-MTL-H] 36 | 37 | ## Additional context 38 | 39 | Add any other context about the problem here. 40 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | **Description:** 2 | 3 | Please provide a brief description of the changes made in this pull request. 4 | 5 | **Related Issue:** 6 | 7 | If this pull request is related to any existing issue, please mention the issue number here. 8 | 9 | **Changes Made:** 10 | 11 | Please list down the specific changes made in this pull request. 12 | 13 | **Testing Done:** 14 | 15 | Please describe the testing that has been done to ensure the changes made in this pull request are functioning as expected. 16 | 17 | **Screenshots:** 18 | 19 | If applicable, please provide screenshots or GIFs or videos to visually demonstrate the changes made. 20 | 21 | **Checklist:** 22 | 23 | - [ ] I have tested the changes locally. 24 | - [ ] I have self-reviewed the code changes. 25 | - [ ] I have updated the documentation, if necessary. 26 | -------------------------------------------------------------------------------- /.github/workflows/bandit.yml: -------------------------------------------------------------------------------- 1 | name: Bandit 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | pull_request: 9 | branches: 10 | - main 11 | - dev 12 | 13 | jobs: 14 | analyze: 15 | runs-on: ubuntu-latest 16 | permissions: 17 | # required for all workflows 18 | security-events: write 19 | steps: 20 | - name: Perform Bandit Analysis 21 | uses: PyCQA/bandit-action@v1 22 | -------------------------------------------------------------------------------- /.github/workflows/build-installer.yml: -------------------------------------------------------------------------------- 1 | name: build installer 2 | 3 | run-name: installer-build-${{ github.sha }} 4 | 5 | on: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-installer: 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v3 15 | 16 | - name: setup miniforge 17 | uses: conda-incubator/setup-miniconda@v3 18 | with: 19 | miniforge-version: latest 20 | channels: conda-forge 21 | conda-remove-defaults: "true" 22 | python-version: "3.11" 23 | activate-environment: 'cp311_libuv' 24 | 25 | - name: Install libuv dependency 26 | run: | 27 | conda install -y libuv 28 | conda env list | findstr libuv 29 | echo "LIBUV_DLLS_PATH=$($(conda env list | findstr libuv) -split ' ' | Select-Object -Last 1)\Library\bin" 30 | echo "LIBUV_DLLS_PATH=$($(conda env list | findstr libuv) -split ' ' | Select-Object -Last 1)\Library\bin" >> $env:GITHUB_ENV 31 | 32 | - name: copy libuv dlls to workspace 33 | run: | 34 | New-Item -ItemType Directory -Path "python_package_res\conda\Library\bin" -Force 35 | copy "${{ env.LIBUV_DLLS_PATH }}\*.dll" "python_package_res\conda\Library\bin" 36 | 37 | - name: Install Node.js and npm 38 | uses: actions/setup-node@v3 39 | with: 40 | node-version: '20' 41 | 42 | - name: setup npm project 43 | working-directory: "WebUI" 44 | run: npm install 45 | 46 | - name: build installer 47 | working-directory: "WebUI" 48 | run: | 49 | npm run fetch-build-resources -- --conda_env_dir=../python_package_res/conda 50 | npm run prepare-build 51 | npm run build 52 | 53 | - name: set release path 54 | working-directory: "release" 55 | run: | 56 | echo "RELEASE_DIR=$((pwd).Path)" 57 | echo "RELEASE_DIR=$((pwd).Path)" >> $env:GITHUB_ENV 58 | 59 | - name: upload release 60 | uses: actions/upload-artifact@v4 61 | with: 62 | name: "installers-${{ github.sha }}" 63 | path: ${{ env.RELEASE_DIR }}\*.exe 64 | if-no-files-found: error 65 | retention-days: 1 66 | overwrite: true 67 | -------------------------------------------------------------------------------- /.github/workflows/eslint-prettier.yml: -------------------------------------------------------------------------------- 1 | name: Lint TS 2 | on: [push, pull_request] 3 | jobs: 4 | lint-ts: 5 | runs-on: ubuntu-latest 6 | defaults: 7 | run: 8 | working-directory: ./WebUI 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-node@v4 12 | with: 13 | node-version: 20 14 | - run: npm ci 15 | - run: npm run lint:ci 16 | - run: npm run format:ci 17 | -------------------------------------------------------------------------------- /.github/workflows/ruff.yml: -------------------------------------------------------------------------------- 1 | name: Ruff 2 | on: [push, pull_request] 3 | jobs: 4 | ruff: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v4 8 | - uses: astral-sh/ruff-action@v1 9 | with: 10 | src: "./service" 11 | changed-files: "true" 12 | -------------------------------------------------------------------------------- /.github/workflows/trivy.yml: -------------------------------------------------------------------------------- 1 | name: Trivy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - dev 7 | pull_request: 8 | branches: 9 | - main 10 | - dev 11 | jobs: 12 | trivy-scan: 13 | name: Trivy Scan 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v4 18 | 19 | - name: Run Trivy vulnerability scanner in repo mode 20 | uses: aquasecurity/trivy-action@0.28.0 21 | with: 22 | scan-type: 'fs' 23 | ignore-unfixed: true 24 | format: 'sarif' 25 | output: 'trivy-results.sarif' 26 | severity: 'CRITICAL, HIGH, MEDIUM, LOW' 27 | 28 | - name: Upload trivy results 29 | uses: actions/upload-artifact@v4 30 | with: 31 | name: trivy-results 32 | path: trivy-results.sarif 33 | 34 | - name: Upload Trivy scan results to GitHub Security tab 35 | uses: github/codeql-action/upload-sarif@v3 36 | with: 37 | sarif_file: 'trivy-results.sarif' 38 | trivy-sbom: 39 | name: Trivy dependency map 40 | runs-on: ubuntu-latest 41 | steps: 42 | - name: Checkout code 43 | uses: actions/checkout@v4 44 | 45 | - name: Run Trivy in GitHub SBOM mode and submit results to Dependency Graph 46 | uses: aquasecurity/trivy-action@0.28.0 47 | with: 48 | scan-type: 'fs' 49 | format: 'spdx' 50 | output: 'dependency-results.sbom.json' 51 | image-ref: '.' 52 | github-pat: ${{ secrets.GITHUB_TOKEN }} 53 | env: 54 | TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db,aquasec/trivy-db,ghcr.io/aquasecurity/trivy-db 55 | 56 | - name: Upload trivy dependency map 57 | uses: actions/upload-artifact@v4 58 | with: 59 | name: trivy-dependencies 60 | path: dependency-results.sbom.json 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | env/ 3 | package_res/ 4 | build_resources/ 5 | build_envs/ 6 | release/ 7 | WebUI/external/device-service/ 8 | WebUI/external/service/ 9 | WebUI/external/workflows_intel/ 10 | WebUI/external/workflows_bak/ 11 | 12 | 7zr.exe 13 | *.7z 14 | *.whl 15 | hijacks/ 16 | ComfyUI/ 17 | env 18 | llama-cpp-env/ 19 | *env_tmp/ 20 | *service_tmp/ 21 | *-env/ 22 | build-envs/ 23 | portable-git/ 24 | llm_cache/* 25 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /AI Playground Users Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/AI Playground Users Guide.pdf -------------------------------------------------------------------------------- /AI Playground Users Guide_v1.21b.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/AI Playground Users Guide_v1.21b.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Intel Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LlamaCPP/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | models/llm/ 4 | temp/ 5 | test/ 6 | dist/ 7 | build/ 8 | cache/ 9 | test/ 10 | env/ 11 | 12 | !tools/*.exe 13 | -------------------------------------------------------------------------------- /LlamaCPP/llama_cpp_backend.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Callable 2 | from os import path 3 | from interface import LLMInterface 4 | from params import LLMParams 5 | from llama_cpp import CreateChatCompletionStreamResponse, Iterator, Llama 6 | import config 7 | import gc 8 | 9 | class LlamaCpp(LLMInterface): 10 | def __init__(self): 11 | self._model = None 12 | self.stop_generate = False 13 | self._last_repo_id = None 14 | 15 | def load_model(self, params: LLMParams, n_gpu_layers: int = -1, context_length: int = 16000, callback: Callable[[str], None] = None): 16 | model_repo_id = params.model_repo_id 17 | if self._model is None or self._last_repo_id != model_repo_id: 18 | if callback is not None: 19 | callback("start") 20 | self.unload_model() 21 | 22 | model_base_path = config.llama_cpp_model_paths.get("ggufLLM") 23 | namespace, repo, *model = model_repo_id.split("/") 24 | model_path = path.abspath(path.join(model_base_path,"---".join([namespace, repo]), "---".join(model))) 25 | 26 | self._model = Llama( 27 | model_path=model_path, 28 | n_gpu_layers=n_gpu_layers, 29 | n_ctx=context_length, 30 | verbose=False, 31 | ) 32 | 33 | self._last_repo_id = model_repo_id 34 | if callback is not None: 35 | callback("finish") 36 | 37 | def create_chat_completion(self, messages: List[Dict[str, str]], max_tokens: int = 1024): 38 | completion: Iterator[CreateChatCompletionStreamResponse] = self._model.create_chat_completion( 39 | messages=messages, 40 | max_tokens=max_tokens, 41 | stream=True, 42 | ) 43 | return completion 44 | 45 | def unload_model(self): 46 | if self._model is not None: 47 | self._model.close() 48 | del self._model 49 | gc.collect() 50 | self._model = None 51 | 52 | def get_backend_type(self): 53 | return "llama_cpp" -------------------------------------------------------------------------------- /LlamaCPP/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==3.0.3 2 | apiflask==2.3.0 3 | dpcpp-cpp-rt==2025.0 4 | mkl-dpcpp==2025.0 5 | intel-sycl-rt==2025.0.0 6 | onednn-devel==2025.0.0 7 | langchain_community==0.3.0 -------------------------------------------------------------------------------- /OpenVINO/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | models/llm/ 4 | temp/ 5 | test/ 6 | dist/ 7 | build/ 8 | cache/ 9 | test/ 10 | env/ 11 | 12 | !tools/*.exe 13 | llm_cache/ 14 | TinyLlama-* 15 | laion/ 16 | db/ -------------------------------------------------------------------------------- /OpenVINO/openvino_adapter.py: -------------------------------------------------------------------------------- 1 | from interface_adapter import InterfaceAdapter 2 | from interface import LLMInterface 3 | 4 | class LLM_SSE_Adapter(InterfaceAdapter): 5 | """ 6 | Adapter for the OpenVINO backend. 7 | This class extends InterfaceAdapter to maintain backward compatibility. 8 | """ 9 | 10 | def __init__(self, llm_interface: LLMInterface): 11 | """Initialize the adapter with an LLMInterface instance.""" 12 | super().__init__(llm_interface) 13 | -------------------------------------------------------------------------------- /OpenVINO/openvino_backend.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Callable 2 | from os import path 3 | from interface import LLMInterface 4 | from params import LLMParams 5 | import config 6 | import openvino_genai 7 | import gc 8 | 9 | class OpenVino(LLMInterface): 10 | def __init__(self): 11 | self._model = None 12 | self.stop_generate = False 13 | self._last_repo_id = None 14 | 15 | def load_model(self, params: LLMParams, callback: Callable[[str], None] = None): 16 | model_repo_id = params.model_repo_id 17 | if self._model is None or self._last_repo_id != model_repo_id: 18 | if callback is not None: 19 | callback("start") 20 | self.unload_model() 21 | callback(params.model_repo_id) 22 | 23 | model_base_path = config.openvino_model_paths.get("openvinoLLM") 24 | model_name = model_repo_id.replace("/", "---") 25 | model_path = path.abspath(path.join(model_base_path, model_name)) 26 | 27 | enable_compile_cache = dict() 28 | enable_compile_cache["CACHE_DIR"] = "llm_cache" 29 | self._model = openvino_genai.LLMPipeline(model_path, "AUTO", **enable_compile_cache) 30 | self._tokenizer = self._model.get_tokenizer() 31 | 32 | self._last_repo_id = model_repo_id 33 | if callback is not None: 34 | callback("finish") 35 | 36 | 37 | def create_chat_completion(self, messages: List[Dict[str, str]], streamer: Callable[[str], None], max_tokens: int = 1024): 38 | config = openvino_genai.GenerationConfig() 39 | config.max_new_tokens = max_tokens 40 | 41 | full_prompt = self._tokenizer.apply_chat_template(messages, add_generation_prompt=True) 42 | return self._model.generate(full_prompt, config, streamer) 43 | 44 | 45 | def unload_model(self): 46 | if self._model is not None: 47 | del self._model 48 | gc.collect() 49 | self._model = None 50 | 51 | def get_backend_type(self): 52 | return "openvino" -------------------------------------------------------------------------------- /OpenVINO/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==3.0.3 2 | apiflask==2.3.0 3 | openvino==2025.1.0.0 4 | openvino-genai==2025.1.0.0 5 | openvino-tokenizers==2025.1.0.0 6 | langchain_community==0.3.0 7 | optimum[openvino]==1.24.0 8 | -------------------------------------------------------------------------------- /Port-OV-Models.md: -------------------------------------------------------------------------------- 1 | ## How to port models to OpenVINO format and add to AI Playground manually. 2 | 3 | This document will walk you through the steps to port a model to the IR format for use in AI Playground using OpenVINO. This document is in draft (WIP) 4 | 5 | 1. Make sure, that AI Playground is installed on your PC. 6 | 2. Create a folder in AI Playground 7 | \AI Playground\resources\service\models\llm\openvino\OpenVINO--- 8 | 9 | For example, to add Phi-4-mini-instruct model with int4 quantization you can create such folder. 10 | \AI Playground\resources\service\models\llm\openvino\OpenVINO---Phi-4-mini-instruct-int4-ov 11 | ![image](https://github.com/user-attachments/assets/247f6e2c-380c-4d8a-99cf-b5de69ad2d4a) 12 | 13 | 3. To be used in AI Playground, the model must be converted to OpenVINO IR format first. The most convenient approach to convert the models is by using the corresponding OpenVINO notebook. Please follow the steps below to prepare OpenVINO model. 14 | - a. Install OpenVINO Notebooks on your PC following these instructions 15 | https://github.com/openvinotoolkit/openvino_notebooks/tree/latest?tab=readme-ov-file#-installation-guide 16 | 17 | - b. Convert a popular model to the OpenVINO IR format using this notebook 18 | https://github.com/openvinotoolkit/openvino_notebooks/blob/latest/notebooks/llm-chatbot/llm-chatbot-generate-api.ipynb 19 |
In the notebook you can select any model you prefer (for example, phi-4-mini-instruct) and type of compression. The model list is maintained by Intel and represents a list of popular chat models. You can alternatively follow the instructions in section 2d using Command Line to port models outside of this list. 20 | ![image](https://github.com/user-attachments/assets/933a1424-d38d-4ad2-af97-e0a8eb16eacb) 21 |

You can execute the notebook up to cells 7 and 8. As a result, you will get the converted model in IR format
![image](https://github.com/user-attachments/assets/aa941a49-46fe-4d3f-aebf-c4c629347ae5) 22 | 23 | 24 | - c. Copy IR files to the corresponding AI Playground folder 25 | ![image](https://github.com/user-attachments/assets/e8f62017-6f3a-4ec3-b67e-06a83ee7233d) 26 | - d. Model conversion without OpenVINO notebook: 27 | Alternatively, models can be converted to OpenVINO IR format directly from command line using optimum-cli. More information about this tool can be found here https://huggingface.co/docs/optimum/en/intel/openvino/export Please refer also to usage samples in OpenVINO GenAI Quick-start Guide 28 | https://docs.openvino.ai/2024/_static/download/GenAI_Quick_Start_Guide.pdf 29 | 30 | 4. New model is available in AI Playground 31 | ![image](https://github.com/user-attachments/assets/83ce8ea1-4f02-442b-b640-da30e1c92e4f) 32 | 33 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. 3 | 4 | ## Reporting a Vulnerability 5 | Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). 6 | -------------------------------------------------------------------------------- /WebUI/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] 2 | charset = utf-8 3 | indent_size = 2 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | end_of_line = lf 9 | max_line_length = 100 10 | -------------------------------------------------------------------------------- /WebUI/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules/ 11 | dist/ 12 | dist-ssr 13 | *.local 14 | release/ 15 | ComfyUI/ 16 | LlamaCPP/ 17 | OpenVino/ 18 | embeddingCache/ 19 | backend-shared/ 20 | 21 | # Editor directories and files 22 | .vscode/* 23 | !.vscode/extensions.json 24 | .idea 25 | .DS_Store 26 | *.suo 27 | *.ntvs* 28 | *.njsproj 29 | *.sln 30 | *.sw? 31 | -------------------------------------------------------------------------------- /WebUI/.prettierignore: -------------------------------------------------------------------------------- 1 | src/auto-import.d.ts 2 | workflows_intel/ -------------------------------------------------------------------------------- /WebUI/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "singleQuote": true, 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /WebUI/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/app.ico -------------------------------------------------------------------------------- /WebUI/build/README.md: -------------------------------------------------------------------------------- 1 | # Installer Build 2 | 3 | ## Fetch remote dependencies for build 4 | 5 | 1. run `npm install` 6 | 2. aquire windows libuv dlls, e.g. via miniforge: 7 | - Install miniforge: https://github.com/conda-forge/miniforge 8 | - Create a reference conda environment with libuv installed 9 | ``` 10 | conda create -n cp311_libuv python=3.11 libuv -y 11 | # copy the path to this conda env 12 | conda env list | findstr cp311_libuv 13 | ``` 14 | 3. run `npm run fetch-build-resources -- --conda_env_dir=$PATH_TO_CONDA_ENV` 15 | 16 | ## decide for offline or online installer 17 | 18 | ### online installer 19 | 20 | run 21 | 22 | ``` 23 | npm run prepare-build 24 | npm run build 25 | ``` 26 | 27 | ### offline installer 28 | 29 | **FIXME: offline scripts are missing** 30 | 31 | run 32 | 33 | ``` 34 | npm run prepare-build:${PLATFORM}-offline 35 | npm run build:${PLATFORM}-offline 36 | ``` 37 | 38 | Fetching, installing and compressing the full python dependencies takes a considerable amount of time. 39 | -------------------------------------------------------------------------------- /WebUI/build/scripts/check-i18n.js: -------------------------------------------------------------------------------- 1 | // Usage: node check-i18n.js --i18n-dir=$DIR 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | const argv = require('minimist')(process.argv.slice(2)) 6 | 7 | const i18nDirArg = argv.i18n_dir 8 | if (!i18nDirArg) { 9 | console.error('Usage: node check-i18n.js --i18n-dir=$DIR\n') 10 | process.exit(1) 11 | } 12 | 13 | const i18nDir = path.resolve(i18nDirArg) 14 | const enData = JSON.parse(fs.readFileSync(path.join(i18nDir, 'en-US.json'))) 15 | const keys = Object.keys(enData) 16 | 17 | const langs = fs.readdirSync(i18nDir).filter((f) => f.endsWith('.json')) 18 | const missingKeys = {} 19 | const unusedKeys = {} 20 | 21 | langs.forEach((lang) => { 22 | const data = JSON.parse(fs.readFileSync(path.join(i18nDir, lang))) 23 | keys.forEach((key) => { 24 | if (!data[key]) { 25 | if (!missingKeys[lang]) { 26 | missingKeys[lang] = [] 27 | } 28 | missingKeys[lang].push(key) 29 | } 30 | }) 31 | 32 | Object.keys(data).forEach((key) => { 33 | if (!keys.includes(key)) { 34 | if (!unusedKeys[lang]) { 35 | unusedKeys[lang] = [] 36 | } 37 | unusedKeys[lang].push(key) 38 | } 39 | }) 40 | 41 | if (missingKeys[lang]) { 42 | // print pretty 43 | // 5 entries per row 44 | const entriesPerRow = 5 45 | const entries = missingKeys[lang] 46 | const rows = [] 47 | for (let i = 0; i < entries.length; i += entriesPerRow) { 48 | rows.push(entries.slice(i, i + entriesPerRow).join(', ')) 49 | } 50 | console.log(`${missingKeys[lang].length} missing keys for ${lang}:`) 51 | console.log(` ${rows.join('\n ')}`) 52 | console.log() 53 | } 54 | if (unusedKeys[lang]) { 55 | console.log(`${unusedKeys[lang].length} unused keys for ${lang}:`) 56 | console.log(` ${unusedKeys[lang].join(', ')}`) 57 | console.log() 58 | } 59 | }) 60 | -------------------------------------------------------------------------------- /WebUI/build/scripts/patch-nsis-template.js: -------------------------------------------------------------------------------- 1 | path = require('path') 2 | const customizedTemplate = path.resolve(__dirname, '../installSection.nsh') 3 | const targetTemplate = path.resolve( 4 | __dirname, 5 | '../../node_modules/app-builder-lib/templates/nsis/installSection.nsh', 6 | ) 7 | console.log(`Copying customized NSIS template ${customizedTemplate} to ${targetTemplate}`) 8 | require('fs').copyFileSync(customizedTemplate, targetTemplate) 9 | 10 | const addMediaOutputChangeWarningTemplate = path.resolve(__dirname, '../installUtil.nsh') 11 | const addMediaOutputChangeWarningTargetTemplate = path.resolve( 12 | __dirname, 13 | '../../node_modules/app-builder-lib/templates/nsis/include/installUtil.nsh', 14 | ) 15 | console.log( 16 | `Copying customized NSIS template ${addMediaOutputChangeWarningTemplate} to ${addMediaOutputChangeWarningTargetTemplate} displaying now a warning to back-up media files`, 17 | ) 18 | require('fs').copyFileSync( 19 | addMediaOutputChangeWarningTemplate, 20 | addMediaOutputChangeWarningTargetTemplate, 21 | ) 22 | -------------------------------------------------------------------------------- /WebUI/build/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": 0, 3 | "comfyUiParameters": [ 4 | "--lowvram", 5 | "--disable-ipex-optimize", 6 | "--bf16-unet", 7 | "--reserve-vram", 8 | "6.0" 9 | ], 10 | "availableThemes": ["dark", "lnl", "bmg"], 11 | "currentTheme": "bmg" 12 | } 13 | -------------------------------------------------------------------------------- /WebUI/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://shadcn-vue.com/schema.json", 3 | "style": "new-york", 4 | "typescript": true, 5 | "tailwind": { 6 | "config": "tailwind.config.cjs", 7 | "css": "src/assets/css/index.css", 8 | "baseColor": "slate", 9 | "cssVariables": false 10 | }, 11 | "aliases": { 12 | "components": "@/components", 13 | "utils": "@/lib/utils" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /WebUI/electron/electron-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare namespace NodeJS { 4 | interface ProcessEnv { 5 | /** 6 | * The built directory structure 7 | * 8 | * ```tree 9 | * ├─┬─┬ dist 10 | * │ │ └── index.html 11 | * │ │ 12 | * │ ├─┬ dist-electron 13 | * │ │ ├── main.js 14 | * │ │ └── preload.js 15 | * │ 16 | * ``` 17 | */ 18 | DIST: string 19 | /** /dist/ or /public/ */ 20 | VITE_PUBLIC: string 21 | } 22 | } 23 | 24 | // Used in Renderer process, expose in `preload.ts` 25 | interface Window { 26 | ipcRenderer: import('electron').IpcRenderer 27 | } 28 | 29 | type KVObject = { 30 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 31 | [key: string]: any 32 | } 33 | 34 | type Theme = 'dark' | 'lnl' | 'bmg' 35 | 36 | type LocalSettings = { 37 | debug: number 38 | comfyUiParameters?: string[] 39 | deviceArchOverride?: 'bmg' | 'acm' | 'arl_h' | 'lnl' | 'mtl' 40 | } & KVObject 41 | 42 | type ThemeSettings = { 43 | availableThemes: Theme[] 44 | currentTheme: Theme 45 | } 46 | 47 | type SetupData = { 48 | modelPaths: ModelPaths 49 | modelLists: ModelLists 50 | isAdminExec: boolean 51 | version: string 52 | } 53 | 54 | type UpdateWorkflowsFromIntelResult = { 55 | success: boolean 56 | backupDir: string 57 | } 58 | 59 | type BackendStatus = 60 | | 'notYetStarted' 61 | | 'starting' 62 | | 'running' 63 | | 'stopped' 64 | | 'stopping' 65 | | 'failed' 66 | | 'notInstalled' 67 | | 'installationFailed' 68 | | 'installing' 69 | | 'uninitializedStatus' 70 | -------------------------------------------------------------------------------- /WebUI/electron/subprocesses/deviceArch.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_base.inl 2 | const ID2ARCH: { [key: number]: Arch } = { 3 | // bmg 4 | 0xe202: 'bmg', 5 | 0xe20b: 'bmg', 6 | 0xe20c: 'bmg', 7 | 0xe20d: 'bmg', 8 | 0xe212: 'bmg', 9 | 10 | // lnl 11 | 0x6420: 'lnl', 12 | 0x64a0: 'lnl', 13 | 0x64b0: 'lnl', 14 | 15 | // dg2, using alias name "acm" 16 | 0x4f80: 'acm', 17 | 0x4f81: 'acm', 18 | 0x4f82: 'acm', 19 | 0x4f83: 'acm', 20 | 0x4f84: 'acm', 21 | 0x4f85: 'acm', 22 | 0x4f86: 'acm', 23 | 0x4f87: 'acm', 24 | 0x4f88: 'acm', 25 | 0x5690: 'acm', 26 | 0x5691: 'acm', 27 | 0x5692: 'acm', 28 | 0x5693: 'acm', 29 | 0x5694: 'acm', 30 | 0x5695: 'acm', 31 | 0x5696: 'acm', 32 | 0x5697: 'acm', 33 | 0x56a3: 'acm', 34 | 0x56a4: 'acm', 35 | 0x56b0: 'acm', 36 | 0x56b1: 'acm', 37 | 0x56b2: 'acm', 38 | 0x56b3: 'acm', 39 | 0x56ba: 'acm', 40 | 0x56bb: 'acm', 41 | 0x56bc: 'acm', 42 | 0x56bd: 'acm', 43 | 0x56be: 'acm', 44 | 0x56bf: 'acm', 45 | 0x56a0: 'acm', 46 | 0x56a1: 'acm', 47 | 0x56a2: 'acm', 48 | 0x56a5: 'acm', 49 | 0x56a6: 'acm', 50 | 0x56c0: 'acm', 51 | 0x56c1: 'acm', 52 | 0x56c2: 'acm', 53 | 54 | // mtl 55 | 0x7d40: 'mtl', 56 | 0x7d55: 'mtl', 57 | 0x7dd5: 'mtl', 58 | 0x7d45: 'mtl', 59 | 60 | // // arl 61 | // 0x7D67: "arl", 62 | 0x7d51: 'arl_h', 63 | 0x7dd1: 'arl_h', 64 | // 0x7D41: "arl", 65 | } 66 | 67 | export function getDeviceArch(deviceId: number): Arch { 68 | return ID2ARCH[deviceId] || 'unknown' 69 | } 70 | 71 | export function getArchPriority(arch: Arch): number { 72 | switch (arch) { 73 | case 'bmg': 74 | return 5 75 | case 'acm': 76 | return 4 77 | case 'arl_h': 78 | return 3 79 | case 'lnl': 80 | return 2 81 | case 'mtl': 82 | return 1 83 | default: 84 | return 0 85 | } 86 | } 87 | 88 | export type Arch = 'bmg' | 'acm' | 'arl_h' | 'lnl' | 'mtl' | 'unknown' 89 | -------------------------------------------------------------------------------- /WebUI/electron/subprocesses/mediaServer.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | 3 | const app = express() 4 | 5 | const port: number = Number(process.env.PORT_NUMBER) 6 | const mediaPath: string = process.env.MEDIA_DIRECTORY! 7 | 8 | app.use(express.static(mediaPath)) 9 | 10 | app.listen(port, () => { 11 | console.log(`Media server started on port ${port}`, 'electron-backend') 12 | }) 13 | -------------------------------------------------------------------------------- /WebUI/electron/subprocesses/osProcessHelper.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import * as fs from 'fs-extra' 3 | import { spawn } from 'node:child_process' 4 | 5 | export function existingFileOrError(filePath: string) { 6 | const resolvedFilePath = path.resolve(filePath) 7 | if (fs.existsSync(resolvedFilePath)) { 8 | return resolvedFilePath 9 | } 10 | throw Error(`File at ${resolvedFilePath} does not exist`) 11 | } 12 | export async function spawnProcessAsync( 13 | command: string, 14 | args: string[] = [], 15 | logHandler: (data: string) => void = () => {}, 16 | extraEnv?: object, 17 | workDir?: string, 18 | ): Promise { 19 | logHandler(`Spawning command ${command} ${args.join(' ')}`) 20 | if (extraEnv) { 21 | logHandler(`Extra env: ${JSON.stringify(extraEnv)}`) 22 | } 23 | const spawnedProcess = spawn(command, args, { 24 | windowsHide: true, 25 | cwd: workDir ?? process.cwd(), 26 | env: { 27 | ...process.env, 28 | ...extraEnv, 29 | }, 30 | }) 31 | 32 | const stdOut: string[] = [] 33 | 34 | spawnedProcess.stdout.on('data', (data: string | Buffer) => { 35 | logHandler(data.toString('utf8')) 36 | stdOut.push(data.toString('utf8')) 37 | }) 38 | spawnedProcess.stderr.on('data', (data) => { 39 | logHandler(data.toString('utf8')) 40 | }) 41 | 42 | return new Promise((resolve, reject) => { 43 | spawnedProcess.on('exit', (code) => { 44 | if (code === 0) { 45 | resolve(stdOut.join('\n')) 46 | } else { 47 | reject(new Error(`command ${command} ${args} failed ${code}`)) 48 | } 49 | }) 50 | spawnedProcess.on('error', (err) => { 51 | reject(new Error(`command ${command} ${args} failed with error ${err}`)) 52 | }) 53 | }) 54 | } 55 | 56 | export async function copyFileWithDirs(src: string, dest: string) { 57 | const stats = await fs.promises.lstat(src) 58 | if (stats.isSymbolicLink()) { 59 | const linkTarget = await fs.promises.readlink(src) 60 | src = linkTarget 61 | } 62 | const destDir = path.dirname(dest) 63 | await fs.promises.mkdir(destDir, { recursive: true }) 64 | await fs.promises.cp(src, dest, { recursive: true, force: true }) 65 | } 66 | -------------------------------------------------------------------------------- /WebUI/electron/test/subprocesses/deviceArch.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | import { getDeviceArch, getArchPriority } from '../../subprocesses/deviceArch' 3 | 4 | describe('deviceArch', () => { 5 | describe('getDeviceArch', () => { 6 | it('should return the correct architecture for known device IDs', () => { 7 | expect(getDeviceArch(0x4f80)).toBe('acm') 8 | expect(getDeviceArch(0x7d40)).toBe('mtl') 9 | expect(getDeviceArch(0xe202)).toBe('bmg') 10 | }) 11 | 12 | it('should return "unknown" for unknown device IDs', () => { 13 | expect(getDeviceArch(0x0000)).toBe('unknown') 14 | expect(getDeviceArch(0xffff)).toBe('unknown') 15 | }) 16 | }) 17 | 18 | describe('getArchPriority', () => { 19 | it('should return the correct priority for each architecture', () => { 20 | expect(getArchPriority('bmg')).toBe(5) 21 | expect(getArchPriority('acm')).toBe(4) 22 | expect(getArchPriority('arl_h')).toBe(3) 23 | expect(getArchPriority('lnl')).toBe(2) 24 | expect(getArchPriority('mtl')).toBe(1) 25 | expect(getArchPriority('unknown')).toBe(0) 26 | }) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /WebUI/electron/test/subprocesses/service.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, vi, beforeEach } from 'vitest' 2 | import { DeviceService } from '../../subprocesses/service' 3 | import path from 'node:path' 4 | 5 | vi.mock('electron', () => ({ 6 | app: { 7 | isPackaged: false, 8 | }, 9 | })) 10 | 11 | describe('DeviceService', () => { 12 | let deviceService: DeviceService 13 | 14 | beforeEach(() => { 15 | vi.clearAllMocks() 16 | 17 | deviceService = new DeviceService() 18 | 19 | vi.spyOn(deviceService, 'run').mockImplementation(async () => { 20 | return JSON.stringify({ 21 | device_list: [ 22 | { 23 | device_id: 0, 24 | device_name: 'Intel(R) UHD Graphics', 25 | device_type: 'GPU', 26 | pci_bdf_address: '0000:00:02.0', 27 | pci_device_id: '0x9a60', 28 | uuid: '00000000-0000-0200-0000-00019a608086', 29 | vendor_name: 'Intel(R) Corporation', 30 | }, 31 | { 32 | device_id: 1, 33 | device_name: 'Intel(R) Arc(TM) B580 Graphics', 34 | device_type: 'GPU', 35 | pci_bdf_address: '0000:03:00.0', 36 | pci_device_id: '0xe20b', 37 | uuid: '00000000-0000-0003-0000-0000e20b8086', 38 | vendor_name: 'Intel(R) Corporation', 39 | }, 40 | { 41 | device_id: 2, 42 | device_name: 'Intel(R) Arc(TM) A770 Graphics', 43 | device_type: 'GPU', 44 | pci_bdf_address: '0000:03:00.0', 45 | pci_device_id: '0x56a0', 46 | uuid: '00000000-0000-0003-0000-000856a08086', 47 | vendor_name: 'Intel(R) Corporation', 48 | }, 49 | ], 50 | }) 51 | }) 52 | }) 53 | 54 | describe('getExePath', () => { 55 | it('should return the correct path to xpu-smi.exe', () => { 56 | const exePath = deviceService.getExePath() 57 | expect(exePath).toContain(path.join('device-service', 'xpu-smi.exe')) 58 | }) 59 | }) 60 | 61 | describe('getBestDeviceArch', () => { 62 | it('should return the architecture of the best device', async () => { 63 | const arch = await deviceService.getBestDeviceArch() 64 | 65 | expect(arch).toBe('bmg') 66 | }) 67 | 68 | it('should return "unknown" if device detection fails', async () => { 69 | vi.spyOn(deviceService, 'run').mockRejectedValue(new Error('Test error')) 70 | 71 | const arch = await deviceService.getBestDeviceArch() 72 | 73 | expect(arch).toBe('unknown') 74 | }) 75 | }) 76 | }) 77 | -------------------------------------------------------------------------------- /WebUI/electron/util.ts: -------------------------------------------------------------------------------- 1 | import { app } from 'electron' 2 | import path from 'node:path' 3 | 4 | export const externalResourcesDir = () => 5 | path.resolve(app.isPackaged ? process.resourcesPath : path.join(__dirname, '../../external/')) 6 | 7 | export const getMediaDir = () => { 8 | let mediaDir: string 9 | if (process.env.USERPROFILE) { 10 | mediaDir = path.join(process.env.USERPROFILE, 'Documents', 'AI-Playground', 'media') 11 | } else if (process.env.HOME) { 12 | mediaDir = path.join(process.env.HOME, 'AI-Playground', 'media') 13 | } else { 14 | mediaDir = path.join(externalResourcesDir(), 'service', 'static', 'sd_out') 15 | } 16 | return mediaDir 17 | } 18 | -------------------------------------------------------------------------------- /WebUI/eslint.config.ts: -------------------------------------------------------------------------------- 1 | import pluginVue from 'eslint-plugin-vue' 2 | import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' 3 | import skipFormatting from '@vue/eslint-config-prettier/skip-formatting' 4 | 5 | // To allow more languages other than `ts` in `.vue` files, uncomment the following lines: 6 | // import { configureVueProject } from '@vue/eslint-config-typescript' 7 | // configureVueProject({ scriptLangs: ['ts', 'tsx'] }) 8 | // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup 9 | 10 | export default defineConfigWithVueTs( 11 | { 12 | name: 'app/files-to-lint', 13 | files: ['**/*.{ts,mts,tsx,vue}'], 14 | }, 15 | 16 | { 17 | name: 'app/files-to-ignore', 18 | ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', '**/*.cjs'], 19 | }, 20 | 21 | pluginVue.configs['flat/essential'], 22 | vueTsConfigs.recommended, 23 | skipFormatting, 24 | { 25 | rules: { 26 | 'vue/multi-word-component-names': 'off', 27 | 'vue/require-v-for-key': 'warn', 28 | 'vue/no-use-v-if-with-v-for': 'warn', 29 | '@typescript-eslint/no-this-alias': 'warn', 30 | '@typescript-eslint/no-unused-vars': [ 31 | 'error', 32 | { 33 | args: 'all', 34 | argsIgnorePattern: '^_', 35 | caughtErrors: 'all', 36 | caughtErrorsIgnorePattern: '^_', 37 | destructuredArrayIgnorePattern: '^_', 38 | varsIgnorePattern: '(^_|Schema$)', 39 | ignoreRestSiblings: true, 40 | }, 41 | ], 42 | }, 43 | }, 44 | { 45 | name: 'allow-cjs-build-scripts', 46 | files: ['**/build/scripts/*.js'], 47 | rules: { 48 | '@typescript-eslint/no-require-imports': 'off', 49 | }, 50 | }, 51 | ) 52 | -------------------------------------------------------------------------------- /WebUI/external/model_config.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "llm": "../service/models/llm/checkpoints", 3 | "ggufLLM": "../service/models/llm/ggufLLM", 4 | "openvinoLLM": "../service/models/llm/openvino", 5 | "embedding": "../service/models/llm/embedding/ipexLLM", 6 | "stableDiffusion": "../service/models/stable_diffusion/checkpoints", 7 | "inpaint": "../service/models/stable_diffusion/inpaint", 8 | "lora": "../service/models/stable_diffusion/lora", 9 | "vae": "../service/models/stable_diffusion/vae" 10 | } 11 | -------------------------------------------------------------------------------- /WebUI/external/model_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "llm": "./resources/service/models/llm/checkpoints", 3 | "ggufLLM": "./resources/service/models/llm/ggufLLM", 4 | "openvinoLLM": "./resources/service/models/llm/openvino", 5 | "embedding": "./resources/service/models/llm/embedding/ipexLLM", 6 | "stableDiffusion": "./resources/service/models/stable_diffusion/checkpoints", 7 | "inpaint": "./resources/service/models/stable_diffusion/inpaint", 8 | "lora": "./resources/service/models/stable_diffusion/lora", 9 | "vae": "./resources/service/models/stable_diffusion/vae" 10 | } 11 | -------------------------------------------------------------------------------- /WebUI/external/settings-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": 1, 3 | "comfyUiParameters": [ 4 | "--lowvram", 5 | "--disable-ipex-optimize", 6 | "--bf16-unet", 7 | "--reserve-vram", 8 | "6.0" 9 | ], 10 | "availableThemes": ["dark", "lnl", "bmg"], 11 | "currentTheme": "bmg" 12 | } 13 | -------------------------------------------------------------------------------- /WebUI/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | AI Playground 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /WebUI/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'tailwindcss/nesting': {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /WebUI/public/A1111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/A1111.png -------------------------------------------------------------------------------- /WebUI/public/AI_Playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/AI_Playground.png -------------------------------------------------------------------------------- /WebUI/public/ComfyUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/ComfyUI.png -------------------------------------------------------------------------------- /WebUI/public/Fooocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/Fooocus.png -------------------------------------------------------------------------------- /WebUI/public/Intel_Insiders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/Intel_Insiders.png -------------------------------------------------------------------------------- /WebUI/public/SDNext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/SDNext.png -------------------------------------------------------------------------------- /WebUI/public/TechCraftVideos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/public/TechCraftVideos.png -------------------------------------------------------------------------------- /WebUI/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | @import 'tailwindcss/base'; 2 | @import 'tailwindcss/components'; 3 | @import 'tailwindcss/utilities'; 4 | @import './theme.css'; 5 | @import './main.css'; 6 | @import './pc.css'; 7 | @import './compontents.css'; 8 | @import './svg.css'; 9 | 10 | @layer base { 11 | :root { 12 | --background: 280 50% 5%; 13 | --foreground: 280 5% 90%; 14 | --card: 280 50% 0%; 15 | --card-foreground: 280 5% 90%; 16 | --popover: 280 50% 5%; 17 | --popover-foreground: 280 5% 90%; 18 | --primary: 280 98.4% 50.6%; 19 | --primary-foreground: 0 0% 100%; 20 | --secondary: 280 30% 10%; 21 | --secondary-foreground: 0 0% 100%; 22 | --muted: 242 30% 15%; 23 | --muted-foreground: 280 5% 60%; 24 | --accent: 242 30% 15%; 25 | --accent-foreground: 280 5% 90%; 26 | --destructive: 0 100% 30%; 27 | --destructive-foreground: 280 5% 90%; 28 | --border: 280 30% 18%; 29 | --input: 280 30% 18%; 30 | --ring: 280 98.4% 50.6%; 31 | --radius: 0.5rem; 32 | } 33 | .dark { 34 | --background: 280 50% 5%; 35 | --foreground: 280 5% 90%; 36 | --card: 280 50% 0%; 37 | --card-foreground: 280 5% 90%; 38 | --popover: 280 50% 5%; 39 | --popover-foreground: 280 5% 90%; 40 | --primary: 280 98.4% 50.6%; 41 | --primary-foreground: 0 0% 100%; 42 | --secondary: 280 30% 10%; 43 | --secondary-foreground: 0 0% 100%; 44 | --muted: 242 30% 15%; 45 | --muted-foreground: 280 5% 60%; 46 | --accent: 242 30% 15%; 47 | --accent-foreground: 280 5% 90%; 48 | --destructive: 0 100% 30%; 49 | --destructive-foreground: 280 5% 90%; 50 | --border: 280 30% 18%; 51 | --input: 280 30% 18%; 52 | --ring: 280 98.4% 50.6%; 53 | --radius: 0.5rem; 54 | } 55 | } 56 | 57 | @layer base { 58 | * { 59 | @apply border-border; 60 | } 61 | body { 62 | @apply bg-background text-foreground; 63 | } 64 | code { 65 | @apply break-words whitespace-pre-wrap; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /WebUI/src/assets/css/pc.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 1441px) { 2 | .max-image-size { 3 | max-width: 1024px; 4 | max-height: 768px; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/css/vertical.css: -------------------------------------------------------------------------------- 1 | .vertical_tab { 2 | } 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/fonts/intelone-display-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/fonts/intelone-display-bold.woff2 -------------------------------------------------------------------------------- /WebUI/src/assets/fonts/intelone-display-light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/fonts/intelone-display-light.woff2 -------------------------------------------------------------------------------- /WebUI/src/assets/fonts/intelone-display-medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/fonts/intelone-display-medium.woff2 -------------------------------------------------------------------------------- /WebUI/src/assets/fonts/intelone-display-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/fonts/intelone-display-regular.woff2 -------------------------------------------------------------------------------- /WebUI/src/assets/image/arc-graphics-environments-3color-pattern-full.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/image/arc-graphics-environments-3color-pattern-full.jpg -------------------------------------------------------------------------------- /WebUI/src/assets/image/arc_graphics_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/image/arc_graphics_badge.png -------------------------------------------------------------------------------- /WebUI/src/assets/image/core_ultra_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/image/core_ultra_badge.png -------------------------------------------------------------------------------- /WebUI/src/assets/image/nsfw_result_detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/WebUI/src/assets/image/nsfw_result_detected.png -------------------------------------------------------------------------------- /WebUI/src/assets/js/clientAPI.ts: -------------------------------------------------------------------------------- 1 | export const isClient = 2 | window.chrome.webview && 3 | window.chrome.webview.hostObjects && 4 | window.chrome.webview.hostObjects.clientAPI 5 | 6 | export function minimizedWin() { 7 | window.electronAPI.miniWindow() 8 | } 9 | 10 | export function exitApp() { 11 | window.electronAPI.exitApp() 12 | } 13 | 14 | export function setWinSize(width: number, height: number) { 15 | return window.electronAPI.setWinSize(width, height) 16 | } 17 | 18 | export function showOpenDialog(options: Electron.OpenDialogOptions) { 19 | return window.electronAPI.showOpenDialog(options) 20 | } 21 | 22 | export function showSaveDialog(options: Electron.SaveDialogOptions) { 23 | return window.electronAPI.showSaveDialog(options) 24 | } 25 | 26 | export function saveImage(url: string) { 27 | return window.electronAPI.saveImage(url) 28 | } 29 | -------------------------------------------------------------------------------- /WebUI/src/assets/js/const.ts: -------------------------------------------------------------------------------- 1 | export const MODEL_TYPE_LLM = 0 2 | export const MODEL_TYPE_STABLE_DIFFUSION = 1 3 | export const MODEL_TYPE_LORA = 2 4 | export const MODEL_TYPE_VAE = 3 5 | export const MODEL_TYPE_ESRGAN = 4 6 | export const MODEL_TYPE_EMBEDDING = 5 7 | export const MODEL_TYPE_INPAINT = 6 8 | export const MODEL_TYPE_PREVIEW = 7 9 | export const MODEL_TYPE_LLAMA_CPP = 8 10 | export const MODEL_TYPE_OPENVINO = 9 11 | export const MODEL_TYPE_COMFY_UNET = 100 12 | export const MODEL_TYPE_COMFY_CLIP = 101 13 | export const MODEL_TYPE_COMFY_VAE = 102 14 | export const MODEL_TYPE_COMFY_DEFAULT_CHECKPOINT = 103 15 | export const MODEL_TYPE_COMFY_DEFAULT_LORA = 104 16 | export const MODEL_TYPE_COMFY_CONTROL_NET = 105 17 | export const MODEL_TYPE_FACESWAP = 106 18 | export const MODEL_TYPE_FACERESTORE = 107 19 | export const MODEL_TYPE_NSFW_DETECTOR = 108 20 | export const MODEL_TYPE_COMFY_CHECKPOINTS = 109 21 | -------------------------------------------------------------------------------- /WebUI/src/assets/js/sseProcessor.ts: -------------------------------------------------------------------------------- 1 | export class SSEProcessor { 2 | readonly reader: ReadableStreamDefaultReader 3 | readonly onData?: (data: string) => void 4 | readonly onFinish?: () => void 5 | readonly decoder = new TextDecoder() 6 | processing = false 7 | message = '' 8 | 9 | constructor( 10 | reader: ReadableStreamDefaultReader, 11 | onData?: (data: string) => void, 12 | onFinish?: () => void, 13 | ) { 14 | this.reader = reader 15 | this.onData = onData 16 | this.onFinish = onFinish 17 | } 18 | 19 | async start() { 20 | if (this.processing) { 21 | return 22 | } 23 | this.processing = true 24 | const result = await this.reader.read() 25 | return this.processText(result) 26 | } 27 | 28 | async processText({ done, value }: ReadableStreamReadResult) { 29 | if (done) { 30 | this.processing = false 31 | this.onFinish?.call(this) 32 | return 33 | } 34 | 35 | const text = this.decoder.decode(value) 36 | let start = 0 37 | let pos: number 38 | while (start < text.length) { 39 | pos = text.indexOf('\0', start) 40 | if (pos > -1) { 41 | const line = text.substring(start, pos) 42 | if (line.startsWith('data:')) { 43 | this.onData?.call(this, line) 44 | } else { 45 | this.message += line 46 | this.onData?.call(this, this.message) 47 | } 48 | this.message = '' 49 | start = pos + 1 50 | } else { 51 | this.message += text.substring(start) 52 | break 53 | } 54 | } 55 | const result = await this.reader.read() 56 | await this.processText(result) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /WebUI/src/assets/js/store/conversations.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | export const useConversations = defineStore( 4 | 'conversations', 5 | () => { 6 | const conversationList = ref>({}) 7 | const activeKey = ref('') 8 | const activeConversation = computed(() => conversationList.value[activeKey.value]) 9 | 10 | const addToActiveConversation = (key: string, item: ChatItem) => { 11 | const list = conversationList.value[key] 12 | list.push(item) 13 | addNewConversationIfLatestIsNotEmpty(conversationList.value, activeKey.value) 14 | } 15 | 16 | function deleteConversation(conversationKey: string) { 17 | delete conversationList.value[conversationKey] 18 | } 19 | 20 | function clearConversation(conversationKey: string) { 21 | conversationList.value[conversationKey] = [] 22 | } 23 | 24 | function deleteItemFromConversation(conversationKey: string, index: number) { 25 | conversationList.value[conversationKey].splice(index, 1) 26 | } 27 | 28 | const isNewConversation = (key: string) => conversationList.value[key].length === 0 29 | 30 | watchEffect(() => { 31 | if (Object.keys(conversationList.value).includes(activeKey.value)) return 32 | const latestConversationKey = Object.keys(conversationList.value).at(-1) 33 | if (!latestConversationKey) return 34 | activeKey.value = latestConversationKey 35 | }) 36 | 37 | return { 38 | conversationList, 39 | activeKey, 40 | activeConversation, 41 | addToActiveConversation, 42 | deleteConversation, 43 | clearConversation, 44 | deleteItemFromConversation, 45 | isNewConversation, 46 | } 47 | }, 48 | { 49 | persist: { 50 | pick: ['conversationList'], 51 | afterHydrate: (ctx) => 52 | addNewConversationIfLatestIsNotEmpty(ctx.store.$state.conversationList), 53 | }, 54 | }, 55 | ) 56 | 57 | function addNewConversationIfLatestIsNotEmpty( 58 | list: Record, 59 | conversationKey?: string, 60 | ) { 61 | if (conversationKey && list[conversationKey].length !== 0) { 62 | // If the last conversation is already empty, do nothing 63 | const lastKey = Object.keys(list).at(-1) 64 | if (lastKey && list[lastKey].length === 0) return 65 | 66 | // Otherwise, create a fresh conversation 67 | list[new Date().getTime().toString()] = [] 68 | return 69 | } 70 | 71 | // Fallback old logic 72 | if (Object.values(list).at(-1)?.length !== 0) { 73 | list[new Date().getTime().toString()] = [] 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /WebUI/src/assets/js/store/theme.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | const knownThemes: Theme[] = ['dark', 'lnl', 'bmg'] 4 | export const useTheme = defineStore( 5 | 'theme', 6 | () => { 7 | const selected = ref(null) 8 | const availableThemes = ref([...knownThemes]) 9 | 10 | window.electronAPI.getThemeSettings().then((themeSettings) => { 11 | const themesFromSettings = themeSettings.availableThemes.filter((t) => 12 | knownThemes.includes(t), 13 | ) 14 | if (themesFromSettings.length > 0) availableThemes.value = themesFromSettings 15 | if (knownThemes.includes(themeSettings.currentTheme)) 16 | selected.value = themeSettings.currentTheme 17 | }) 18 | 19 | return { 20 | selected, 21 | availableThemes, 22 | active: computed(() => 23 | selected.value && availableThemes.value.includes(selected.value) 24 | ? selected.value 25 | : availableThemes.value[0], 26 | ), 27 | } 28 | }, 29 | { 30 | persist: { 31 | pick: ['selected'], 32 | }, 33 | }, 34 | ) 35 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/add-box.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/ai-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/audio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/broom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/check.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/collapse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/dice.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/download-cloud.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/easer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/expand.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/fullscreen-exit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/fullscreen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/generate-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/hide-history.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/history.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/loading.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/md.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/mini.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/outpaint-bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/outpaint-dir.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/pen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/ppt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/queue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/radio-checked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/rag-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/right-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/setup.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/slide-bar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/tab-active-first.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/tab-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/toggle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/transfer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/txt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/uncheck.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/upload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/user-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/video.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/warning-triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/word.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/zoom-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /WebUI/src/assets/svg/zoom-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebUI/src/components/Checkbox.vue: -------------------------------------------------------------------------------- 1 | 11 | 29 | -------------------------------------------------------------------------------- /WebUI/src/components/ComfyUIDownloadDialog.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 52 | -------------------------------------------------------------------------------- /WebUI/src/components/DropDownNew.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 82 | -------------------------------------------------------------------------------- /WebUI/src/components/FolderSelector.vue: -------------------------------------------------------------------------------- 1 | 14 | 48 | -------------------------------------------------------------------------------- /WebUI/src/components/ImagePromptOptions.vue: -------------------------------------------------------------------------------- 1 | 9 | 32 | -------------------------------------------------------------------------------- /WebUI/src/components/InpaintOptions.vue: -------------------------------------------------------------------------------- 1 | 32 | 67 | -------------------------------------------------------------------------------- /WebUI/src/components/LanguageSelector.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /WebUI/src/components/LoadingBar.vue: -------------------------------------------------------------------------------- 1 | 9 | 16 | -------------------------------------------------------------------------------- /WebUI/src/components/ModelDropDownItem.vue: -------------------------------------------------------------------------------- 1 | 10 | 34 | -------------------------------------------------------------------------------- /WebUI/src/components/OutpaintOptions.vue: -------------------------------------------------------------------------------- 1 | 46 | 73 | -------------------------------------------------------------------------------- /WebUI/src/components/ProgressBar.vue: -------------------------------------------------------------------------------- 1 | 9 | 17 | -------------------------------------------------------------------------------- /WebUI/src/components/Radio.vue: -------------------------------------------------------------------------------- 1 | 9 | 27 | -------------------------------------------------------------------------------- /WebUI/src/components/RadioBlock.vue: -------------------------------------------------------------------------------- 1 | 12 | 30 | -------------------------------------------------------------------------------- /WebUI/src/components/RandomNumber.vue: -------------------------------------------------------------------------------- 1 | 22 | 73 | -------------------------------------------------------------------------------- /WebUI/src/components/SettingsImageComfyDynamic.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 74 | -------------------------------------------------------------------------------- /WebUI/src/components/TextToImage.vue: -------------------------------------------------------------------------------- 1 | 16 | 21 | -------------------------------------------------------------------------------- /WebUI/src/components/UpscaleOptions.vue: -------------------------------------------------------------------------------- 1 | 24 | 53 | -------------------------------------------------------------------------------- /WebUI/src/components/WarningDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 48 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/aipgInput/Input.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 33 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/aipgInput/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Input } from './Input.vue' 2 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialog.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogAction.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogCancel.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogContent.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogDescription.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 23 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogFooter.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogTitle.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/AlertDialogTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/alert-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AlertDialog } from './AlertDialog.vue' 2 | export { default as AlertDialogAction } from './AlertDialogAction.vue' 3 | export { default as AlertDialogCancel } from './AlertDialogCancel.vue' 4 | export { default as AlertDialogContent } from './AlertDialogContent.vue' 5 | export { default as AlertDialogDescription } from './AlertDialogDescription.vue' 6 | export { default as AlertDialogFooter } from './AlertDialogFooter.vue' 7 | export { default as AlertDialogHeader } from './AlertDialogHeader.vue' 8 | export { default as AlertDialogTitle } from './AlertDialogTitle.vue' 9 | export { default as AlertDialogTrigger } from './AlertDialogTrigger.vue' 10 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/button/Button.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/button/index.ts: -------------------------------------------------------------------------------- 1 | import { cva, type VariantProps } from 'class-variance-authority' 2 | 3 | export { default as Button } from './Button.vue' 4 | 5 | export const buttonVariants = cva( 6 | 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-slate-300', 7 | { 8 | variants: { 9 | variant: { 10 | default: 11 | 'bg-slate-900 text-slate-50 shadow hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90', 12 | destructive: 13 | 'bg-red-500 text-slate-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90', 14 | outline: 15 | 'border border-slate-200 bg-white shadow-sm hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50', 16 | secondary: 17 | 'bg-slate-100 text-slate-900 shadow-sm hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80', 18 | ghost: 19 | 'hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50', 20 | link: 'text-slate-900 underline-offset-4 hover:underline dark:text-slate-50', 21 | }, 22 | size: { 23 | default: 'h-9 px-4 py-2', 24 | xs: 'h-7 rounded px-2', 25 | sm: 'h-8 rounded-md px-3 text-xs', 26 | lg: 'h-10 rounded-md px-8', 27 | icon: 'h-9 w-9', 28 | }, 29 | }, 30 | defaultVariants: { 31 | variant: 'default', 32 | size: 'default', 33 | }, 34 | }, 35 | ) 36 | 37 | export type ButtonVariants = VariantProps 38 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/collapsible/Collapsible.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/collapsible/CollapsibleContent.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/collapsible/CollapsibleTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/collapsible/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Collapsible } from './Collapsible.vue' 2 | export { default as CollapsibleTrigger } from './CollapsibleTrigger.vue' 3 | export { default as CollapsibleContent } from './CollapsibleContent.vue' 4 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/Dialog.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogClose.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogContent.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 52 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogDescription.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogFooter.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogScrollContent.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 65 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogTitle.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/DialogTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Dialog } from './Dialog.vue' 2 | export { default as DialogClose } from './DialogClose.vue' 3 | export { default as DialogContent } from './DialogContent.vue' 4 | export { default as DialogDescription } from './DialogDescription.vue' 5 | export { default as DialogFooter } from './DialogFooter.vue' 6 | export { default as DialogHeader } from './DialogHeader.vue' 7 | export { default as DialogScrollContent } from './DialogScrollContent.vue' 8 | export { default as DialogTitle } from './DialogTitle.vue' 9 | export { default as DialogTrigger } from './DialogTrigger.vue' 10 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenu.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuContent.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 44 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuGroup.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuItem.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuLabel.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 44 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 25 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuSub.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 36 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 32 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/dropdown-menu/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DropdownMenu } from './DropdownMenu.vue' 2 | 3 | export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue' 4 | export { default as DropdownMenuContent } from './DropdownMenuContent.vue' 5 | export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue' 6 | export { default as DropdownMenuItem } from './DropdownMenuItem.vue' 7 | export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue' 8 | export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue' 9 | export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue' 10 | export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue' 11 | export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue' 12 | export { default as DropdownMenuSub } from './DropdownMenuSub.vue' 13 | export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue' 14 | export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue' 15 | export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue' 16 | export { DropdownMenuPortal } from 'reka-ui' 17 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/FormControl.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/FormDescription.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/FormItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/FormLabel.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/FormMessage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/index.ts: -------------------------------------------------------------------------------- 1 | export { default as FormControl } from './FormControl.vue' 2 | export { default as FormDescription } from './FormDescription.vue' 3 | export { default as FormItem } from './FormItem.vue' 4 | export { default as FormLabel } from './FormLabel.vue' 5 | export { default as FormMessage } from './FormMessage.vue' 6 | export { FORM_ITEM_INJECTION_KEY } from './injectionKeys' 7 | export { Form, Field as FormField, FieldArray as FormFieldArray } from 'vee-validate' 8 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/injectionKeys.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey } from 'vue' 2 | 3 | export const FORM_ITEM_INJECTION_KEY = Symbol() as InjectionKey 4 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/form/useFormField.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FieldContextKey, 3 | useFieldError, 4 | useIsFieldDirty, 5 | useIsFieldTouched, 6 | useIsFieldValid, 7 | } from 'vee-validate' 8 | import { inject } from 'vue' 9 | import { FORM_ITEM_INJECTION_KEY } from './injectionKeys' 10 | 11 | export function useFormField() { 12 | const fieldContext = inject(FieldContextKey) 13 | const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY) 14 | 15 | if (!fieldContext) throw new Error('useFormField should be used within ') 16 | 17 | const { name } = fieldContext 18 | const id = fieldItemContext 19 | 20 | const fieldState = { 21 | valid: useIsFieldValid(name), 22 | isDirty: useIsFieldDirty(name), 23 | isTouched: useIsFieldTouched(name), 24 | error: useFieldError(name), 25 | } 26 | 27 | return { 28 | id, 29 | name, 30 | formItemId: `${id}-form-item`, 31 | formDescriptionId: `${id}-form-item-description`, 32 | formMessageId: `${id}-form-item-message`, 33 | ...fieldState, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/input/Input.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 33 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Input } from './Input.vue' 2 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/label/Label.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 28 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/label/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Label } from './Label.vue' 2 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/loadImage/index.ts: -------------------------------------------------------------------------------- 1 | export { default as LoadImage } from './LoadImage.vue' 2 | -------------------------------------------------------------------------------- /WebUI/src/components/ui/slider/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ResolutionPicker } from './ResolutionPicker.vue' 2 | -------------------------------------------------------------------------------- /WebUI/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | import { useI18N } from '@/assets/js/store/i18n.ts' 4 | 5 | export function cn(...inputs: ClassValue[]) { 6 | return twMerge(clsx(inputs)) 7 | } 8 | 9 | export function mapStatusToColor(componentState: BackendStatus) { 10 | switch (componentState) { 11 | case 'running': 12 | return '#66BB55' 13 | case 'installationFailed': 14 | case 'failed': 15 | return '#ef335e' 16 | case 'notInstalled': 17 | return '#bbc2c5' 18 | case 'notYetStarted': 19 | case 'stopped': 20 | return 'orange' 21 | case 'starting': 22 | case 'stopping': 23 | case 'installing': 24 | return '#e1cb50' 25 | default: 26 | return 'blue' 27 | } 28 | } 29 | 30 | export function mapToDisplayStatus(componentState: BackendStatus) { 31 | const i18nState = useI18N().state 32 | switch (componentState) { 33 | case 'running': 34 | return i18nState.BACKEND_STATUS_RUNNING 35 | case 'stopping': 36 | return i18nState.BACKEND_STATUS_STOPPING 37 | case 'starting': 38 | return i18nState.BACKEND_STATUS_STARTING 39 | case 'stopped': 40 | case 'notYetStarted': 41 | return i18nState.BACKEND_STATUS_INSTALLED 42 | case 'installationFailed': 43 | case 'failed': 44 | return i18nState.BACKEND_STATUS_FAILED 45 | case 'notInstalled': 46 | return i18nState.BACKEND_STATUS_NOT_INSTALLED 47 | case 'installing': 48 | return i18nState.BACKEND_STATUS_INSTALLING 49 | default: 50 | return componentState 51 | } 52 | } 53 | 54 | export function mapServiceNameToDisplayName(serviceName: string) { 55 | switch (serviceName) { 56 | case 'comfyui-backend': 57 | return 'ComfyUI' 58 | case 'ai-backend': 59 | return 'AI Playground' 60 | case 'llamacpp-backend': 61 | return 'Llama.cpp - GGUF' 62 | case 'openvino-backend': 63 | return 'OpenVINO' 64 | default: 65 | return serviceName 66 | } 67 | } 68 | 69 | export function mapModeToText(value: number | undefined) { 70 | const i18nState = useI18N().state 71 | switch (value) { 72 | case 0: 73 | return i18nState.TAB_CREATE 74 | case 1: 75 | return i18nState.ENHANCE_UPSCALE 76 | case 2: 77 | return i18nState.ENHANCE_IMAGE_PROMPT 78 | case 3: 79 | return i18nState.ENHANCE_INPAINT 80 | case 4: 81 | return i18nState.ENHANCE_OUTPAINT 82 | default: 83 | return 'unknown' 84 | } 85 | } 86 | 87 | export function getTranslationLabel(prefix: string, label: string) { 88 | return prefix + label.replace(/ - /g, '_').replace(/-/g, '_').replace(/ /g, '_').toUpperCase() 89 | } 90 | -------------------------------------------------------------------------------- /WebUI/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import { createPinia } from 'pinia' 4 | import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' 5 | import { useI18N } from './assets/js/store/i18n' 6 | 7 | const app = createApp(App) 8 | app.use(createPinia()) 9 | const pinia = createPinia() 10 | pinia.use(piniaPluginPersistedstate) 11 | app.use(pinia) 12 | const i18n = useI18N() 13 | i18n.init().then(() => { 14 | const languages = i18n.state 15 | app.config.globalProperties.languages = languages 16 | app.provide('languages', languages) 17 | app.mount('#app') 18 | }) 19 | -------------------------------------------------------------------------------- /WebUI/src/toast.d.ts: -------------------------------------------------------------------------------- 1 | type ToastOptions = { 2 | mounted?: string | HTMLElement 3 | style?: ToastStyle 4 | settings?: ToastSettings 5 | } 6 | 7 | type ToastStyle = { 8 | main?: KVObject 9 | content?: KVObject 10 | } 11 | 12 | type ToastSettings = { 13 | duration: number 14 | } 15 | 16 | type ToastTransitions = { 17 | show: object 18 | hide: object 19 | } 20 | -------------------------------------------------------------------------------- /WebUI/src/views/AppSettings.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 77 | -------------------------------------------------------------------------------- /WebUI/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 3 | import Vue from 'vue' 4 | 5 | declare module 'vue' { 6 | interface ComponentCustomProperties { 7 | languages: StringKV 8 | } 9 | } 10 | 11 | declare module '*.vue' { 12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type 13 | const component: DefineComponent 14 | export default component 15 | } 16 | -------------------------------------------------------------------------------- /WebUI/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2023", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2023", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | /* Bundler mode */ 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "noEmit": true, 14 | "jsx": "preserve", 15 | /* Linting */ 16 | "strict": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noFallthroughCasesInSwitch": false, 20 | "paths": { 21 | "@": ["./src"], 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.d.ts", "electron"], 26 | "references": [ 27 | { 28 | "path": "./tsconfig.node.json" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /WebUI/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "types": ["vite/client", "node"] 10 | }, 11 | "include": ["vite.config.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /WebUI/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | import path from 'node:path' 3 | 4 | export default defineConfig({ 5 | test: { 6 | environment: 'node', 7 | include: ['**/*.test.ts'], 8 | exclude: ['node_modules', 'dist'], 9 | }, 10 | resolve: { 11 | alias: { 12 | '@': path.resolve(__dirname, './src'), 13 | electron: path.resolve(__dirname, './electron'), 14 | }, 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /backend-shared/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /backend-shared/__init__.py: -------------------------------------------------------------------------------- 1 | # Backend Shared Module 2 | # This module contains shared code for all backends 3 | -------------------------------------------------------------------------------- /backend-shared/interface.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Dict, List, Optional 3 | from params import LLMParams 4 | 5 | class LLMInterface(ABC): 6 | """ 7 | Abstract interface for LLM backends. 8 | 9 | This interface defines the common methods that all LLM backends must implement: 10 | - Default (IPEX) 11 | - LlamaCPP 12 | - OpenVINO 13 | """ 14 | stop_generate: bool 15 | _model: Optional[object] 16 | 17 | @abstractmethod 18 | def load_model(self, params: LLMParams, **kwargs): 19 | """ 20 | Load the model with the given parameters. 21 | 22 | Args: 23 | params: LLM parameters including model_repo_id, device, etc. 24 | **kwargs: Additional backend-specific parameters 25 | """ 26 | pass 27 | 28 | @abstractmethod 29 | def unload_model(self): 30 | """ 31 | Unload the model and free resources. 32 | """ 33 | pass 34 | 35 | @abstractmethod 36 | def create_chat_completion(self, messages: List[Dict[str, str]]): 37 | """ 38 | Generate a chat completion for the given messages. 39 | 40 | Args: 41 | messages: List of message dictionaries with "role" and "content" keys 42 | """ 43 | pass 44 | 45 | @abstractmethod 46 | def get_backend_type(self): 47 | """ 48 | Get the type of the backend. 49 | 50 | Returns: 51 | String identifier for the backend type 52 | """ 53 | pass 54 | -------------------------------------------------------------------------------- /backend-shared/params.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, List, Optional 2 | 3 | class LLMParams: 4 | """ 5 | Unified parameters class for all LLM backends. 6 | 7 | This class contains all parameters needed for LLM inference across different backends: 8 | - Default (IPEX) 9 | - LlamaCPP 10 | - OpenVINO 11 | """ 12 | prompt: List[Dict[str, str]] 13 | device: int 14 | model_repo_id: str 15 | max_tokens: int 16 | external_rag_context: Optional[str] 17 | print_metrics: bool 18 | generation_parameters: Dict[str, Any] 19 | 20 | def __init__( 21 | self, prompt: list, device: int, model_repo_id: str, 22 | max_tokens: int, external_rag_context: Optional[str] = None, 23 | print_metrics: bool = True, 24 | **kwargs 25 | ) -> None: 26 | """ 27 | Initialize LLM parameters. 28 | 29 | Args: 30 | prompt: List of prompt dictionaries with "question" and optionally "answer" keys 31 | device: Device ID to run inference on 32 | model_repo_id: Model repository ID or path 33 | max_tokens: Maximum number of tokens to generate 34 | external_rag_context: Optional context from external RAG system 35 | print_metrics: Whether to print performance metrics 36 | **kwargs: Additional generation parameters passed to the model 37 | """ 38 | self.prompt = prompt 39 | self.device = device 40 | self.model_repo_id = model_repo_id 41 | self.max_tokens = max_tokens 42 | self.external_rag_context = external_rag_context 43 | self.print_metrics = print_metrics 44 | self.generation_parameters = kwargs 45 | -------------------------------------------------------------------------------- /device-service/xpu-smi.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/device-service/xpu-smi.exe -------------------------------------------------------------------------------- /device-service/xpum.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/device-service/xpum.dll -------------------------------------------------------------------------------- /service/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | models/llm/ 4 | models/stable_diffusion/* 5 | !models/stable_diffusion/ESRGAN/ 6 | !models/stable_diffusion/preview/ 7 | temp/ 8 | static/* 9 | !static/assets/ 10 | test/ 11 | dist/ 12 | build/ 13 | cache/ 14 | db/ 15 | test/ 16 | env/ 17 | 18 | !tools/*.exe 19 | -------------------------------------------------------------------------------- /service/build_dowloader.bat: -------------------------------------------------------------------------------- 1 | pyinstaller -F downloader.py -n model_info.exe ^ 2 | --exclude-module scipy ^ 3 | --exclude-module sqlite3 ^ 4 | --exclude-module tensorflow ^ 5 | --exclude-module _tkinter ^ 6 | --exclude-module nltk ^ 7 | --exclude-module torch ^ 8 | --exclude-module sklearn ^ 9 | --exclude-module numpy ^ 10 | --exclude-module PIL ^ 11 | --exclude-module jinja2 -------------------------------------------------------------------------------- /service/exceptions.py: -------------------------------------------------------------------------------- 1 | class DownloadException(Exception): 2 | url: str 3 | 4 | def __init__(self, url: str): 5 | super().__init__(f"download {url} failed") 6 | -------------------------------------------------------------------------------- /service/llm_adapter.py: -------------------------------------------------------------------------------- 1 | from model_downloader import NotEnoughDiskSpaceException, DownloadException 2 | from psutil._common import bytes2human 3 | import llm_biz 4 | from service_adapter import ServiceAdapter 5 | 6 | class LLM_SSE_Adapter(ServiceAdapter): 7 | """ 8 | Adapter for the default service backend. 9 | This class extends ServiceAdapter to maintain backward compatibility. 10 | """ 11 | 12 | def error_callback(self, ex: Exception): 13 | """ 14 | Extended error callback with additional error types specific to the service backend. 15 | """ 16 | if ( 17 | isinstance(ex, NotImplementedError) 18 | and ex.__str__() == "Access to repositories lists is not implemented." 19 | ): 20 | self.put_msg( 21 | { 22 | "type": "error", 23 | "err_type": "repositories_not_found", 24 | } 25 | ) 26 | elif isinstance(ex, NotEnoughDiskSpaceException): 27 | self.put_msg( 28 | { 29 | "type": "error", 30 | "err_type": "not_enough_disk_space", 31 | "need": bytes2human(ex.requires_space), 32 | "free": bytes2human(ex.free_space), 33 | } 34 | ) 35 | elif isinstance(ex, DownloadException): 36 | self.put_msg({"type": "error", "err_type": "download_exception"}) 37 | elif isinstance(ex, llm_biz.StopGenerateException): 38 | pass 39 | else: 40 | # Fall back to the base implementation for other error types 41 | super().error_callback(ex) 42 | -------------------------------------------------------------------------------- /service/main.py: -------------------------------------------------------------------------------- 1 | # Load model directly 2 | from threading import Thread 3 | import time 4 | import traceback 5 | import torch 6 | from transformers import pipeline, PreTrainedModel, TextIteratorStreamer 7 | 8 | def stream_chat_generate(model: PreTrainedModel, args: dict): 9 | try: 10 | print("generate start") 11 | start = time.time() 12 | model.generate(**args) 13 | end = time.time() 14 | print(f"generate finish. cost {end-start}s") 15 | except Exception: 16 | traceback.print_exc() 17 | 18 | 19 | if __name__ == "__main__": 20 | pipe = pipeline( 21 | "text-generation", 22 | model="microsoft/Phi-3-mini-4k-instruct", 23 | torch_dtype=torch.bfloat16, 24 | ) 25 | 26 | # We use the tokenizer's chat template to format each message - see https://huggingface.co/docs/transformers/main/en/chat_templating 27 | messages = [ 28 | { 29 | "role": "system", 30 | "content": "You are a friendly chatbot who always responds in the style of a pirate", 31 | }, 32 | { 33 | "role": "user", 34 | "content": "How many helicopters can a human eat in one sitting?", 35 | }, 36 | ] 37 | pipe.model.eval() 38 | pipe.model.to("xpu") 39 | model = ipex.optimize(pipe.model, dtype=torch.bfloat16) 40 | prompt = pipe.tokenizer.apply_chat_template( 41 | messages, tokenize=False, add_generation_prompt=True, return_tensors="pt" 42 | ) 43 | encoding = pipe.tokenizer.encode_plus(prompt, return_tensors="pt").to("xpu") 44 | tensor: torch.Tensor = encoding.get("input_ids") 45 | streamer = TextIteratorStreamer( 46 | pipe.tokenizer, 47 | skip_prompt=False, # skip prompt in the generated tokens 48 | skip_special_tokens=True, 49 | ) 50 | generate_kwargs = dict( 51 | inputs=tensor, 52 | streamer=streamer, 53 | num_beams=1, 54 | do_sample=True, 55 | max_new_tokens=256, 56 | temperature=0.7, 57 | top_k=50, 58 | top_p=0.95, 59 | ) 60 | torch.xpu.synchronize() 61 | Thread(target=stream_chat_generate, args=(pipe.model, generate_kwargs)).start() 62 | 63 | for stream_output in streamer: 64 | print(stream_output, end="") 65 | print() 66 | -------------------------------------------------------------------------------- /service/model_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "llm": "./models/llm/checkpoints", 3 | "ggufLLM": "./models/llm/gguf", 4 | "openvinoLLM": "./models/llm/openvino", 5 | "stableDiffusion": "./models/stable_diffusion/checkpoints", 6 | "lora": "./models/stable_diffusion/lora", 7 | "vae": "./models/stable_diffusion/vae", 8 | "sampler": "./models/stable_diffusion/sampler", 9 | "ESRGAN":"./models/ESRGAN/RealESRGAN/RealESRGAN_x2plus.pth", 10 | "ipexLLMEmbedding": "./models/embedding/ipexLLM" 11 | } 12 | -------------------------------------------------------------------------------- /service/models/stable_diffusion/ESRGAN/RealESRGAN_x2plus.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/ESRGAN/RealESRGAN_x2plus.pth -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesd/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "_class_name": "AutoencoderTiny", 3 | "_diffusers_version": "0.20.0.dev0", 4 | "act_fn": "relu", 5 | "decoder_block_out_channels": [ 6 | 64, 7 | 64, 8 | 64, 9 | 64 10 | ], 11 | "encoder_block_out_channels": [ 12 | 64, 13 | 64, 14 | 64, 15 | 64 16 | ], 17 | "force_upcast": false, 18 | "in_channels": 3, 19 | "latent_channels": 4, 20 | "latent_magnitude": 3, 21 | "latent_shift": 0.5, 22 | "num_decoder_blocks": [ 23 | 3, 24 | 3, 25 | 3, 26 | 1 27 | ], 28 | "num_encoder_blocks": [ 29 | 1, 30 | 3, 31 | 3, 32 | 3 33 | ], 34 | "out_channels": 3, 35 | "scaling_factor": 1.0, 36 | "upsampling_scaling_factor": 2 37 | } 38 | -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesd/diffusion_pytorch_model.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesd/diffusion_pytorch_model.safetensors -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesd/taesd_decoder.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesd/taesd_decoder.safetensors -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesd/taesd_encoder.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesd/taesd_encoder.safetensors -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesdxl/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "_class_name": "AutoencoderTiny", 3 | "_diffusers_version": "0.20.0.dev0", 4 | "act_fn": "relu", 5 | "decoder_block_out_channels": [ 6 | 64, 7 | 64, 8 | 64, 9 | 64 10 | ], 11 | "encoder_block_out_channels": [ 12 | 64, 13 | 64, 14 | 64, 15 | 64 16 | ], 17 | "force_upcast": false, 18 | "in_channels": 3, 19 | "latent_channels": 4, 20 | "latent_magnitude": 3, 21 | "latent_shift": 0.5, 22 | "num_decoder_blocks": [ 23 | 3, 24 | 3, 25 | 3, 26 | 1 27 | ], 28 | "num_encoder_blocks": [ 29 | 1, 30 | 3, 31 | 3, 32 | 3 33 | ], 34 | "out_channels": 3, 35 | "scaling_factor": 1.0, 36 | "upsampling_scaling_factor": 2 37 | } 38 | -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesdxl/diffusion_pytorch_model.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesdxl/diffusion_pytorch_model.safetensors -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesdxl/taesdxl_decoder.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesdxl/taesdxl_decoder.safetensors -------------------------------------------------------------------------------- /service/models/stable_diffusion/preview/madebyollin---taesdxl/taesdxl_encoder.safetensors: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/models/stable_diffusion/preview/madebyollin---taesdxl/taesdxl_encoder.safetensors -------------------------------------------------------------------------------- /service/real_esrgan_patch.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def patch_import(file_path): 5 | # Read the file 6 | with open(file_path, "r") as file: 7 | lines = file.readlines() 8 | 9 | # Patch the import line 10 | with open(file_path, "w") as file: 11 | for line in lines: 12 | # Replace the old import line with the new one 13 | if ( 14 | "from torchvision.transforms.functional_tensor import rgb_to_grayscale" 15 | in line 16 | ): 17 | line = line.replace( 18 | "from torchvision.transforms.functional_tensor import rgb_to_grayscale", 19 | "from torchvision.transforms.functional import rgb_to_grayscale", 20 | ) 21 | file.write(line) 22 | 23 | print(f"Patched {file_path} successfully.") 24 | 25 | 26 | if __name__ == "__main__": 27 | if len(sys.argv) != 2: 28 | print("Usage: python patch_import.py ") 29 | sys.exit(1) 30 | 31 | file_path = sys.argv[1] 32 | patch_import(file_path) 33 | -------------------------------------------------------------------------------- /service/requirements-ipex-llm.txt: -------------------------------------------------------------------------------- 1 | --extra-index-url https://download.pytorch.org/whl/xpu 2 | 3 | ipex-llm[xpu_2.7]==2.3.0b20250426.post0 4 | -------------------------------------------------------------------------------- /service/requirements-xpu.txt: -------------------------------------------------------------------------------- 1 | --extra-index-url https://download.pytorch.org/whl/xpu 2 | torch==2.7.0+xpu 3 | torchvision==0.22.0+xpu 4 | torchaudio==2.7.0+xpu 5 | -------------------------------------------------------------------------------- /service/requirements.txt: -------------------------------------------------------------------------------- 1 | basicsr==1.4.2 2 | compel==2.0.3 3 | datasets==2.18.0 4 | diffusers==0.27.2 5 | Flask==3.1.0 6 | apiflask==2.3.2 7 | marshmallow-dataclass==8.7.1 8 | langchain_community==0.3.0 9 | numpy==1.26.4 10 | opencv_python==4.11.0.86 11 | peft==0.10.0 12 | Pillow==11.1.0 13 | psutil==7.0.0 14 | Requests==2.32.3 15 | sentence_transformers==2.3.1 16 | transformers==4.48.0 17 | trl==0.9.3 18 | faiss-cpu==1.8.0 19 | docx2txt==0.8 20 | pypdf==5.3.1 21 | unstructured==0.17.0 22 | setuptools>=76.0.0 23 | huggingface_hub==0.25.2 24 | -------------------------------------------------------------------------------- /service/service_adapter.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | import llm_biz 4 | from params import LLMParams 5 | from adapter import BaseAdapter 6 | 7 | class ServiceAdapter(BaseAdapter): 8 | """Adapter for the default service backend.""" 9 | 10 | def __init__(self, external_rag_context=None): 11 | """Initialize the adapter with optional RAG parameters.""" 12 | super().__init__() 13 | self.metrics_data = None 14 | self.external_rag_context = external_rag_context 15 | 16 | def metrics_callback(self, msg: dict): 17 | """Callback for metrics data.""" 18 | self.metrics_data = msg 19 | 20 | def text_conversation_run(self, params: LLMParams): 21 | """Run the text conversation using llm_biz. 22 | 23 | Args: 24 | params: LLM parameters 25 | """ 26 | try: 27 | # Set RAG context and source on the params object if provided 28 | if self.external_rag_context is not None: 29 | params.external_rag_context = self.external_rag_context 30 | 31 | llm_biz.chat( 32 | params=params, 33 | load_model_callback=self.load_model_callback, 34 | text_out_callback=self.text_out_callback, 35 | error_callback=self.error_callback, 36 | metrics_callback=self.metrics_callback, 37 | ) 38 | self.put_msg(self.metrics_data) 39 | self.put_msg({"type": "finish"}) 40 | 41 | except Exception as ex: 42 | traceback.print_exc() 43 | self.error_callback(ex) 44 | finally: 45 | self.finish = True 46 | self.signal.set() 47 | -------------------------------------------------------------------------------- /service/service_config.py: -------------------------------------------------------------------------------- 1 | # Import shared configuration from backend-shared 2 | import config 3 | 4 | # Re-export all configuration from the shared module 5 | service_model_paths = config.service_model_paths 6 | comfy_ui_root_path = config.comfy_ui_root_path 7 | git = config.git 8 | comfyui_python_exe = config.comfyui_python_exe 9 | comfyui_python_env = config.comfyui_python_env 10 | comfy_ui_model_paths = config.comfy_ui_model_paths 11 | llama_cpp_model_paths = config.llama_cpp_model_paths 12 | openvino_model_paths = config.openvino_model_paths 13 | device = config.device 14 | 15 | # Re-export the convert_model_type function 16 | convert_model_type = config.convert_model_type 17 | -------------------------------------------------------------------------------- /service/static/assets/aipg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/static/assets/aipg.png -------------------------------------------------------------------------------- /service/static/assets/history.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #181524; 3 | padding: 40px 20px; 4 | color: #fff; 5 | font-size: 16px; 6 | line-height: 150%; 7 | font-family: "Micorsoft YaHei", Arial, Helvetica, sans-serif; 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | } 12 | 13 | .history-list { 14 | display: flex; 15 | flex-direction: column; 16 | gap: 20px; 17 | } 18 | *{ 19 | padding: 0px; 20 | margin: 0px; 21 | box-sizing: border-box; 22 | } 23 | .history-list > li { 24 | display: flex; 25 | padding: 12px; 26 | border: 1px solid #666; 27 | } 28 | 29 | 30 | .result-img { 31 | align-self: stretch; 32 | flex: 1 1 auto; 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | padding-right: 8px; 37 | } 38 | 39 | .result-img img { 40 | max-width: 700px; 41 | height: 400px; 42 | } 43 | 44 | .params { 45 | width: 700px; 46 | flex: none; 47 | display: flex; 48 | flex-direction: column; 49 | gap: 8px; 50 | 51 | border-left: 1px solid #666; 52 | } 53 | 54 | .params > li { 55 | display: flex; 56 | align-items: top; 57 | gap: 8px; 58 | padding-left: 8px; 59 | } 60 | .params > li:nth-last-child(n + 1) { 61 | border-bottom: 1px solid #666; 62 | } 63 | 64 | .param-name { 65 | width: 140px; 66 | line-height: 200%; 67 | font-weight: bold; 68 | flex: none; 69 | } 70 | 71 | .param-value { 72 | flex: 1 1 auto; 73 | word-break: break-all; 74 | } 75 | 76 | a{ 77 | color: rgb(59 130 246); 78 | } -------------------------------------------------------------------------------- /service/static/assets/history.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | html = ""; 3 | for (let i = 0; i < history.length; i++) { 4 | let item = history[i]; 5 | html += `
    • `; 6 | for (let j = 0; j < item.params.length; j++) { 7 | let param = item.params[j]; 8 | if (param.type == "image") { 9 | pos = param.value.lastIndexOf("/"); 10 | filename = pos > -1 ? param.value.substring(pos + 1) : param.value; 11 | html += `
    • ${param.name}${filename}
    • `; 12 | } else { 13 | html += `
    • ${param.name}${param.value}
    • `; 14 | } 15 | } 16 | html += "
  • "; 17 | } 18 | document.querySelector(".history-list").innerHTML = html; 19 | }); 20 | -------------------------------------------------------------------------------- /service/static/assets/history_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generate History 5 | 6 | 7 | 8 | 9 | 10 |
      11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /service/tools/ls_level_zero.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace sycl; 5 | 6 | int main() { 7 | std::cout << "["; 8 | unsigned int id = 0; 9 | for (const auto &plt : platform::get_platforms()) { 10 | if (plt.get_backend() != backend::ext_oneapi_level_zero) 11 | continue; 12 | 13 | for (const auto &dev : plt.get_devices()) { 14 | if (id > 0) 15 | std::cout << ", "; 16 | std::string name = dev.get_info(); 17 | std::cout << "{\"id\": " << id << ", \"name\": \"" << name << "\""; 18 | if (dev.has(aspect::ext_intel_device_id)) { 19 | int device_id = dev.get_info(); 20 | std::cout << ", \"device_id\": " << device_id; 21 | } 22 | std::cout << "}"; 23 | id++; 24 | } 25 | } 26 | std::cout << "]" << std::endl; 27 | } 28 | -------------------------------------------------------------------------------- /service/tools/ls_level_zero.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/AI-Playground/98b89a31c15e778e2dd4af977fa4b1267da41586/service/tools/ls_level_zero.exe -------------------------------------------------------------------------------- /service/tools/move_model_files.py: -------------------------------------------------------------------------------- 1 | # To be invoked by installer 2 | # Usage: python move_model_files.py 3 | 4 | import os 5 | import sys 6 | 7 | 8 | if len(sys.argv) != 3: 9 | print("Usage: python move_model_files.py ") 10 | sys.exit(1) 11 | 12 | 13 | src_dir = sys.argv[1] 14 | target_dir = sys.argv[2] 15 | if not os.path.exists(src_dir): 16 | print("Backup model directory does not exist: " + src_dir) 17 | sys.exit(1) 18 | if not os.path.exists(target_dir): 19 | os.makedirs(target_dir) 20 | 21 | 22 | log_file = os.path.join(target_dir, "copy.log") 23 | if os.path.exists(log_file): 24 | os.remove(log_file) 25 | 26 | 27 | def log(msg): 28 | print(msg) 29 | with open(log_file, "a") as f: 30 | f.write(msg + "\n") 31 | 32 | 33 | def move_model_files(src_dir, target_dir): 34 | try: 35 | # for each file in src_dir, move it to target_dir if target path does not exist 36 | # otherwise, remove the target file and move the backup file to target path 37 | for root, dirs, files in os.walk(src_dir): 38 | for file in files: 39 | src_file = os.path.join(root, file) 40 | target_file = src_file.replace(src_dir, target_dir) 41 | if os.path.exists(target_file): 42 | os.remove(target_file) 43 | log(f"Removed existing {target_file}") 44 | tdir = os.path.dirname(target_file) 45 | if not os.path.exists(tdir): 46 | os.makedirs(tdir) 47 | os.rename(src_file, target_file) 48 | log(f"Moved {src_file} to {target_file}") 49 | except Exception as e: 50 | log("Failed to recover model files: " + str(e)) 51 | sys.exit(1) 52 | 53 | 54 | move_model_files(src_dir, target_dir) 55 | -------------------------------------------------------------------------------- /service/web_request_bodies.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | import marshmallow_dataclass 4 | from marshmallow import EXCLUDE 5 | 6 | 7 | @marshmallow_dataclass.dataclass 8 | class DownloadModelData: 9 | class Meta: 10 | unknown = EXCLUDE 11 | type : int 12 | repo_id : str 13 | backend : str 14 | additionalLicenseLink: Optional[str] 15 | 16 | @marshmallow_dataclass.dataclass 17 | class DownloadModelRequestBody: 18 | data : List[DownloadModelData] 19 | 20 | @marshmallow_dataclass.dataclass 21 | class ComfyUICustomNodesGithubRepoId: 22 | username: str 23 | repoName: str 24 | gitRef: Optional[str] 25 | 26 | @marshmallow_dataclass.dataclass 27 | class ComfyUICustomNodesDownloadRequest: 28 | data : List[ComfyUICustomNodesGithubRepoId] 29 | 30 | @marshmallow_dataclass.dataclass 31 | class ComfyUICheckWorkflowRequirementRequest: 32 | pythonPackages : List[str] 33 | customNodes : List[ComfyUICustomNodesGithubRepoId] 34 | 35 | @marshmallow_dataclass.dataclass 36 | class ComfyUIPackageInstallRequest: 37 | data : List[str] 38 | --------------------------------------------------------------------------------